Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

January 28, 2008 / by Zsolt Soczó

SQL Server 2008 újdonságok 18. – térbeli adattípusok 5.

Pár metódus még a geometry típushoz, aztán tényleg jönnek a valódi adatok és számítások.

A példáim eddig a geometry típusra építettek, azt könnyebb kezelni, de a metódusok jelentős része értelmezhető lesz a geograpy típuson is. Ha nem ebben a CTP-ben, majd a következőben (CTP6 pre-t már le tudnék tölteni mint MVP, de várok pár napot a végleges CTP-re, ne kelljen állandóan telepíteni). Nem mindent lehet viszont egy gömbön értelmezni, ezért nem teljesen azonos a két típus metóduskészlete, de erről majd később.

Csak ízelítőül, sík tartomány esetén (geometry) triviális értelmezni a kívül és a belül fogalmát, amelyik tartomány véges, az van belül. És egy gömbön? Ott mindkét tartomány véges. Akkor, most mi nézzük a majmokat az állatkertben, vagy ők néznek minket? Ezt a kérdést is elrendezzük majd. Ezeket csak azért mondom, hogy ne csüggedjen senki a sok metódus láttán, kellenek majd ezek.

Távolság meghatározás: STDistance. Ez egy pont és egy teszőleges alakzat között keresi meg a legrövidebb utat. Geometrynél ennek nincs mértékegysége, geograpy esetén pedig az SRID-től függ, mi lesz ez, sok esetben például fokban kapjuk meg a távolságot (hisz a geograpy szélesség-hosszúsággal dolgozik).
A példában még látható a STLength, az az alakzat körvonalának hosszát adja vissza (pl. egy ország kerülete).

DECLARE @g geometry;
DECLARE @h geometry;
DECLARE @i geometry;
SET @g = geometry::STGeomFromText('POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))', 0);
SET @h = geometry::STGeomFromText('POINT(10 10)', 0);
SET @i = geometry::STGeomFromText('LINESTRING(2 2,10 10)', 0);
SELECT @g, @g.STDistance(@h), 0.1 as [Thickness], 'Green' as [Color]
UNION ALL
SELECT @i, @i.STLength(), 0.1 as [Thickness], 'Gray' as [Color] -- demonstration line
UNION ALL 
SELECT @h, null, 0.3 as [Thickness], 'Red' as [Color];
POLYGON ((0 0, 2 0, 2 2, 0 2,  11.3137084989848       0.1                            Green
LINESTRING (2 2, 10 10)        11.3137084989848       0.1                            Gray
POINT (10 10)                  NULL                   0.3                            Red

stlengthstdistance.png

Befoglaló téglalap meghatározása: STEnvelope. Ezt könnyű elképzelni, nem mellékelek képet, csak a kimenetet:

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('LINESTRING(0 0, 2 3)', 0);
SELECT @g, @g.STEnvelope(), 0.1 as [Thickness];
LINESTRING (0 0, 2 3)                    POLYGON ((0 0, 2 0, 2 3, 0 3, 0 0))

Egyenlő-e két alakzat? STEquals. Azt gondolnánk ez egyszerű, de lehet, hogy másként vannak összerakva. Pl. egy sokszöget össze lehet rakni multi-lineként, aminek az első és utolsó pontja ugyanaz és polygonként is. A függvény észreveszi az ilyen csibészségeket.

DECLARE @g geometry
DECLARE @h geometry;
SET @g = geometry::STGeomFromText('LINESTRING(0 2, 2 0, 4 2)', 0);
SET @h = geometry::STGeomFromText('MULTILINESTRING((4 2, 2 0), (0 2, 2 0))', 0);
SELECT @h, @h.STEquals(@g), 'Blue' as [Color], 0.2 as [Thickness]
UNION ALL
SELECT @g, @g.STEquals(@h), 'Orange' as [Color], 0.1 as [Thickness];
MULTILINESTRING ((4 2, 2 0), (0 2, 2 0)) 1
LINESTRING (0 2, 2 0, 4 2)               1

A példából látszik, hogy a művelet kommutatív (még szép).

stequals.png

Külső körvonal meghatározása: STExteriorRing. A korábbi lukas négyzetes példában a külső négyzetet adja vissza. Ha egy épületegyüttes van például poligonok kollekciójaként leírva, akkor ezzel könnyű meghatározni az együttes körvonalukat. Az STInteriorRingN(n) kívülről befelé haladva az n. belső körvonalat adja vissza.

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0),(2 2, 2 1, 1 1, 1 2, 2 2))', 0);
SELECT @g, 0.3 as [Thickness], 'Red' as Color
UNION ALL
SELECT @g.STExteriorRing() AS [ExteriorRing], 0.1 as [Thickness], 'Yellow' as Color
UNION ALL
SELECT @g.STInteriorRingN(1) AS [FirstInteriorRing], 0.1 as [Thickness], 'Green' as Color;
POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (2 2, 2 1, 1 1, 1 2, 2 2))         0.3                            Red
LINESTRING (0 0, 3 0, 3 3, 0 3, 0 0)                                   0.1                            Yellow
LINESTRING (2 2, 2 1, 1 1, 1 2, 2 2)                                   0.1                            Green

