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 22, 2008 / by Zsolt Soczó

SQL Server 2008 újdonságok 16. – térbeli adattípusok 2.

Az előző rész végén volt egy kép, ami vizualizálta a geometriai alakzatokat. Ez a kis program a GeoQuery 2008, és rendkívül jó szolgálatot tesz megnézni, melyik függvény mire szolgál.

Ebben a részben bemutatok pár geometry metódust, szemérmetlenül ellopva a program beépített msdn példáit (köszönet a szerzőnek a feldolgozásért). Párat azért én is szültem. :)

A példákban a Thickness és a Color oszlopok csak a programnak szólnak, hogyan jelenítse meg az alakzatokat.

Területszámítás, STArea:

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, @g.STArea() as [AreaInUnits], 0.1 as [Thickness];
8

starea.png

Azaz van egy 3×3-as négyzetünk, amiben van egy 1×1-es luk. Így a területe 8, nem meglepő.

Határolóvonalak, STBoundary. Ez már nem teljesen triviális, a BOL sem segít egyelőre, csak a szabvány.

“-Point and MultiPoint instances do not have a boundary.
-LineString and MultiLineString boundaries are formed by the start points and end points, removing those that occur an even number of times.”
-The boundary of a Polygon consists of a set of LinearRings that make up its exterior and interior boundaries.”

DECLARE @g geometry;
SET @g = geometry::STPolyFromText('POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))', 10);
SELECT 'Red' Color, 0.2 as [Thickness], @g
union all
select 'Yellow' Color, 0.1 as [Thickness], @g.STBoundary()
POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))
MULTILINESTRING((1 1, 1 2, 2 1, 1 1), (0 0, 3 0, 0 3, 0 0))

stboundary1.png

A piros az alakzat, a sárga a határolóvonala. A kettő egybeesik, csak az irányuk más, ez a kimenetből látszik, illetve az egyik sokszög, a másik vonalak halmaza.

Ugyanez vonalakkal:

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

stboundary.png

Látszik, hogy a szabványnak megfelelő a kimenet.

STBuffer. Azokat a pontokat adja vissza, amelyek egy alakzattól a megadott távolságra, vagy annál közelebb fekszenek.
Egyszerű vonallal:

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('LINESTRING(0 0, 4 0)', 0);
SELECT @g, @g.STBuffer(1), 0.1 as [Thickness];
Marha sok pontból álló POLYGON.

stbuffer1.png

Bonyolultabb sokszöggel:

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))', 0);
SELECT @g, 0.1 as [Thickness], 'Red' as Color
union all 
select @g.STBuffer(1), 0.1 as [Thickness], 'Yellow' as Color;
Marha sok pontból álló POLYGON.

stbuffer2.png

A sárga vonal a számított Buffer.

Középpont számítás, STCentroid. Matekosok utánakereshetnek, hogy számolják (érdekelne a link).

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, @g.STCentroid(), 0.1 as [Thickness];
POINT(1.5 1.5)

stcentroid1.png

Ez könnyű volt. Bonyolultabb alakzatra meg majd kiszámolja a gép. :)

Tartalmazza-e az egyik alakzat a másikat (teljesen), STContains:

DECLARE @g geometry;
DECLARE @h geometry;
SET @g = geometry::STGeomFromText('POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))', 0);
SET @h = geometry::STGeomFromText('POINT(1 1)', 0);
SELECT @g, @h, @g.STContains(@h), 0.1 as [Thickness];
1

Azt mondja, benne van, meglepő. Képet most nem mellékelek, láttunk már ilyen négyzetet.

Konkávból konvex, STConvexHull:

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('POLYGON((0 0, 0 2, 1 1, 2 2, 2 0, 0 0))', 0);
SELECT @g, 'Original' AS [Display], 'Blue' as [Color], 0.2 as [Thickness]
UNION ALL
SELECT @g.STConvexHull(), 'Hull', 'Green' as [Color], 0.1 as [Thickness];

stconvexhull1.png

