Skip to content

Commit

Permalink
Merge branch 'new_triangulation_fix' into 'master'
Browse files Browse the repository at this point in the history
fix: reliably select triangulation projection plane and orientation

Closes #49

See merge request Oslandia/py3dtiles!86
  • Loading branch information
autra committed Mar 25, 2022
2 parents 6381ce9 + 3603b00 commit 4c46614
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 3 deletions.
39 changes: 36 additions & 3 deletions py3dtiles/wkb_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,41 @@ def triangulate(polygon, additionalPolygons=[]):
"""
Triangulates 3D polygons
"""
vect1 = polygon[0][1] - polygon[0][0]
vect2 = polygon[0][2] - polygon[0][0]
vectProd = np.cross(vect1, vect2)
# let's find out if the polygon is *mostly* clockwise or counter-clockwise
# and triangulate accordingly
# for 2D explanations:
# https://stackoverflow.com/a/1165943/1528985
# and https://www.element84.com/blog/determining-the-winding-of-a-polygon-given-as-a-set-of-ordered-points
#
# Quick explanation in case it goes down: for each edge we calculate the
# area of the polygon formed by this edge, the x axis and the 2 vertical.
# It's (x2-x1) / ((y2+y1 / 2) (draw it if you don't believe me). This
# results will be positive for a edge that goes toward positive x. Summing
# all these areas will give plus or minus the total polygon area. it would
# be positive for a clockwise polygon (upper edges contributing positively)
# and negative for counter-clockwise polygons (upper edges contributing
# negatively)
#
# Adaptations here:
# - we prefer to reason with counter-clockwise positive, hence the x1-x2 instead of x2-x1
# - in 3D, we calcule this value for each axis planes (xy, yz, zx),
# looking in the other axis negative direction.
# - comparing these 3 results actually give us the most interesting plane
# to triangulate in (the plane were the projected area is the biggest)
# - we drop the 1/2 factor because we are only interesting in the sign and relative comparison
vectProd = np.array([0, 0, 0], dtype=np.float32)
for i in range(len(polygon[0])):
curr_edge = polygon[0][i]
next_edge = polygon[0][(i + 1) % len(polygon[0])]
vectProd += np.array([
# yz plane, seen from negative x
(curr_edge[1] - next_edge[1]) * (next_edge[2] + curr_edge[2]),
# zx plane, seen from negative y
(curr_edge[2] - next_edge[2]) * (next_edge[0] + curr_edge[0]),
# xy plane, seen from negative z
(curr_edge[0] - next_edge[0]) * (next_edge[1] + curr_edge[1]),
], dtype=np.float32)

