[gdal-dev] Algorithm to clip the inner loop of a polygon
Chao YUE
chaoyuejoy at gmail.com
Wed Apr 15 06:08:16 PDT 2020
Hi Ari and Andreas,
Thanks for the information. I will check it out. Today I advanced a little
by almost implementing what's been proposed in my message there.
Regards,
Chao
On Wed, Apr 15, 2020 at 3:04 PM Ari Jolma <ari.jolma at gmail.com> wrote:
> Andreas Oxenstierna kirjoitti 15.4.2020 klo 9.03:
>
> Hi
>
> Have you tested PostGIS?
> ST_ExteriorRing((ST_Dump(ST_LineMerge(ST_Union(ST_Force2D(<your
> geometry>))))).geom)
>
> should extract the points you want to keep by splitting at intersections -
> but it may fail in very complex cases. Then I would start with a
> ST_SnapToGrid with a quite high tolerance to lower the coordinate
> resolution.
>
>
> That PostGIS solution looks quite nice. Unfortunately I was not able to
> use PostGIS in my case but were restricted to Shapely, which uses GEOS. But
> then, PostGIS is mostly based on GEOS, so it should perhaps be doable that
> way too. I'm not working or using that solution I gave right now so won't
> test it.
>
> Best,
>
> Ari
>
>
>
>
> Hi,
>
> I wrote a method to a Polygon class (in Python) that solves that problem
> because the ones in GEOS via Shapely did not seem good enough. My method
> was based on no published algorithm but just my own reasoning, it is
> probably not optimal speed-wise. I did not perform formal testing on it but
> it worked on my data, which was quite large. The basic idea was to build
> the polygon by adding points and when adding test for self intersections /
> collinearity against existing segments. The method returns the loops while
> points are added. The code is not in a public repo but I'll add the method
> below. It needs some basic methods and function which should be simple to
> add.
>
> Ari
> Chao YUE kirjoitti 15.4.2020 klo 6.30:
>
> Dear all,
>
> Does anyone have some experience or is aware of some algorithm that can
> find and clip the inner loop formed in a polygon ? I attach one example
> here. In this case I would only keep the outer points and drop the ones
> that make an inner loop. I am developing some algorithm to simulate
> wildland fire propagation. The algorithm is based on Richards 1990.
>
> In the paper he described an algorithm based on two steps: (1) find the
> points where a concave curvature is made. (2) search for both sides of this
> point to see where any two line segments cross over each other.
> But I am wondering whether there is already some existing solutions or
> other better ones.
>
> Thanks a lot for the kind help for any hints on this !
> Kind regards,
> Chao
>
> Gwynfor Richards, 1990. An elliptical growth model of forest fire fronts
> and its numerical solution. International journal for Numerical Methods in
> Engineering, Vol. 30, 1163-1179.
>
> [image: InnerLoop.png]
>
> --
>
> ***********************************************************************************
> Chao YUE(岳超)
> 西北农林科技大学水土保持研究所 研究员
> 黄土高原土壤侵蚀与旱地农业国家重点实验室
> State Key Laboratory of Soil Erosion and Dryland Farming on the Loess
> Plateau
> Institute of Soil and Water Conservation
> Northwest A&F University, Yangling, Shaanxi 712100, P.R. China
> chaoyue at ms.iswc.ac.cn
> Mobile: +86 18709187546
>
> ************************************************************************************
>
> _______________________________________________
> gdal-dev mailing listgdal-dev at lists.osgeo.orghttps://lists.osgeo.org/mailman/listinfo/gdal-dev
>
>
> Code copyright Simosol Oy, licence MIT
>
> def add_point(self, p=None):
> """ Add a point to the end of points (before root)
> The first level ear (hole or in-a-point-intersecting polygon) is
> returned
> if there is such.
> p -- point to add, if None, close the ring
>
> self is a Polygon, which has as attributes a dict of points, where
> point = [index of previous point, index of next point, coords]
> no duplicates, no null indexes in points
>
> """
> n = self.n_points()
> if p is None and n < 3:
> raise ValueError("Can't close a polygon with less than three
> points.")
> if self.root is None:
> self.root = 0
> self.points[self.root] = [self.root, self.root, p]
> return
> i0 = self.points[self.root][0]
> if p is not None and p[0] == self.points[i0][2][0] and p[1] ==
> self.points[i0][2][1]:
> # same point, skip
> return None
> index = i0 + 1
> while index in self.points:
> index += 1
> ear = None
> close = False
> if n > 2:
> # test for self-intersection,
> # current - new against (0-1, )1-2, ... prev(current)-current
> current_point = self.get_point(i0)
> j0 = self.root
> if p is None: # close
> p = self.get_point(self.root)
> j0 = self.index_of_next_point(j0)
> close = True
> while True:
> j1 = self.index_of_next_point(j0)
> if j1 == i0:
> break
> pj0 = self.get_point(j0)
> pj1 = self.get_point(j1)
> x = get_line_intersection(pj0, pj1, current_point, p)
>
> if type(x) is tuple: # Intersection
> #print('intersection',pj0,pj1,current_point,p)
> # snip away and return eventually the closed part
> ear = self.get_noose(j1, i0, first_point=x)
> # set new j1 and delete from j1+1 ... current
> self.set_point(j1, x)
> j2 = self.index_of_next_point(j1)
> self.delete_points(j2, i0)
> i0 = j0
> index = j1
> break
>
> elif abs(x) == 1: # Collinear
> if point_on_line(p, pj0, pj1): # new is on j0 - j1
> #print('collinear new on
> j0-j1',pj0,pj1,current_point,p)
> # is j1 on cp - new?
> if point_in_box(pj1, current_point, p):
> k = j1 # ear is j1 ... cp
> else: # j0 is on cp - new
> k = j0 # ear is j0 ... cp
> ear = self.get_noose(k, i0)
> self.delete_points(j1, i0)
> i0 = j0
> index = j1
> break
> elif point_on_line(pj1, current_point, p): # j1 is on
> cp - new
> #print('collinear j1 on
> cp-new',pj0,pj1,current_point,p)
> # ear is j1 ... cp
> ear = self.get_noose(j1, i0)
> self.delete_points(j1, i0)
> i0 = j0
> index = j1
> break
> j0 = j1
>
> if not close:
> self.points[index] = [i0, self.root, p]
> self.points[i0][1] = index
> self.points[self.root][0] = index
> return ear
>
> _______________________________________________
> gdal-dev mailing listgdal-dev at lists.osgeo.orghttps://lists.osgeo.org/mailman/listinfo/gdal-dev
>
>
> --
> Hälsningar
>
> Andreas Oxenstierna
> T-Kartor Geospatial AB
> Olof Mohlins väg 12 Kristianstad
> mobile: +46 733 206831
> mailto: ao at t-kartor.sehttp://www.t-kartor.com
>
>
> _______________________________________________
> gdal-dev mailing listgdal-dev at lists.osgeo.orghttps://lists.osgeo.org/mailman/listinfo/gdal-dev
>
> _______________________________________________
> gdal-dev mailing list
> gdal-dev at lists.osgeo.org
> https://lists.osgeo.org/mailman/listinfo/gdal-dev
--
***********************************************************************************
Chao YUE(岳超)
西北农林科技大学水土保持研究所 研究员
黄土高原土壤侵蚀与旱地农业国家重点实验室
State Key Laboratory of Soil Erosion and Dryland Farming on the Loess
Plateau
Institute of Soil and Water Conservation
Northwest A&F University, Yangling, Shaanxi 712100, P.R. China
chaoyue at ms.iswc.ac.cn
Mobile: +86 18709187546
************************************************************************************
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/gdal-dev/attachments/20200415/08fdea69/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: InnerLoop.png
Type: image/png
Size: 30127 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/gdal-dev/attachments/20200415/08fdea69/attachment-0001.png>
More information about the gdal-dev
mailing list