Skip to content

Commit

Permalink
Add test for winding order when triangulating
Browse files Browse the repository at this point in the history
  • Loading branch information
autra committed Mar 25, 2022
1 parent 6381ce9 commit fa012d7
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 0 deletions.
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 ] ] ] } }
]
}
199 changes: 199 additions & 0 deletions tests/test_wkb_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import pytest
import numpy as np

from py3dtiles import wkb_utils


@pytest.fixture
def clockwise_star():
with open('./tests/star_clockwise.geojson', 'r') as f:
star_geo = json.load(f)
coords = star_geo['features'][0]['geometry']['coordinates']
# triangulate expects the coordinates to be numpy array
polygon = coords[0]
for i in range(len(polygon)):
polygon[i] = np.array(polygon[i], dtype=np.float32)
# triangulate implicitly use wkb format, which is not self-closing
del polygon[-1]
return coords


@pytest.fixture
def counterclockwise_star():
with open('./tests/star_counterclockwise.geojson', 'r') as f:
star_geo = json.load(f)
coords = star_geo['features'][0]['geometry']['coordinates']
# triangulate expects the coordinates to be numpy array
polygon = coords[0]
for i in range(len(polygon)):
polygon[i] = np.array(polygon[i], dtype=np.float32)
# triangulate implicitly use wkb format, which is not self-closing
del polygon[-1]
return coords


@pytest.fixture
def counterclockwise_zx_star():
with open('./tests/star_zx_counter_clockwise.geojson', 'r') as f:
star_geo = json.load(f)
coords = star_geo['features'][0]['geometry']['coordinates']
# triangulate expects the coordinates to be numpy array
polygon = coords[0]
for i in range(len(polygon)):
polygon[i] = np.array(polygon[i], dtype=np.float32)
# triangulate implicitly use wkb format, which is not self-closing
del polygon[-1]
return coords


@pytest.fixture
def big_poly():
with open('./tests/big_polygon_counter_clockwise.geojson', 'r') as f:
big_poly = json.load(f)
coords = big_poly['features'][0]['geometry']['coordinates']
# triangulate expects the coordinates to be numpy array
polygon = coords[0]
for i in range(len(polygon)):
polygon[i] = np.array(polygon[i], dtype=np.float32)
# triangulate implicitly use wkb format, which is not self-closing
del polygon[-1]
return coords


@pytest.fixture
def complex_polygon():
# tricky polygon 1:
# 0x---------x 4
# \ |
# \ |
# 1 x |
# / |
# / |
# 2x---------x 3
# the first few vertices seems to indicate an inverse winding order
return [
[
np.array([0, 1, 0], dtype=np.float32),
np.array([0.5, 0.5, 0], dtype=np.float32),
np.array([0, 0, 0], dtype=np.float32),
np.array([1, 0, 0], dtype=np.float32),
np.array([1, 1, 0], dtype=np.float32)
]
]


def test_triangulate_winding_order_simple():
# simple case: a square on xy plane, counter-clockwise
polygon = [
[
np.array([0, 0, 0], dtype=np.float32),
np.array([1, 0, 0], dtype=np.float32),
np.array([1, 1, 0], dtype=np.float32),
np.array([0, 1, 0], dtype=np.float32)
]
]

triangles = wkb_utils.triangulate(polygon)
assert len(triangles[0]) == 2, 'Should generate 2 triangles'
assert \
all(np.cross(
triangles[0][0][1] - triangles[0][0][0],
triangles[0][0][2] - triangles[0][0][0]) == np.array([0, 0, 1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: counter-clockwise (triangle 1)'
assert \
all(np.cross(
triangles[0][1][1] - triangles[0][1][0],
triangles[0][1][2] - triangles[0][1][0]) == np.array([0, 0, 1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: counter-clockwise (triangle 2)'

# simple case 2: a square on xy plane, clockwise
polygon = [
[
np.array([0, 0, 0], dtype=np.float32),
np.array([0, 1, 0], dtype=np.float32),
np.array([1, 1, 0], dtype=np.float32),
np.array([1, 0, 0], dtype=np.float32)
]
]
triangles = wkb_utils.triangulate(polygon)
assert len(triangles[0]) == 2, 'Should generate 2 triangles'
assert \
all(np.cross(
triangles[0][0][1] - triangles[0][0][0],
triangles[0][0][2] - triangles[0][0][0]) == np.array([0, 0, -1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: clockwise (triangle1)'
assert \
all(np.cross(
triangles[0][1][1] - triangles[0][1][0],
triangles[0][1][2] - triangles[0][1][0]) == np.array([0, 0, -1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: clockwise (triangle2)'


def test_triangulate_winding_order_complex(complex_polygon):
triangles = wkb_utils.triangulate(complex_polygon)
assert len(triangles[0]) == 3, 'Should generate 2 triangles'
crossprod_triangle1 = np.cross(
triangles[0][0][1] - triangles[0][0][0],
triangles[0][0][2] - triangles[0][0][0])
crossprod_triangle1 /= np.linalg.norm(crossprod_triangle1)
assert \
all(crossprod_triangle1 == np.array([0, 0, 1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: counter-clockwise'


def test_triangulate_winding_order_stars(clockwise_star):
triangles = wkb_utils.triangulate(clockwise_star)
crossprod_triangle1 = np.cross(
triangles[0][0][1] - triangles[0][0][0],
triangles[0][0][2] - triangles[0][0][0])
crossprod_triangle1 /= np.linalg.norm(crossprod_triangle1)
assert all(crossprod_triangle1 == np.array([0, 0, -1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: clockwise'


def test_triangulate_winding_order_counter_clockwise_stars(counterclockwise_star):
triangles = wkb_utils.triangulate(counterclockwise_star)
crossprod_triangle1 = np.cross(
triangles[0][0][1] - triangles[0][0][0],
triangles[0][0][2] - triangles[0][0][0])
crossprod_triangle1 /= np.linalg.norm(crossprod_triangle1)
assert all(crossprod_triangle1 == np.array([0, 0, 1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: counter-clockwise'


def test_triangulate_winding_order_counter_clockwise_zx_stars(counterclockwise_zx_star):
triangles = wkb_utils.triangulate(counterclockwise_zx_star)
crossprod_triangle1 = np.cross(
triangles[0][0][1] - triangles[0][0][0],
triangles[0][0][2] - triangles[0][0][0])
crossprod_triangle1 /= np.linalg.norm(crossprod_triangle1)
# check the 2nd dimension is the largest by far and is positive
assert crossprod_triangle1[1] > 0.8,\
'Check winding order is coherent with vertex order: counter-clockwise in zx plane'


def test_big_poly_winding_order(big_poly):
triangles = wkb_utils.triangulate(big_poly)
crossprod_triangle1 = np.cross(
triangles[0][0][1] - triangles[0][0][0],
triangles[0][0][2] - triangles[0][0][0])
crossprod_triangle1 /= np.linalg.norm(crossprod_triangle1)
assert all(crossprod_triangle1 == np.array([0, 0, 1], dtype=np.float32)), \
'Check winding order is coherent with vertex order: counter-clockwise'

################
# benchmarking #
################
def test_benchmark_triangulate(complex_polygon, benchmark):
benchmark(wkb_utils.triangulate, complex_polygon)


def test_benchmark_star(clockwise_star, benchmark):
benchmark(wkb_utils.triangulate, clockwise_star)


def test_benchmark_big_poly(big_poly, benchmark):
benchmark(wkb_utils.triangulate, big_poly)

0 comments on commit fa012d7

Please sign in to comment.