<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Hi,</p>
<p>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.<br>
</p>
<p>Ari<br>
</p>
<div class="moz-cite-prefix">Chao YUE kirjoitti 15.4.2020 klo 6.30:<br>
</div>
<blockquote type="cite"
cite="mid:CAAN-aRFQsyoVTBceU0QhGcoPr-obmeVhUujAccYroaJwBBPUCw@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="ltr">
<div class="gmail_default" style="font-size:small">
<div>Dear all,</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div>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. </div>
<div>But I am wondering whether there is already some existing
solutions or other better ones. </div>
<div><br>
</div>
<div>Thanks a lot for the kind help for any hints on this !</div>
<div>Kind regards,</div>
<div>Chao</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div><img src="cid:part1.1F4D8229.94F736F6@gmail.com"
alt="InnerLoop.png" class="" width="562" height="415"><br>
</div>
</div>
<div><br>
</div>
-- <br>
<div dir="ltr" class="gmail_signature"
data-smartmail="gmail_signature">
<div dir="ltr">
<div>
<div dir="ltr">
<div>
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div><span style="font-size:12.8px">***********************************************************************************</span><br>
</div>
<div><font color="#000000">Chao YUE(岳超)</font></div>
<font color="#000000">西北农林科技大学水土保持研究所 研究员</font></div>
<div dir="ltr"><font color="#000000">黄土高原土壤侵蚀与旱地农业国家重点实验室</font></div>
<div dir="ltr"><span
style="font-family:Helvetica;font-size:12px"><font
color="#000000">State Key Laboratory of Soil
Erosion and Dryland Farming on the Loess
Plateau</font></span></div>
<div dir="ltr"><span
style="font-family:Helvetica;font-size:12px"><font
color="#000000">Institute of Soil and Water
Conservation</font></span></div>
<div dir="ltr"><font color="#000000"><span
style="font-family:Helvetica;font-size:12px">Northwest
A&F University, Yangling, Shaanxi
712100, P.R. China</span><br>
</font></div>
<div dir="ltr">
<div><font color="#000000"><a
href="mailto:chaoyue@ms.iswc.ac.cn"
style="font-family:Helvetica;font-size:12px"
target="_blank" moz-do-not-send="true">chaoyue@ms.iswc.ac.cn</a><br>
</font></div>
<div><font color="#000000">Mobile: +86
18709187546</font></div>
<div>************************************************************************************<br>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<pre class="moz-quote-pre" wrap="">_______________________________________________
gdal-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:gdal-dev@lists.osgeo.org">gdal-dev@lists.osgeo.org</a>
<a class="moz-txt-link-freetext" href="https://lists.osgeo.org/mailman/listinfo/gdal-dev">https://lists.osgeo.org/mailman/listinfo/gdal-dev</a></pre>
</blockquote>
<p><br>
</p>
<p>Code copyright Simosol Oy, licence MIT<br>
</p>
<p>def add_point(self, p=None):<br>
""" Add a point to the end of points (before root)<br>
The first level ear (hole or in-a-point-intersecting
polygon) is returned<br>
if there is such.<br>
p -- point to add, if None, close the ring</p>
<p> self is a Polygon, which has as attributes a dict of points,
where<br>
point = [index of previous point, index of next point, coords]<br>
no duplicates, no null indexes in points<br>
</p>
<p> """<br>
n = self.n_points()<br>
if p is None and n < 3:<br>
raise ValueError("Can't close a polygon with less than
three points.")<br>
if self.root is None:<br>
self.root = 0<br>
self.points[self.root] = [self.root, self.root, p]<br>
return<br>
i0 = self.points[self.root][0]<br>
if p is not None and p[0] == self.points[i0][2][0] and
p[1] == self.points[i0][2][1]:<br>
# same point, skip<br>
return None<br>
index = i0 + 1<br>
while index in self.points:<br>
index += 1<br>
ear = None<br>
close = False<br>
if n > 2:<br>
# test for self-intersection,<br>
# current - new against (0-1, )1-2, ...
prev(current)-current<br>
current_point = self.get_point(i0)<br>
j0 = self.root<br>
if p is None: # close<br>
p = self.get_point(self.root)<br>
j0 = self.index_of_next_point(j0)<br>
close = True<br>
while True:<br>
j1 = self.index_of_next_point(j0)<br>
if j1 == i0:<br>
break<br>
pj0 = self.get_point(j0)<br>
pj1 = self.get_point(j1)<br>
x = get_line_intersection(pj0, pj1, current_point,
p)<br>
<br>
if type(x) is tuple: # Intersection<br>
#print('intersection',pj0,pj1,current_point,p)<br>
# snip away and return eventually the closed
part<br>
ear = self.get_noose(j1, i0, first_point=x)<br>
# set new j1 and delete from j1+1 ... current<br>
self.set_point(j1, x)<br>
j2 = self.index_of_next_point(j1)<br>
self.delete_points(j2, i0)<br>
i0 = j0<br>
index = j1<br>
break<br>
<br>
elif abs(x) == 1: # Collinear<br>
if point_on_line(p, pj0, pj1): # new is on j0
- j1<br>
#print('collinear new on
j0-j1',pj0,pj1,current_point,p)<br>
# is j1 on cp - new?<br>
if point_in_box(pj1, current_point, p):<br>
k = j1 # ear is j1 ... cp<br>
else: # j0 is on cp - new<br>
k = j0 # ear is j0 ... cp<br>
ear = self.get_noose(k, i0)<br>
self.delete_points(j1, i0)<br>
i0 = j0<br>
index = j1<br>
break<br>
elif point_on_line(pj1, current_point, p): #
j1 is on cp - new<br>
#print('collinear j1 on
cp-new',pj0,pj1,current_point,p)<br>
# ear is j1 ... cp<br>
ear = self.get_noose(j1, i0)<br>
self.delete_points(j1, i0)<br>
i0 = j0<br>
index = j1<br>
break<br>
j0 = j1<br>
<br>
if not close:<br>
self.points[index] = [i0, self.root, p]<br>
self.points[i0][1] = index<br>
self.points[self.root][0] = index<br>
return ear<br>
</p>
</body>
</html>