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
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).
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
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
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]
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
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.
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.
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.