stinteriorringnstexteriorring.png

STIsEmpty: ez olyan, mint a NULL. Itt egy alakzat lehetne, de nincs. Azaz olyan, mint az ISNULL, csak geo izékre.

STIsClosed: zárt-e az alakzat. Ha a kezdő és a végpont ugyanaz, akkor zárt.

STIsSimple: ha az alakzat nem metszi saját magát. Pl. a 8-as, az X vagy az A nem egyszerű alakzat. Az O vagy a D igen.

STIsRing: akkor gyűrű valami, ha zárt és egyszerű. Az O pl. gyűrű, de a D is, az A nem, mert nem zárt (kilóg a két lába) és nem is egyszerű (a vízszintes beleér a két lábába).

STOverlaps: átfedi-e egymást két alakzat, elég egyszerű értelmezni. Mozgó alakzatoknál ütközést érzékelni is jó. (Doom for SQL Server) :)

STPointOnSurface: visszaad egy tetszőleges pontot egy felület belsejében. Nem igazán tudom még mire lehet jó, de talán arra, hogy ha pl. egy épülethez képest kell mérni valami, de nem tudjuk hol vannak az ajtók, akkor kiválasztunk a belsejében egy tetszőleges pontot a függvénnyel, és onnan mérünk. Ha valaki ismeri a pontos célját, írja meg.

Update.

Megkérdeztem az MVP newsgroupban, az egyik SQL Server fejlesztő kolléga (Isaac Kunen) azt mondta, arra jó, hogy ha az alakzathoz egy címkét szeretnénk rajzolni, akkor egy ahhoz használható pozíciót ad vissza a metódus. Hmm.

És végül (tényleg elfogyak a metódusok?) egy nem szabványos kiegészítés: Reduce.
Ezzel le lehet egyszerűsíteni alakzatokat, hogy egyszerűen fogalmazva durvább legyen a felbontásuk.

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('LINESTRING(0 0, 0 1, 1 0, 2 1, 3 0, 4 1)', 0);
SELECT @g, 'Original' as [Display], 'Blue' AS [Color], 0.2 AS [Thickness]
UNION ALL
SELECT @g.Reduce(.75), 'Reduced' as [Display], 'Red' AS [Color], 0.1 AS [Thickness]
LINESTRING (0 0, 0 1, 1 0, 2 1, 3 0, 4 1)                              Original Blue  0.2
LINESTRING (0 0, 0 1, 3 0, 4 1)                                        Reduced  Red   0.1

reduce.png

A doksi szerint ő a Douglas-Peucker algoritmussal közelíti meg az eredeti alakzatot, a megadott paraméternek megfelelő agresszivitással. Gondolom akkor jön jól, ha egy számítás lassú lenne a finom felbontás mellett (pl. egy poligon 1500 darabkából), és ilyenkor a pontosság rovására, de egy mondjuk tizedére csökkentett oldalszámra egyszerűsített alakzattal számolunk. Érdemes megnézni, mit csinál egy körrel:

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('POINT(0 0)', 0).STBuffer(10);
SELECT @g, 'Original' as [Display], 'Blue' AS [Color], 1 AS [Thickness]
UNION ALL
SELECT @g.Reduce(.75), 'Reduced1' as [Display], 'Red' AS [Color], 0.2 AS [Thickness]
UNION ALL
SELECT @g.Reduce(2), 'Reduced2' as [Display], 'Yellow' AS [Color], 0.2 AS [Thickness]
UNION ALL
SELECT @g.Reduce(5), 'Reduced3' as [Display], 'Green' AS [Color], 0.2 AS [Thickness]