A kék az eredeti, az zöld a kiegyengetett, konvexesített.

Metszi-e egymást két alakzat? STCrosses.

DECLARE @g geometry;
DECLARE @h geometry;
SET @g = geometry::STGeomFromText('LINESTRING(0 2, 2 0)', 0);
SET @h = geometry::STGeomFromText('LINESTRING(0 0, 2 2)', 0);
SELECT @g, @h, @g.STCrosses(@h), 0.1 as [Thickness];
1

Különbségképzés, azok határolópontok által bekerített terület az egyik alakzatból, amelyek nincsenek benne egy másikban: STDifference.

DECLARE @g geometry;
DECLARE @h geometry;
SET @g = geometry::STGeomFromText('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))', 0);
SET @h = geometry::STGeomFromText('POLYGON((1 1, 3 1, 3 3, 1 3, 1 1))', 0);
SELECT 'Original Polygons' as [Display], @g, @h, 'Green' as [Color],  0.2 as [Thickness]
UNION ALL
SELECT 'First minus second', null, @g.STDifference(@h), 'Blue' as [Color], 0.1 as [Thickness]
UNION ALL
SELECT 'Second minus first', null, @h.STDifference(@g), 'Orange' as [Color], 0.05 as [Thickness];
Original Polygons  POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))      POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))      Green  0.20
First minus second NULL                                     POLYGON ((0 0, 2 0, 2 1, 1 1, 1 2, 0 2,  Blue   0.10
Second minus first NULL                                     POLYGON ((2 1, 3 1, 3 3, 1 3, 1 2, 2 2,  Orange 0.05

stdifference.png

Jópofa. Az alsó zöld négyzet az egyik alakzatunk, a felső zöld a másik. A kék azt mutatja, ha az alsóból kivonjuk a felsőt, a sárga, ha a felsőből az alsót.

Folyt. köv.

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

8 COMMENTS

  • Szindbad January 22, 2008

    Ertem. De mi a fenere jo mindez?

  • Kurbli January 22, 2008

    Na jó. Ez mind síkbeli példa volt. Milyen a térbeli?

  • Soczó Zsolt January 22, 2008

    Mire jók ezek? Térképeken objektumok között keresgélni, navigálni. Előbb-utóbb oda is eljutok. :)

  • Soczó Zsolt January 22, 2008

    Kurbli: eddigi tudásom alapján nincs valódi térbeli típus, csak derékszögű és elliptikus. Lehet, hogy rosszul fordítottam a spatial szót a címben. :)

  • Soczó Zsolt January 22, 2008

    Szindbad: http://www.directionsmag.com/editorials.php?article_id=2477&trv=1

    Egy étteremkereső lekérdezés a fenti cikkből:

    -Return Census Block regions with the count of restaurants
    -contained in each region for each block group in the zipcode the user clicked on

    DECLARE @clickedPoint dbo.Geometry;
    SET @clickedPoint = dbo.Geometry::STPoint(@lat, @lon, 0);
    SELECT c.id,
    c.shape,
    c.pop as [Population],
    c.shape.STArea() as [Area],
    (select count(*) from dbo.business b where c.shape.STIntersects(b.shape)=1
    AND substring(sic,1,2)=’58’) as [Restaurant Count]
    FROM dbo.census c, dbo.zipcodes z
    WHERE c.shape.STIntersects(z.shape)=1 and z.shape.STIntersects(@clickedPoint)=1;

  • Szindbad January 23, 2008

    Es ennek mennyi relevanciaja van? Megeri igyelbonyolitani az SQL szervert? Vagy verszemet kaptak, es a C++ mintajara minden letezo featurrel teletomik, hogy aztan evek mulva visszaterjenek az “egyparadigmas” SQL nyelvhez?

  • Soczó Zsolt January 23, 2008

    Nem sokat bonyolít ez, egyszerűen egy új típust adtak hozzá, jó, az optimizer pár metódus esetén segít, meg indexet is írtak hozzá.

    Oracle-ösödik az SQL Server, gondolom ott már rég van ilyen.