fitodic / centerline Goto Github PK
View Code? Open in Web Editor NEWCalculate the polygon's centerline
Home Page: https://centerline.readthedocs.io
License: MIT License
Calculate the polygon's centerline
Home Page: https://centerline.readthedocs.io
License: MIT License
Hi folks,
I've already set up all the requirements and follow the instructions in order to run the code but:
My system (windows32) is not able to find shp2centerline script. Do I need to change the extension of that file? Maybe should I try to run it as *.py?
This warning is triggered here, and as shapely 2.0 is already in alpha...:
~\.conda\envs\geofileopsdev\lib\site-packages\centerline\geometry.py:128: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
return (polygon for polygon in self._input_geometry)
Hey there,
when I run the centerline method on a rather simple, rectangular Polygon, I unforunately get not only one but several hundred or even thousand LineString objects grouped together as a MultiLineString object. At least with shapely I haven't been able to a) merge, union or dissolve the objects to receive a single LineString or b) split a Polygon with the LineString I'm trying to create.
The bigger problem, however, is that I'm not getting a clean, straight line as shown in the example but a skeleton-like LineString. I'm attaching an image of the Polygon and the LineString I'm getting by running Centerline(my_polygon)
.
Looking at my result I wonder whether I'm doing something wrong?
Using poligon with points:
[(107, 189),
(106, 190),
(100, 190),
(99, 191),
(95, 191),
(94, 192),
(92, 192),
(91, 193),
(90, 193),
(89, 194),
(88, 194),
(87, 195),
(86, 195),
(85, 196),
(84, 196),
(82, 198),
(82, 203),
(86, 207),
(87, 207),
(90, 210),
(91, 210),
(92, 211),
(94, 211),
(95, 212),
(98, 212),
(99, 213),
(101, 213),
(102, 214),
(105, 214),
(106, 215),
(108, 215),
(109, 216),
(111, 216),
(112, 217),
(114, 217),
(115, 218),
(117, 218),
(118, 219),
(120, 219),
(121, 220),
(126, 220),
(127, 221),
(133, 221),
(134, 222),
(136, 222),
(137, 223),
(138, 223),
(139, 224),
(139, 227),
(137, 229),
(137, 230),
(136, 231),
(135, 231),
(133, 233),
(132, 233),
(130, 235),
(129, 235),
(126, 238),
(125, 238),
(124, 239),
(123, 239),
(122, 240),
(121, 240),
(120, 241),
(119, 241),
(118, 242),
(116, 242),
(115, 243),
(114, 243),
(113, 244),
(112, 244),
(110, 246),
(109, 246),
(108, 247),
(107, 247),
(106, 248),
(105, 248),
(104, 249),
(102, 249),
(101, 250),
(99, 250),
(98, 251),
(97, 251),
(96, 252),
(94, 252),
(92, 254),
(91, 254),
(90, 255),
(89, 255),
(88, 256),
(87, 256),
(86, 257),
(85, 257),
(84, 258),
(83, 258),
(82, 259),
(80, 259),
(79, 260),
(78, 260),
(70, 268),
(70, 269),
(69, 270),
(69, 272),
(68, 273),
(68, 276),
(71, 279),
(73, 279),
(74, 280),
(83, 280),
(84, 279),
(90, 279),
(91, 278),
(94, 278),
(95, 277),
(97, 277),
(98, 276),
(99, 276),
(100, 275),
(101, 275),
(103, 273),
(105, 273),
(106, 272),
(108, 272),
(109, 271),
(111, 271),
(112, 270),
(113, 270),
(114, 269),
(115, 269),
(116, 268),
(117, 268),
(120, 265),
(121, 265),
(122, 264),
(124, 264),
(125, 263),
(126, 263),
(127, 262),
(128, 262),
(129, 261),
(130, 261),
(132, 259),
(133, 259),
(135, 257),
(136, 257),
(137, 256),
(138, 256),
(139, 255),
(141, 255),
(142, 254),
(143, 254),
(145, 252),
(146, 252),
(149, 249),
(150, 249),
(153, 246),
(154, 246),
(158, 242),
(158, 241),
(164, 235),
(164, 234),
(165, 233),
(165, 232),
(166, 231),
(166, 230),
(167, 229),
(167, 227),
(168, 226),
(168, 223),
(169, 222),
(169, 220),
(170, 219),
(170, 212),
(169, 211),
(169, 210),
(168, 209),
(168, 208),
(167, 207),
(167, 206),
(162, 201),
(161, 201),
(159, 199),
(158, 199),
(157, 198),
(155, 198),
(154, 197),
(153, 197),
(151, 195),
(150, 195),
(149, 194),
(147, 194),
(146, 193),
(144, 193),
(143, 192),
(139, 192),
(138, 191),
(132, 191),
(131, 190),
(122, 190),
(121, 189)]
polygon = Polygon(pts)
attributes = {"id": 1, "name": "polygon", "valid": True}
centerline = Centerline(polygon, **attributes)
I got:
QhullError: QH6214 qhull input error: not enough points(2) to construct initial simplex (need 4
(/Users/vivek/anaconda3/envs/centerline27) bash-3.2$ shp2centerline 84/sidewalks_w_id/sidewalks_w_id.shp 84/output/sidewalk_output.shp
Importing polygons from: 84/sidewalks_w_id/sidewalks_w_id.shp
Calculating centerlines.
Traceback (most recent call last):
File "/Users/vivek/anaconda3/envs/centerline27/bin/shp2centerline", line 94, in <module>
Shp2centerline(args.SRC, args.DEST, args.BORDENS)
File "/Users/vivek/anaconda3/envs/centerline27/bin/shp2centerline", line 20, in __init__
self.run()
File "/Users/vivek/anaconda3/envs/centerline27/bin/shp2centerline", line 38, in run
self.dct_centerlines[key] = centerlineObj.createCenterline()
File "/Users/vivek/anaconda3/envs/centerline27/lib/python2.7/site-packages/centerline/centerline.py", line 32, in createCenterline
vor = Voronoi(border)
File "scipy/spatial/qhull.pyx", line 2544, in scipy.spatial.qhull.Voronoi.__init__ (scipy/spatial/qhull.c:25511)
File "scipy/spatial/qhull.pyx", line 434, in scipy.spatial.qhull._Qhull.__init__ (scipy/spatial/qhull.c:5799)
scipy.spatial.qhull.QhullError: QH6214 qhull input error: not enough points(2) to construct initial simplex (need 4)
While executing: | qhull v Qbb Qz Qc
Options selected for Qhull 2015.2.r 2016/01/18:
run-id 1309006505 voronoi Qbbound-last Qz-infinity-point Qcoplanar-keep
_pre-merge _zero-centrum Qinterior-keep```
Hello,
I cannot compute centerline using your module and attached polygon.
Any help would be greatly appreciated !
Regards,
We would like to cite centerline in one of our papers. Can you please add a CITATION.cff file, zenodo id? We may cite this repository as (Todić, 2023)? Thank you!
When trying to get the basic example from readme running,
from shapely.geometry import Polygon
from centerline.geometry import Centerline
polygon = Polygon([[0, 0], [0, 4], [4, 4], [4, 0]])
attributes = {"id": 1, "name": "polygon", "valid": True}
centerline = Centerline(polygon, **attributes)
I get the following error: TypeError: One of the arguments is of incorrect type. Please provide only Geometry objects.
Python 3.10, shapely 2.0.3., pygeos 0.14, GDAL 3.4.1
The whole stack:
TypeError Traceback (most recent call last)
Cell In[41], line 7
4 polygon = Polygon([[0, 0], [0, 4], [4, 4], [4, 0]])
5 attributes = {"id": 1, "name": "polygon", "valid": True}
----> 7 centerline = Centerline(polygon, **attributes)
File /opt/homebrew/Caskroom/miniconda/base/envs/parkplatz2/lib/python3.10/site-packages/centerline/geometry.py:44, in Centerline.init(self, input_geometry, interpolation_distance, **attributes)
41 self._min_x, self._min_y = self._get_reduced_coordinates()
42 self.assign_attributes_to_instance(attributes)
---> 44 self.geometry = MultiLineString(lines=self._construct_centerline())
File /opt/homebrew/Caskroom/miniconda/base/envs/parkplatz2/lib/python3.10/site-packages/centerline/geometry.py:88, in Centerline._construct_centerline(self)
85 linestring = LineString((starting_point, ending_point))
86 linestrings.append(linestring)
---> 88 str_tree = STRtree(linestrings)
89 linestrings_indexes = str_tree.query(self._input_geometry, "contains")
90 contained_linestrings = [linestrings[i] for i in linestrings_indexes]
File /opt/homebrew/Caskroom/miniconda/base/envs/parkplatz2/lib/python3.10/site-packages/shapely/strtree.py:82, in STRtree.init(self, geoms, node_capacity)
79 self.geometries = np.array(geoms, dtype=np.object, copy=True)
81 # initialize GEOS STRtree
---> 82 self._tree = lib.STRtree(self.geometries, node_capacity)
When testing using centerline = Centerline(polygon, **attributes)
or command line,
Reports "TypeError: new() got an unexpected keyword argument 'XXX,' "XXX" is the first attribute name.
I have tested on several machines; the results were the same.
I've tried many things and have scanned the the web and stack-exchange, and I still can't install this. On ubuntu 16.04, in my most recent attempt, I did the following:
sudo apt install python-gdal
python3 -m venv CL
. CL/bin/activate
pip install -U pip setuptools wheel
pip install GDAL==2.2.2
pip install centerline
The last step fails as follows liekly because its trying to install/build GDAL>-2.3.3.
Is there an earlier version of centerline that I can install with GDAL==2.2.2?
Hi @fitodic !
I think I found a (much) faster way to perform those calculations. Or at least, it is with the case with the data I tested with.
This is the python script I used to compare them:
from centerline.geometry import Centerline
import shapely
import geopandas as gpd
from timeit import default_timer as timer
def construct_centerline(input_geometry, interpolation_distance=0.5):
#find the voronoi verticies (equivalent to Centerline._get_voronoi_vertices_and_ridges())
borders = input_geometry.segmentize(interpolation_distance) #To have smaler verticies (equivalent to Centerline._get_densified_borders())
voronoied = shapely.voronoi_polygons(borders,only_edges=True) #equivalent to the scipy.spatial.Voronoi
#to select only the linestring within the input geometry (equivalent to Centerline._linestring_is_within_input_geometry)
centerlines = gpd.GeoDataFrame(geometry=gpd.GeoSeries(voronoied.geoms)).sjoin(gpd.GeoDataFrame(geometry=gpd.GeoSeries(input_geometry)),predicate="within")
return centerlines.unary_union
start = timer()
open_area_lines = Centerline(open_area_Road[0],interpolation_distance=2)
end = timer()
centerlines = construct_centerline(open_area_Road[0],interpolation_distance=2)
end2 = timer()
Print(f" Duration current implementation : {end-start:0.3f}s \n Duration proposed implementation : {end2-end:0.3f}s")
In my testing, the proposed version takes 8.580s and the current version of Centerline takes 278.823s. Both versions give fairly similar results in therm of centerline network (see figure). I suppose the difference comes mainly from the segmenting algorithm, but I haven't explored this much. Note that the polygone.segmentize() is only available since version 2.0.0 of the shapely library.
I suppose the main speed-up comes from the way the inside vertices are calculated, as using the spatial join from geopandas is really fast.
I know this way of measuring calculation speed is not perfect and multiple times should at least be averaged out and with different initial polygons. But given the speed difference in my testing, I thought the difference was clear enough to not bother with more extensive testing for now.
To stay constant with the current behavior of the library, I transformed the geoDataFrame back to a shapely multiline. But I figured that is you implement those changes, the Centerline could stay a geoDataFrame as those are less difficult to work with (That's my opinion obviously).
Have a nice day
Hi @fitodic
I think maybe version haven't updated because something wrong
ERROR: Could not find a version that satisfies the requirement centerline==1.0.0 (from versions: 0.1, 0.2, 0.2.1, 0.3, 0.4, 0.4.1, 0.4.2, 0.5, 0.5.2, 0.6.0, 0.6.3, 0.6.4)
ERROR: No matching distribution found for centerline==1.0.0
Can you review it.
Thank you.
Hi @fitodic
Thanks for great repo that helping to have centerlines
My question is: "if I have centerline, can reverse to caculate width of polygons"
Here is pic example
Have you have ideas??
Thank you very much!
Recently, I started to get the following warnings while using centerline:
/Users/ogourgue/Library/Python/3.9/lib/python/site-packages/centerline-0.6.3-py3.9.egg/centerline/geometry.py:34: ShapelyDeprecationWarning: Setting custom attributes on geometry objects is deprecated, and will raise an AttributeError in Shapely 2.0 self._input_geometry = input_geometry /Users/ogourgue/Library/Python/3.9/lib/python/site-packages/centerline-0.6.3-py3.9.egg/centerline/geometry.py:35: ShapelyDeprecationWarning: Setting custom attributes on geometry objects is deprecated, and will raise an AttributeError in Shapely 2.0 self._interpolation_distance = abs(interpolation_distance) /Users/ogourgue/Library/Python/3.9/lib/python/site-packages/centerline-0.6.3-py3.9.egg/centerline/geometry.py:40: ShapelyDeprecationWarning: Setting custom attributes on geometry objects is deprecated, and will raise an AttributeError in Shapely 2.0 self._min_x, self._min_y = self._get_reduced_coordinates()
Is there a plan to update centerline to avoid this future error?
Hey,
thanks for your work.
The current version 1.0.0 cannot be installed with python 3.7.
pip install git+https://github.com/fitodic/[email protected]
ERROR: Package 'centerline' requires a different Python: 3.7.16 not in '>=3.8'
Python 3.7 is listed here: https://github.com/fitodic/centerline/blob/master/setup.cfg#L22 and
the constraint is defined here: https://github.com/fitodic/centerline/blob/master/setup.cfg#L31.
Is Python 3.8 really necessary, or can we also enable the other versions? Otherwise we should update the classifiers.
Thank you
Mathias
Hi, I'm trying to use this code to find Centerline inside a polygon. I got a TypeError.
TypeError: unbound method createCenterline() must be called with Centerline instance as first argument (got ndarray instance instead)
I gave it a wkt polygon string. However, I don't know what should Centerline instance look like.
Could anyone give me some example? I didnt find the documents.
Many thanks.
------update------
I created self by Centerline() and I got this: 'list' object has no attribute 'envelope'
thanks for your great lib. here I have some problems with the result.
how to remove green color lines?
here is my data
[[
[2.18, 5.52], [0.9, 5.52], [0.9, 5.4], [2.18, 5.4], [2.18, 5.16], [2.19, 5.16], [2.19, 4.02], [2.18, 4.02], [2.18, 3.73], [2.53, 3.73], [2.53, 4],
[2.54, 4], [2.54, 5.2], [2.53, 5.2], [2.53, 5.36], [2.54, 5.37], [2.54, 5.36], [3.09, 5.36], [3.09, 5.37], [4.22, 5.37], [4.22, 5.36],
[4.89, 5.36], [4.89, 5.37], [5.43, 5.37], [5.43, 5.36], [6.12, 5.36], [6.12, 5.37], [7.25, 5.37], [7.25, 5.36], [8.75, 5.36], [8.75, 5.37],
[9.68, 5.37], [9.68, 5.36], [10.41, 5.36], [10.41, 3.77], [9.68, 3.77], [9.68, 3.62], [10.41, 3.62], [10.41, 3.15], [10.68, 3.15], [10.7, 3.75],
[10.7, 3.77], [10.63, 3.77], [10.62, 3.78], [10.63, 5.72], [2.18, 5.72]]]
Hi....
I have read on centerline documentation and is possible to use Multipolygon to calculate the centerline, rigth?
I have a shapefile containing 1328 polygons on the file and the type of this, acoording python is "print(type(Multi)) <class 'shapely.geometry.multipolygon.MultiPolygon'>"
When I have tried execute the comandline the Python returns an error that is showing below:
Multi = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('Plantio_Cana_NDVI_Preparado_Final.shp')])
centerln = centerline.geometry.Centerline(Multi,interpolation_distance=0.5)
Error on python:
**centerln = centerline.geometry.Centerline(Multi,interpolation_distance=0.5)
AttributeError: module 'centerline' has no attribute 'geometry'**
Could you help me to understand this issue?
the fiona has rename the 'path' to 'fp' in fiona.open method.
For some inputs _create_centerline()
returns LineString
, which breaks MultiLineString constructor. Not sure, if that is so by design.
Anyway, here is an example:
from centerline import Centerline
from shapely.geometry import Polygon
p = Polygon([(614, 1005), (614, 1010), (617, 1010), (617, 1009), (620, 1009), (620, 1010), (621, 1010), (621, 1011), (624, 1011), (624, 1010), (625, 1010), (625, 1006), (624, 1006), (624, 1005), (619, 1005), (619, 1006), (618, 1006), (618, 1005), (614, 1005)])
c = Centerline(p, 10)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-f6be4fb7d387> in <module>()
----> 1 c = Centerline(p, 10)
~/.local/lib/python3.6/site-packages/centerline/main.py in __init__(self, input_geom, interpolation_dist, **attributes)
61 setattr(self, key, attributes.get(key))
62
---> 63 super(Centerline, self).__init__(lines=self._create_centerline())
64
65 def _create_centerline(self):
/opt/conda/envs/pytorch-py3.6/lib/python3.6/site-packages/shapely/geometry/multilinestring.py in __init__(self, lines)
50 pass
51 else:
---> 52 self._geom, self._ndim = geos_multilinestring_from_py(lines)
53
54 def shape_factory(self, *args):
/opt/conda/envs/pytorch-py3.6/lib/python3.6/site-packages/shapely/geometry/multilinestring.py in geos_multilinestring_from_py(ob)
117
118 obs = getattr(ob, 'geoms', ob)
--> 119 L = len(obs)
120 assert L >= 1
121 exemplar = obs[0]
TypeError: object of type 'LineString' has no len()
If you consider this an issue, I can provide PR.
Thanks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.