MSSQL Spatial Çizgi İle Hat Kırma
By: Ömer Uygun
Tags: Cutting, Line, Spatial, Mssql

Aşağıdaki kod ile bir hat başka bir hat ile iki parçaya bölünebilir.

USE [AKMERCAN]

GO

/****** Object: UserDefinedFunction [dbo].[STSplitLine] Script Date: 26.02.2021 11:58:44 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

ALTER function [dbo].[STSplitLine](@orjLineString nvarchar(MAX),@cutGeomString nvarchar(MAX),@srid int)

returns nvarchar(MAX)

as

begin

declare @cutGeom geometry;

declare @orjGeom geometry;

declare @intersectionGeom geometry;

declare @nodeCount int=0;

declare @i int=1;

declare @intersectedNodeIndex int=-1;

declare @newLine nvarchar(MAX)='';

declare @line1 nvarchar(MAX)='';

declare @line2 nvarchar(MAX)='';

declare @returnData nvarchar(MAX)='';

declare @geom1 geometry;

declare @geom2 geometry;

declare @segmentIndex int =0;

declare @tmpLine nvarchar(MAX);

declare @cur cursor;

declare @tbl_segments table(

StartPoint geometry,

EndPoint geometry,

NewPoint geometry,

Segment geometry,

SegmentIndex int

);

Set @orjGeom=geometry::STGeomFromText(@orjLineString,@srid);

set @cutGeom=geometry::STGeomFromText(@cutGeomString,@srid);

Set @intersectionGeom=@orjGeom.STIntersection(@cutGeom);

if @intersectionGeom.STGeometryType()='MultiPoint' begin

set @returnData='{Status:false,StatusMessage:"Çiziminiz kırmak istediğiniz hattın birden fazla noktası ile kesişiyor",Line1Wkt:"'+@line1+'",Line2Wkt:"'+@line2+'"}';

return @returnData;

end;

if @orjGeom.STStartPoint().STIntersects(@intersectionGeom.STBuffer(0.001))=1 begin

set @returnData='{Status:false,StatusMessage:"Kırmak istediğiniz hattın başlangıç noktasından kıramazsınız..",Line1Wkt:"'+@line1+'",Line2Wkt:"'+@line2+'"}';

return @returnData;

end;

if @orjGeom.STEndPoint().STIntersects(@intersectionGeom.STBuffer(0.001))=1 begin

set @returnData='{Status:false,StatusMessage:"Kırmak istediğiniz hattın bitiş noktasından kıramazsınız..",Line1Wkt:"'+@line1+'",Line2Wkt:"'+@line2+'"}';

return @returnData;

end;

Set @nodeCount=@orjGeom.STNumPoints ();

set @i=1;

while (@i<@nodeCount)

begin

insert into @tbl_segments(StartPoint,EndPoint,Segment,SegmentIndex)

Values(@orjGeom.STPointN(@i),

@orjGeom.STPointN(@i+1),

geometry::STGeomFromText('LINESTRING('+STR(@orjGeom.STPointN(@i).STX,18,8)+' '+STR(@orjGeom.STPointN(@i).STY,18,8)+','+STR(@orjGeom.STPointN(@i+1).STX,18,8)+' '+STR(@orjGeom.STPointN(@i+1).STY,18,8)+')',@srid),

@i);

set @i=@i+1;

end;

select @segmentIndex=t.SegmentIndex from @tbl_segments t where t.Segment.STBuffer(0.01).STIntersects(@intersectionGeom)=1;

if (Select Count(*) from @tbl_segments t

where t.SegmentIndex=@segmentIndex

and (t.StartPoint.STBuffer(0.1).STIntersects(@intersectionGeom)=1 or t.EndPoint.STBuffer(0.1).STIntersects(@intersectionGeom)=1))<=0

begin

update @tbl_segments set NewPoint=@intersectionGeom where SegmentIndex=@segmentIndex;

end

else

begin

if (Select Count(*) from @tbl_segments t

where t.SegmentIndex=@segmentIndex

and t.StartPoint.STBuffer(0.1).STIntersects(@intersectionGeom)=1)>0

begin

update @tbl_segments set NewPoint=StartPoint where SegmentIndex=@segmentIndex;

end

else

begin

update @tbl_segments set NewPoint=EndPoint where SegmentIndex=@segmentIndex;

end

end

set @i=1;

set @cur=cursor for

(select case

when t.NewPoint is null then

STR(t.StartPoint.STX,18,8)+' '+STR(t.StartPoint.STY,18,8)+','+STR(t.EndPoint.STX,18,8)+' '+STR(t.EndPoint.STY,18,8)

else

STR(t.StartPoint.STX,18,8)+' '+STR(t.StartPoint.STY,18,8)+','+STR(t.NewPoint.STX,18,8)+' '+STR(t.NewPoint.STY,18,8)

end as LineWkt

from @tbl_segments t where t.SegmentIndex<=@segmentIndex)

open @cur

FETCH NEXT

from @cur into @tmpLine

WHILE @@FETCH_STATUS=0

BEGIN

set @line1=@line1+','+TRIM(@tmpLine);

FETCH NEXT

FROM @cur into @tmpLine

END

close @cur;

set @cur=cursor for

(select case

when t.NewPoint is null then

STR(t.StartPoint.STX,18,8)+' '+STR(t.StartPoint.STY,18,8)+','+STR(t.EndPoint.STX,18,8)+' '+STR(t.EndPoint.STY,18,8)

else

+STR(t.NewPoint.STX,18,8)+' '+STR(t.NewPoint.STY,18,8)+','+STR(t.EndPoint.STX,18,8)+' '+STR(t.EndPoint.STY,18,8)

end as LineWkt

from @tbl_segments t where t.SegmentIndex>=@segmentIndex)

open @cur

FETCH NEXT

from @cur into @tmpLine

WHILE @@FETCH_STATUS=0

BEGIN

set @line2=@line2+','+TRIM(@tmpLine);

FETCH NEXT

FROM @cur into @tmpLine

END

close @cur;

set @line1= 'LINESTRING ('+SUBSTRING(@line1,2,LEN(@line1)-1)+')';

set @line2= 'LINESTRING ('+SUBSTRING(@line2,2,LEN(@line2)-1)+')';

set @geom1=geometry::STGeomFromText(@line1,@srid).MakeValid().Reduce(0);

set @geom2=geometry::STGeomFromText(@line2,@srid).MakeValid().Reduce(0);

set @line1=@geom1.STAsText();

set @line2=@geom2.STAsText();

set @returnData='{Status:true,StatusMessage:"İşlem Başarılı",Line1Wkt:"'+@line1+'",Line2Wkt:"'+@line2+'"}';

return @returnData;

end;

Aşağıdaki örnek ile denendiğinde ekran görüntüsündeki gibi sonuç elde edilmektedir.

Select dbo.STSplitLine('LINESTRING (3918330.9493079544 5131284.8657211363, 3918329.6669074208 5131285.4668463869)',

'LINESTRING(3918331.024705282 5131286.203856818,3918329.41982627 5131283.777876917)',3857)

Resimdeki mavi çizgi hat kırmanın yapılacağı çizgi.

Mor ve yeşil çizgiler kırma işlemi sonrasında oluşan çizgileri göstermektedir.