reduceacircle.png

Ez volt a kör négyszögesítése projekt.

No, még mindig nem érintettünk minden metódust, de a legfontosabbakat már láttuk. A következő részben letöltünk adatokat az országról és a környékéről, és elkezdünk méricskélni rajta. Ízelítőül megmutatom a környező országok kerületének és területének kiszámítását (Addig lehet ellenőrizni, jók-e az adatok? Románia területe nem gyanúsan nagy? ;)

select
CNTRY_NAME as 'Ország',
cast([geom].STArea() /1000 /1000 as int) as 'Terület [km2]',
cast([geom].STLength() /1000 as int) as 'Kerület [km]'
from Country
Ország                         Terület [km2] Kerület [km]
------------------------------ ------------- ------------
Byelarus                       1024          162
Poland                         139576        2068
Czech Republic                 54465         1303
Ukraine                        43739         1240
Germany                        3585          285
Slovakia                       48926         1207
Hungary                        92995         1562
Austria                        42468         966
Slovenia                       14000         651
Serbia                         76621         1614
Romania                        105365        1613
Bosnia and Herzegovina         51005         1173
Croatia                        52209         3009
Bulgaria                       19237         724
Montenegro                     7780          450

Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

LEAVE A COMMENT

3 COMMENTS

  • Szindbad January 28, 2008

    Kockat tud mar forgatni az SQL server? Phong shading? Antialiast kopi mar? :D

    Hatszoval akarhogy is probalok megbaratkozni, hogy az SQL serverem tud bennfoglalo teglalapot szamolni, valahogy nem megy. Ok, ertem en, hogy ez csak .NET tipusokon valo “batch” fuggvenyhivasoknak felel meg, de megis, nem akarodzik tetszeni nekem.

    Egyre jobban kezd olyan benyomasom lenni az egeszrol, hogy az SQL szerverbol egy altalanos algoritmus alkalmazas szervert keszitenek, amit ilyen szornyu szintatikaju felig tipusos felig nem, deklarativ script nyelvvel lehet programozni.

    Ne erts felre, remek dolog, hogy fel lehet tenni ilyen kerdeseket, amiket peldakent irtal, de mennyi ennek a relevanciaja? Hol terul meg az, hogy egy mukodo rendszert lecsereljunk az SQL server 2008 legujabb featureit kihasznalo megoldasra?

    Nem latom benne a perspektivat, de legyen ez az en szemelyes vaksagom.

  • Soczó Zsolt January 29, 2008

    Szerintem arra halad az sql server, amerre az oracle meg a kusztormerigények húzzák. Ha ott van rengeteg adat egy adatbázisszerverben, akkor logikus, hogy a rajtuk végezhető műveleteket szeretnék a közelébe vinni, mert sokkal hatékonyabban lehet helyben rajtuk dolgozni. Ezt látni fogod, amikor felindexelem a spatial adatokat.

    Az SQL Server egyre inkább nem csak adatbázis szerver, hanem alkalmazás szerver és platform. Az SQL 2005nél látszott ez már nagyon, a 2008 ebben az irányba megy tovább.

    A 2008ban számtalan új érték van, amiket majd igyekszek bemutatni, csak ez elég időigényes folyamat, de nyár elejére talán a végére érek. Addig a neten találsz már sok ifót róla, sok ponton fejlesztették, nem ilyen extra dolgokkal, mint a spatial, hanem alapokkal, mint végrehajtási terv fejlesztések, új index hint, stb. is.

  • Soczó Zsolt January 29, 2008

    Ps. Ja, és az ora tud kockát forgatni, videót szerkeszteni, benne keresni, stb. Állítólag. Ott ez nem furcsa, sőt, emiatt szeretik sokan jobban az SQL Servernél, ami az SQL 2000-ig “csak” egy adatbázismotor volt.