polygon2D = []
holes = []
delta = 0
Expand Down Expand Up @@ -215,6 +247,7 @@ def triangulate(polygon, additionalPolygons=[]):
p2 = unflatten(polygon, holes, t[2])
# triangulation may break triangle orientation, test it before
# adding triangles
# FIXME fix / change the triangulation code instead?
crossProduct = np.cross(p1 - p0, p2 - p0)
invert = np.dot(vectProd, crossProduct) < 0
if invert:
Expand Down
8 changes: 8 additions & 0 deletions tests/big_polygon_counter_clockwise.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "FeatureCollection",
"name": "big_polygon_counter_clockwise",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.000025694188824, 0.000042615519839, 0.0 ], [ 0.000024542634788, 0.000040141811177, 0.0 ], [ 0.000020448220437, 0.00004073891327, 0.0 ], [ 0.000019893768494, 0.000036687149068, 0.0 ], [ 0.000022111576267, 0.000034682592052, 0.0 ], [ 0.000024883835984, 0.000029095422459, 0.0 ], [ 0.000033413865881, 0.000026067261849, 0.0 ], [ 0.000026376591216, 0.00001826228449, 0.0 ], [ 0.000019893768494, 0.00001834758479, 0.0 ], [ 0.000023860232396, 0.000017025430169, 0.0 ], [ 0.0000317931602, 0.000016641578819, 0.0 ], [ 0.000041432093983, 0.00001745193166, 0.0 ], [ 0.000052137281504, 0.000022356698851, 0.0 ], [ 0.000054269788978, 0.000019029987179, 0.0 ], [ 0.000055165442117, 0.000022441999144, 0.0 ], [ 0.000055336042715, 0.000025598110207, 0.0 ], [ 0.000054824240921, 0.000028199769319, 0.0 ], [ 0.000050601876123, 0.000029436623654, 0.0 ], [ 0.000049365021787, 0.000028071818873, 0.0 ], [ 0.000048384068349, 0.000025427509605, 0.0 ], [ 0.000047189864164, 0.00002376415378, 0.0 ], [ 0.000045441208035, 0.000023380302437, 0.0 ], [ 0.000045270607437, 0.000023209701828, 0.0 ], [ 0.000044545554896, 0.000023039101231, 0.0 ], [ 0.00004416170355, 0.00002261259973, 0.0 ], [ 0.000043692551906, 0.000022399348991, 0.0 ], [ 0.000040749691592, 0.000021802246898, 0.0 ], [ 0.000040621741143, 0.000021844897051, 0.0 ], [ 0.000040237889798, 0.000021844897051, 0.0 ], [ 0.000040195239648, 0.000021844897051, 0.0 ], [ 0.000040109939349, 0.000021844897051, 0.0 ], [ 0.000039768738154, 0.000021930197358, 0.0 ], [ 0.000039640787705, 0.000022015497639, 0.0 ], [ 0.000039470187107, 0.000022186098239, 0.0 ], [ 0.000039171636061, 0.000022399348991, 0.0 ], [ 0.000038915735164, 0.000022655249896, 0.0 ], [ 0.000038617184118, 0.000023252351993, 0.0 ], [ 0.00003840393337, 0.000023849454071, 0.0 ], [ 0.000038361283221, 0.000024361255866, 0.0 ], [ 0.00003840393337, 0.000025128958562, 0.0 ], [ 0.000039001035463, 0.000025726060659, 0.0 ], [ 0.000039981988901, 0.000026536413499, 0.0 ], [ 0.000040664391293, 0.000027048215295, 0.0 ], [ 0.000042498347721, 0.000027773267832, 0.0 ], [ 0.00004335135071, 0.000028114469022, 0.0 ], [ 0.000044758805643, 0.000029010122163, 0.0 ], [ 0.000046507461772, 0.000030246976493, 0.0 ], [ 0.000047403114911, 0.000031697081578, 0.0 ], [ 0.000047701665958, 0.000032933935913, 0.0 ], [ 0.000047829616406, 0.00003434139085, 0.0 ], [ 0.000047829616406, 0.000035109093539, 0.0 ], [ 0.000047701665958, 0.00003579149592, 0.0 ], [ 0.000047360464762, 0.000036217997424, 0.0 ], [ 0.000046806012818, 0.00003660184877, 0.0 ], [ 0.000046592762071, 0.000036217997424, 0.0 ], [ 0.000046294211025, 0.000035706195634, 0.0 ], [ 0.000045526508334, 0.000035151743682, 0.0 ], [ 0.000044716155494, 0.00003417079026, 0.0 ], [ 0.000044545554896, 0.000033104536506, 0.0 ], [ 0.000044119053401, 0.00003216623322, 0.0 ], [ 0.00004335135071, 0.000031483830834, 0.0 ], [ 0.000042242446824, 0.000031227929944, 0.0 ], [ 0.000040962942339, 0.000031057329333, 0.0 ], [ 0.000039854038453, 0.000030886728734, 0.0 ], [ 0.000038915735164, 0.000031270580078, 0.0 ], [ 0.000037721530978, 0.000032678035017, 0.0 ], [ 0.000037508280231, 0.000034256090549, 0.0 ], [ 0.00003759358053, 0.000035919446387, 0.0 ], [ 0.000038659834267, 0.000037071000411, 0.0 ], [ 0.000039555487406, 0.000037284251159, 0.0 ], [ 0.000041218843236, 0.00003779605296, 0.0 ], [ 0.000043521951308, 0.000038393155052, 0.0 ], [ 0.000044716155494, 0.000038691706102, 0.0 ], [ 0.000045313257587, 0.000038777006397, 0.0 ], [ 0.000046933963267, 0.000038691706102, 0.0 ], [ 0.000047701665958, 0.000038563755654, 0.0 ], [ 0.000048682619396, 0.000038393155052, 0.0 ], [ 0.000049450322086, 0.000038137254142, 0.0 ], [ 0.000050559225973, 0.00003805195386, 0.0 ], [ 0.000051540179411, 0.000038137254142, 0.0 ], [ 0.000052862334045, 0.000038990257151, 0.0 ], [ 0.000052990284494, 0.000039757959829, 0.0 ], [ 0.000053032934643, 0.000040355061926, 0.0 ], [ 0.000052947634344, 0.000042061067904, 0.0 ], [ 0.000052777033746, 0.000042999371193, 0.0 ], [ 0.0000524784827, 0.000044022974779, 0.0 ], [ 0.000052265231952, 0.000044662727019, 0.0 ], [ 0.000052051981205, 0.000044918627925, 0.0 ], [ 0.000051454879112, 0.000045174528818, 0.0 ], [ 0.000050857777019, 0.000045259829116, 0.0 ], [ 0.000050431275525, 0.000045089228508, 0.0 ], [ 0.000049322371638, 0.000044321525825, 0.0 ], [ 0.00004919442119, 0.000042999371193, 0.0 ], [ 0.000049066470741, 0.000042231668495, 0.0 ], [ 0.000048981170442, 0.00004150661595, 0.0 ], [ 0.000048170817602, 0.000040397712078, 0.0 ], [ 0.000048085517303, 0.000040355061926, 0.0 ], [ 0.000046422161473, 0.00004108011446, 0.0 ], [ 0.000045697108932, 0.000041634566417, 0.0 ], [ 0.00004505735669, 0.000042530219537, 0.0 ], [ 0.000044886756092, 0.000043127321644, 0.0 ], [ 0.000044630855195, 0.000043724423731, 0.0 ], [ 0.000044545554896, 0.000044236225526, 0.0 ], [ 0.000044374954298, 0.000044748027317, 0.0 ], [ 0.00004339400086, 0.000045942231515, 0.0 ], [ 0.00004335135071, 0.000045942231515, 0.0 ], [ 0.000042157146525, 0.000046454033303, 0.0 ], [ 0.000041943895777, 0.000046454033303, 0.0 ], [ 0.000041645344731, 0.000046411383143, 0.0 ], [ 0.000041304143535, 0.0000456863306, 0.0 ], [ 0.000040237889798, 0.000044193575377, 0.0 ], [ 0.000040152589499, 0.000044193575377, 0.0 ], [ 0.000040024639051, 0.000043681773594, 0.0 ], [ 0.000039896688602, 0.000043255272094, 0.0 ], [ 0.000039512837257, 0.000042999371193, 0.0 ], [ 0.000039086335762, 0.000041975767601, 0.0 ], [ 0.000038830434865, 0.000041719866707, 0.0 ], [ 0.000038361283221, 0.000040994814156, 0.0 ], [ 0.000037636230679, 0.000040866863713, 0.0 ], [ 0.000036953828288, 0.000040909513878, 0.0 ], [ 0.000036911178138, 0.000040909513878, 0.0 ], [ 0.000036186125597, 0.000041165414763, 0.0 ], [ 0.000035887574551, 0.000041378665508, 0.0 ], [ 0.000035503723205, 0.000042146368205, 0.0 ], [ 0.000035205172159, 0.00004270082014, 0.0 ], [ 0.000034906621112, 0.000043297922244, 0.0 ], [ 0.000034522769767, 0.00004393767448, 0.0 ], [ 0.000034352169169, 0.000044406826124, 0.0 ], [ 0.000034181568571, 0.000044790677479, 0.0 ], [ 0.000034863970963, 0.000046667284054, 0.0 ], [ 0.000035802274252, 0.000046923184939, 0.0 ], [ 0.000036484676643, 0.000047179085849, 0.0 ], [ 0.000037422979932, 0.000047605587332, 0.0 ], [ 0.000037678880829, 0.000048117389131, 0.0 ], [ 0.000037678880829, 0.00004854389062, 0.0 ], [ 0.000037337679633, 0.000048885091826, 0.0 ], [ 0.000036996478437, 0.000048885091826, 0.0 ], [ 0.000036314076045, 0.000049311593322, 0.0 ], [ 0.00003597287485, 0.000049311593322, 0.0 ], [ 0.000035290472458, 0.000049226293018, 0.0 ], [ 0.000034693370365, 0.000049226293018, 0.0 ], [ 0.00003426686887, 0.00004905569241, 0.0 ], [ 0.000034181568571, 0.000048629190925, 0.0 ], [ 0.000033925667674, 0.000048287989729, 0.0 ], [ 0.000033840367375, 0.000047946788532, 0.0 ], [ 0.000033755067076, 0.000047861488238, 0.0 ], [ 0.000033413865881, 0.000047861488238, 0.0 ], [ 0.000033243265283, 0.000047776187932, 0.0 ], [ 0.000033072664685, 0.000047776187932, 0.0 ], [ 0.000032560862891, 0.000047861488238, 0.0 ], [ 0.000031796230933, 0.000048117021882, 0.0 ], [ 0.000031793280184, 0.000048120163002, 0.0 ], [ 0.000031811048136, 0.000048160236079, 0.0 ], [ 0.000031822216562, 0.000048174958096, 0.0 ], [ 0.000031788203627, 0.000048201356195, 0.0 ], [ 0.000031763328494, 0.000048221662426, 0.0 ], [ 0.000031724746657, 0.000048222677737, 0.0 ], [ 0.000031537259303, 0.000048287989729, 0.0 ], [ 0.000031451959004, 0.000048373290035, 0.0 ], [ 0.000031366658705, 0.000048373290035, 0.0 ], [ 0.000030343055118, 0.00004854389062, 0.0 ], [ 0.000030001853922, 0.00004854389062, 0.0 ], [ 0.000029575352427, 0.00004854389062, 0.0 ], [ 0.00002931945153, 0.000047861488238, 0.0 ], [ 0.000029148850932, 0.000047434986731, 0.0 ], [ 0.000028807649736, 0.000046667284054, 0.0 ], [ 0.000028295847942, 0.000046411383143, 0.0 ], [ 0.000027528145252, 0.00004632608286, 0.0 ], [ 0.000026419241365, 0.000046667284054, 0.0 ], [ 0.000025822139272, 0.00004675258435, 0.0 ], [ 0.000023263130303, 0.000047946788532, 0.0 ], [ 0.000023007229406, 0.000047946788532, 0.0 ], [ 0.000021983625819, 0.000047605587332, 0.0 ], [ 0.000021471824025, 0.000046837884657, 0.0 ], [ 0.000021471824025, 0.000046581983746, 0.0 ], [ 0.00002189832552, 0.000045814281058, 0.0 ], [ 0.000022836628809, 0.000044705377181, 0.0 ], [ 0.000023007229406, 0.000044705377181, 0.0 ], [ 0.000023774932097, 0.00004462007687, 0.0 ], [ 0.000024542634788, 0.000044449476273, 0.0 ], [ 0.000024798535685, 0.000044364175974, 0.0 ], [ 0.000025651538674, 0.000043596473282, 0.0 ], [ 0.000025651538674, 0.000043425872682, 0.0 ], [ 0.000025736838973, 0.000042914070892, 0.0 ], [ 0.000025736838973, 0.000042828770591, 0.0 ], [ 0.000025566238376, 0.000042572869701, 0.0 ], [ 0.000025567207505, 0.000042547486913, 0.0 ], [ 0.000025601728097, 0.000042559670651, 0.0 ], [ 0.000025694188824, 0.000042615519839, 0.0 ] ] ] } }
]
}
8 changes: 8 additions & 0 deletions tests/star_clockwise.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "FeatureCollection",
"name": "star_clockwise",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::3857" } },
"features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 4.248, 5.366808338807478, 0.0 ], [ 4.639186245295105, 4.360047208387124, 0.0 ], [ 5.598379601811539, 4.12166779434162, 0.0 ], [ 4.860538558337359, 3.571124861903194, 0.0 ], [ 5.229754172001015, 2.522008335905782, 0.0 ], [ 4.497293736934685, 3.100041734146602, 0.0 ], [ 3.815820837225469, 2.471208335853966, 0.0 ], [ 3.884318100817675, 3.503016457890193, 0.0 ], [ 3.288369565703914, 3.9457210839747, 0.0 ], [ 3.935399403827426, 4.31464160571179, 0.0 ], [ 4.248, 5.366808338807478, 0.0 ] ] ] } }
]
}
8 changes: 8 additions & 0 deletions tests/star_counterclockwise.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "FeatureCollection",
"name": "star_counterclockwise",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::3857" } },
"features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 4.247620837665905, 5.366808338807478, 0.0 ], [ 3.951287504030311, 4.139141670888591, 0.0 ], [ 2.732087502786728, 4.232275004316921, 0.0 ], [ 4.095220837510457, 3.427941670163167, 0.0 ], [ 3.587220836992297, 2.132541668841859, 0.0 ], [ 4.501620837924985, 3.385608336786654, 0.0 ], [ 5.593820839039028, 2.047875002088833, 0.0 ], [ 5.145087505247988, 3.427941670163167, 0.0 ], [ 6.457420839919901, 4.274608337693434, 0.0 ], [ 4.77255417153467, 4.215341670966315, 0.0 ], [ 4.247620837665905, 5.366808338807478, 0.0 ] ] ] } }
]
}
8 changes: 8 additions & 0 deletions tests/star_zx_counter_clockwise.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "FeatureCollection",
"name": "star_zx_counter_clockwise",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::3857" } },
"features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 4.248, 5.366808338807478, 500.0 ], [ 4.639186245295105, 4.360047208387124, 400.0 ], [ 5.598379601811539, 4.12166779434162, 300.0 ], [ 4.860538558337359, 3.571124861903194, 200.0 ], [ 5.229754172001015, 2.522008335905782, 0.0 ], [ 4.497293736934685, 3.100041734146602, 100.0 ], [ 3.815820837225469, 2.471208335853966, 0.0 ], [ 3.884318100817675, 3.503016457890193, 200.0 ], [ 3.288369565703914, 3.9457210839747, 3.0 ], [ 3.935399403827426, 4.31464160571179, 400.0 ], [ 4.248, 5.366808338807478, 500.0 ] ] ] } }
]
}

0 comments on commit 4c46614

Please sign in to comment.