Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
Thick Section Point Density
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
QIM
Tools
Thick Section Point Density
Commits
83a6dcbf
Commit
83a6dcbf
authored
3 years ago
by
hanste
Browse files
Options
Downloads
Patches
Plain Diff
Added files from local to remote
parent
ecff0650
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
polygon_triangulate.py
+221
-0
221 additions, 0 deletions
polygon_triangulate.py
with
221 additions
and
0 deletions
polygon_triangulate.py
0 → 100644
+
221
−
0
View file @
83a6dcbf
import
numpy
as
np
def
psign
(
p1
,
p2
,
p3
):
return
(
p1
[
0
]
-
p3
[
0
])
*
(
p2
[
1
]
-
p3
[
1
])
-
(
p2
[
0
]
-
p3
[
0
])
*
(
p1
[
1
]
-
p3
[
1
]);
def
PointInTriangle
(
pt
,
v1
,
v2
,
v3
):
d1
=
psign
(
pt
,
v1
,
v2
)
d2
=
psign
(
pt
,
v2
,
v3
)
d3
=
psign
(
pt
,
v3
,
v1
)
has_neg
=
(
d1
<
0
)
|
(
d2
<
0
)
|
(
d3
<
0
)
has_pos
=
(
d1
>
0
)
|
(
d2
>
0
)
|
(
d3
>
0
)
return
not
(
has_neg
&
has_pos
)
def
get_edges
(
tri
):
return
[(
tri
[
0
],
tri
[
1
]),
(
tri
[
0
],
tri
[
2
]),
(
tri
[
1
],
tri
[
2
])]
def
default_add
(
d
,
e
,
V
,
ti
):
if
e
in
d
:
d
[
e
][
1
].
append
(
ti
)
else
:
a
,
b
=
e
length
=
np
.
linalg
.
norm
(
V
[
a
]
-
V
[
b
])
if
a
==
b
:
raise
ValueError
(
'
Adding edge with same index:
'
,
e
,
ti
)
d
[
e
]
=
[
length
,
[
ti
]]
return
d
def
get_all_edges
(
V
,
T
):
E_dict
=
{}
for
n
,
tri
in
enumerate
(
T
):
E
=
get_edges
(
tri
)
# outputs list of edges with sorted vertex indices. eg [(4,7),(4,8),(7,8)]
for
e
in
E
:
a
,
b
=
e
length
=
np
.
linalg
.
norm
(
V
[
a
]
-
V
[
b
])
E_dict
=
default_add
(
E_dict
,
e
,
V
,
n
)
return
E_dict
def
split_long_edges
(
V
,
T
):
E_dict
=
get_all_edges
(
V
,
T
)
target_length
=
np
.
median
([
length
for
length
,
_
in
E_dict
.
values
()])
run
=
True
n_init_V
=
len
(
V
)
while
run
:
run
=
False
max_length
=
0
for
cur_e
in
E_dict
.
keys
():
cur_length
,
cur_Ti
=
E_dict
[
cur_e
]
if
cur_length
>
max_length
:
max_length
=
cur_length
e
=
cur_e
Ti
=
cur_Ti
a
,
b
=
cur_e
if
max_length
>
target_length
:
run
=
True
# make a new vertex
Vnew
=
V
[
a
]
+
V
[
b
]
N
=
2.0
Vnew
=
Vnew
/
N
new_length
=
np
.
linalg
.
norm
(
Vnew
-
V
[
a
])
n
=
len
(
V
)
V
=
np
.
concatenate
([
V
,
[
Vnew
]],
axis
=
0
)
for
ti
in
sorted
(
Ti
)[::
-
1
]:
# find the vertex index which a,b is not co-linear with
m
=
[
i
for
i
in
T
[
ti
]
if
i
!=
a
and
i
!=
b
][
0
]
old
=
np
.
pad
(
np
.
array
([
V
[
ii
]
for
ii
in
T
[
ti
]]),
((
1
,
0
),
(
0
,
0
)),
mode
=
'
wrap
'
)
+
1
new1
=
np
.
pad
(
np
.
array
([
V
[
ii
]
for
ii
in
sorted
([
m
,
n
,
a
])]),
((
1
,
0
),
(
0
,
0
)),
mode
=
'
wrap
'
)
+
2
new2
=
np
.
pad
(
np
.
array
([
V
[
ii
]
for
ii
in
sorted
([
m
,
n
,
b
])]),
((
1
,
0
),
(
0
,
0
)),
mode
=
'
wrap
'
)
T
[
ti
]
=
sorted
([
m
,
n
,
a
])
# ADD m,n,a REM a,b,m
tj
=
len
(
T
)
T
.
append
(
sorted
([
m
,
n
,
b
]))
# ADD m,n,b
# add new edges
an
=
tuple
(
sorted
([
n
,
a
]))
am
=
tuple
(
sorted
([
m
,
a
]))
bn
=
tuple
(
sorted
([
n
,
b
]))
bm
=
tuple
(
sorted
([
m
,
b
]))
mn
=
tuple
(
sorted
([
m
,
n
]))
E_dict
[
tuple
(
sorted
([
m
,
b
]))][
1
]
=
[
tk
for
tk
in
E_dict
[
tuple
(
sorted
([
m
,
b
]))][
1
]
if
tk
!=
ti
]
cross_length
=
np
.
linalg
.
norm
(
V
[
m
]
-
V
[
n
])
E_dict
=
default_add
(
E_dict
,
an
,
V
,
ti
)
# ADD ti to an
E_dict
=
default_add
(
E_dict
,
bn
,
V
,
tj
)
# ADD tj to bn
E_dict
=
default_add
(
E_dict
,
bm
,
V
,
tj
)
# ADD tj to bm
E_dict
=
default_add
(
E_dict
,
mn
,
V
,
ti
)
# ADD ti to mn
E_dict
=
default_add
(
E_dict
,
mn
,
V
,
tj
)
# ADD tj to mn
del
E_dict
[
e
]
interior_vertex_indices
=
set
(
range
(
len
(
V
)))
for
e
in
E_dict
.
keys
():
if
len
(
E_dict
[
e
][
1
])
==
1
:
interior_vertex_indices
=
interior_vertex_indices
-
set
(
e
)
# Smooth interior triangulated points
for
_
in
range
(
100
):
for
i
in
interior_vertex_indices
:
Vs
=
[]
for
e
in
E_dict
.
keys
():
if
i
in
e
:
vn
=
[
j
for
j
in
e
if
j
!=
i
][
0
]
Vs
.
append
(
V
[
vn
])
Vnew
=
np
.
mean
(
Vs
,
axis
=
0
)
V
[
i
]
=
0.7
*
V
[
i
]
+
0.3
*
Vnew
return
V
,
T
def
polygon_triangulate
(
P
):
N
=
len
(
P
)
P3
=
np
.
pad
(
P
,
((
0
,
0
),
(
0
,
1
)))
angle_sum
=
0
angles
=
[]
exterior_angles
=
[]
T
=
[]
for
p1
,
p2
,
p3
in
zip
(
P3
,
np
.
roll
(
P3
,
-
1
,
axis
=
0
),
np
.
roll
(
P3
,
-
2
,
axis
=
0
)):
v1
=
p2
-
p1
v2
=
p3
-
p2
cross
=
np
.
cross
(
v1
,
v2
)
dot
=
np
.
clip
(
np
.
dot
(
v1
,
v2
)
/
(
np
.
linalg
.
norm
(
v1
)
*
np
.
linalg
.
norm
(
v2
)),
-
1
,
1
)
angle
=
np
.
sign
(
cross
[
2
])
*
np
.
arccos
(
dot
)
exterior_angles
.
append
(
angle
/
(
2
*
np
.
pi
)
*
360
)
indices
=
np
.
arange
(
N
)
if
np
.
sum
(
exterior_angles
)
<
0
:
indices
=
indices
[::
-
1
]
# iteratively add a trinagle and remove the index to the point which can no longer be part of another triangle
while
len
(
indices
)
>
2
:
best_i
=
0
best_j
=
0
best_k
=
0
best_n
=
0
best_length
=
np
.
inf
# iterate over the remaining points to find the best candidate
for
n
,
(
i
,
j
,
k
),
in
enumerate
(
zip
(
np
.
roll
(
indices
,
1
),
indices
,
np
.
roll
(
indices
,
-
1
))):
v1
=
P3
[
j
]
-
P3
[
i
]
v2
=
P3
[
k
]
-
P3
[
j
]
cross
=
np
.
cross
(
v1
,
v2
)
angle
=
np
.
arcsin
(
cross
[
2
]
/
(
np
.
linalg
.
norm
(
v1
)
*
np
.
linalg
.
norm
(
v2
)))
length
=
np
.
linalg
.
norm
(
v1
)
+
np
.
linalg
.
norm
(
v2
)
# pick the shortest triangle which is interior
if
angle
>
0
and
length
<
best_length
:
# check all point to see if one lies inside the triangle, skip in that case
contains_point
=
False
for
nn
in
range
(
N
):
if
nn
==
i
or
nn
==
j
or
nn
==
k
:
continue
if
PointInTriangle
(
P
[
nn
],
P
[
i
],
P
[
j
],
P
[
k
]):
contains_point
=
True
break
if
contains_point
:
continue
best_length
=
length
best_i
=
i
best_j
=
j
best_k
=
k
best_n
=
n
# add triangle and remove index to point which can no longer be part of another triangle
T
.
append
(
sorted
([
best_i
,
best_j
,
best_k
]))
indices
=
np
.
delete
(
indices
,
best_n
)
P
,
T
=
split_long_edges
(
P
,
T
)
return
exterior_angles
,
P
,
T
class
PlotTriangulation
:
colors
=
np
.
random
.
uniform
(
0.2
,
1
,(
2048
,
3
))
def
__init__
(
self
,
V
,
T
,
add_labels
=
True
):
import
matplotlib.pyplot
as
plt
V0
=
np
.
copy
(
V
)
if
np
.
argmax
(
np
.
max
(
V0
,
axis
=
0
))
==
1
:
V0
=
V0
[:,::
-
1
]
margins
=
(
np
.
max
(
V0
,
axis
=
0
)
-
np
.
min
(
V0
,
axis
=
0
))
*
0.05
V0
=
V0
-
np
.
min
(
V0
,
axis
=
0
)
+
margins
I
=
np
.
zeros
((
np
.
max
(
V0
[:,
1
]
+
1
+
margins
[
1
]).
astype
(
np
.
int32
),
np
.
max
(
V0
[:,
0
]
+
1
+
margins
[
0
]).
astype
(
np
.
int32
)))
plt
.
imshow
(
I
,
cmap
=
'
gray
'
)
plt
.
axis
(
'
off
'
)
plt
.
subplots_adjust
(
bottom
=
0
,
top
=
1
,
left
=
0
,
right
=
1
)
for
j
in
range
(
len
(
T
)):
tri
=
T
[
j
]
t1
=
plt
.
Polygon
(
V0
[
tri
,:],
alpha
=
0.7
,
color
=
PlotTriangulation
.
colors
[
j
%
2048
])
plt
.
gca
().
add_patch
(
t1
)
if
add_labels
:
plt
.
text
(
np
.
mean
(
V0
[
tri
,
0
]),
np
.
mean
(
V0
[
tri
,
1
]),
str
(
j
))
if
add_labels
:
for
i
,
v
in
enumerate
(
V0
):
plt
.
text
(
v
[
0
],
v
[
1
],
str
(
i
),
color
=
'
orange
'
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment