Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
9.2.2023: Due to updates GitLab will be unavailable for some minutes between 9:00 and 11:00.
Open sidebar
vadere
vadere
Commits
2db821e0
Commit
2db821e0
authored
Nov 13, 2016
by
Benedikt Zoennchen
Browse files
add adpative triangulation implementation
parent
43e77c48
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
VadereUtils/src/org/vadere/util/delaunay/BowyerWatson.java
0 → 100644
View file @
2db821e0
package
org.vadere.util.delaunay
;
import
org.apache.commons.lang3.tuple.ImmutablePair
;
import
org.apache.commons.lang3.tuple.ImmutableTriple
;
import
org.apache.commons.lang3.tuple.Pair
;
import
org.apache.commons.lang3.tuple.Triple
;
import
org.vadere.util.geometry.shapes.VCircle
;
import
org.vadere.util.geometry.shapes.VLine
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VRectangle
;
import
org.vadere.util.geometry.shapes.VTriangle
;
import
javax.swing.*
;
import
java.awt.*
;
import
java.util.*
;
import
java.util.List
;
import
java.util.function.BiFunction
;
import
java.util.function.Predicate
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
import
java.util.stream.Stream
;
/**
* @author Benedikt Zoennchen
*
* This class is for computing the DelaunayTriangulation using the BowyerWatson-Algorithm. In average the algorithm should perfom in O(n log(n)) but
* in degenerated cases its runtime can be in O(n^2) where n is the number of points.
*/
public
class
BowyerWatson
<
P
extends
VPoint
>
{
private
List
<
Triple
<
P
,
P
,
P
>>
triangles
;
private
Collection
<
P
>
points
;
private
List
<
P
>
initPoints
;
private
final
BiFunction
<
Double
,
Double
,
P
>
pointConstructor
;
public
BowyerWatson
(
final
Collection
<
P
>
points
,
final
BiFunction
<
Double
,
Double
,
P
>
pointConstructor
)
{
this
.
points
=
points
;
this
.
pointConstructor
=
pointConstructor
;
}
public
void
execute
()
{
P
max
=
points
.
parallelStream
().
reduce
(
pointConstructor
.
apply
(
Double
.
MIN_VALUE
,
Double
.
MIN_VALUE
),
(
a
,
b
)
->
pointConstructor
.
apply
(
Math
.
max
(
a
.
getX
(),
b
.
getX
()),
Math
.
max
(
a
.
getY
(),
b
.
getY
())));
P
min
=
points
.
parallelStream
().
reduce
(
pointConstructor
.
apply
(
Double
.
MIN_VALUE
,
Double
.
MIN_VALUE
),
(
a
,
b
)
->
pointConstructor
.
apply
(
Math
.
min
(
a
.
getX
(),
b
.
getX
()),
Math
.
min
(
a
.
getY
(),
b
.
getY
())));
VRectangle
bound
=
new
VRectangle
(
min
.
getX
(),
min
.
getY
(),
max
.
getX
()-
min
.
getX
(),
max
.
getY
()-
min
.
getY
());
init
(
bound
);
points
.
stream
().
forEach
(
point
->
handle
(
point
));
cleanUp
();
}
public
List
<
Triple
<
P
,
P
,
P
>>
getTriangles
()
{
return
triangles
;
}
public
List
<
VTriangle
>
getVTriangles
()
{
return
triangles
.
stream
().
map
(
this
::
pointsToTriangle
).
collect
(
Collectors
.
toList
());
}
public
Set
<
VLine
>
getEdges
()
{
return
triangles
.
parallelStream
().
flatMap
(
triangle
->
Stream
.
of
(
new
VTriangle
(
triangle
.
getLeft
(),
triangle
.
getMiddle
(),
triangle
.
getRight
()).
getLines
())).
collect
(
Collectors
.
toSet
());
}
private
void
init
(
final
VRectangle
bound
)
{
triangles
=
new
ArrayList
<>();
initPoints
=
new
ArrayList
<>();
Triple
<
P
,
P
,
P
>
superTriangle
=
getSuperTriangle
(
bound
);
triangles
.
add
(
superTriangle
);
initPoints
.
add
(
superTriangle
.
getLeft
());
initPoints
.
add
(
superTriangle
.
getMiddle
());
initPoints
.
add
(
superTriangle
.
getRight
());
}
private
Triple
<
P
,
P
,
P
>
getSuperTriangle
(
final
VRectangle
bound
)
{
double
gap
=
1.0
;
double
max
=
Math
.
max
(
bound
.
getWidth
(),
bound
.
getHeight
());
P
p1
=
pointConstructor
.
apply
(
bound
.
getX
()
-
max
-
gap
,
bound
.
getY
()
-
gap
);
P
p2
=
pointConstructor
.
apply
(
bound
.
getX
()
+
2
*
max
+
gap
,
bound
.
getY
()
-
gap
);
P
p3
=
pointConstructor
.
apply
(
bound
.
getX
()
+
(
max
+
2
*
gap
)/
2
,
bound
.
getY
()
+
2
*
max
+
gap
);
return
ImmutableTriple
.
of
(
p1
,
p2
,
p3
);
}
private
void
handle
(
final
P
point
)
{
HashSet
<
Line
>
edges
=
new
HashSet
<>();
Map
<
Boolean
,
List
<
Triple
<
P
,
P
,
P
>>>
partition
=
triangles
.
parallelStream
().
collect
(
Collectors
.
partitioningBy
(
t
->
pointsToTriangle
(
t
).
isInCircumscribedCycle
(
point
)));
List
<
Triple
<
P
,
P
,
P
>>
badTriangles
=
partition
.
get
(
true
);
triangles
=
partition
.
get
(
false
);
IntStream
s
;
HashSet
<
Line
>
toRemove
=
new
HashSet
<>();
// duplicated edges
badTriangles
.
stream
().
flatMap
(
t
->
getEdges
(
t
).
stream
()).
forEach
(
line
->
{
if
(!
edges
.
add
(
line
))
{
toRemove
.
add
(
line
);
}
});
toRemove
.
stream
().
forEach
(
removeEdge
->
edges
.
remove
(
removeEdge
));
// identifier ?
edges
.
stream
().
forEach
(
edge
->
triangles
.
add
(
Triple
.
of
(
edge
.
p1
,
edge
.
p2
,
point
)));
}
private
List
<
Line
>
getEdges
(
Triple
<
P
,
P
,
P
>
triangle
)
{
List
<
Line
>
list
=
new
ArrayList
<>();
list
.
add
(
new
Line
(
triangle
.
getLeft
(),
triangle
.
getMiddle
()));
list
.
add
(
new
Line
(
triangle
.
getMiddle
(),
triangle
.
getRight
()));
list
.
add
(
new
Line
(
triangle
.
getRight
(),
triangle
.
getLeft
()));
return
list
;
}
private
void
cleanUp
()
{
triangles
=
triangles
.
stream
().
filter
(
triangle
->
!
isTriangleConnectedToInitialPoints
(
triangle
)).
collect
(
Collectors
.
toList
());
}
private
boolean
isTriangleConnectedToInitialPoints
(
final
Triple
<
P
,
P
,
P
>
trianglePoints
)
{
return
Stream
.
of
(
pointsToTriangle
(
trianglePoints
).
getLines
()).
anyMatch
(
edge
->
{
VPoint
p1
=
new
VPoint
(
edge
.
getP1
().
getX
(),
edge
.
getP1
().
getY
());
VPoint
p2
=
new
VPoint
(
edge
.
getP2
().
getX
(),
edge
.
getP2
().
getY
());
return
initPoints
.
stream
().
anyMatch
(
initPoint
->
p1
.
equals
(
initPoint
)
||
p2
.
equals
(
initPoint
));
});
}
private
VTriangle
pointsToTriangle
(
Triple
<
P
,
P
,
P
>
points
)
{
return
new
VTriangle
(
points
.
getLeft
(),
points
.
getMiddle
(),
points
.
getRight
());
}
private
class
Line
{
final
P
p1
;
final
P
p2
;
private
Line
(
P
p1
,
P
p2
)
{
this
.
p1
=
p1
;
this
.
p2
=
p2
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
return
true
;
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
return
false
;
Line
line
=
(
Line
)
o
;
return
(
p1
.
equals
(
line
.
p1
)
&&
p2
.
equals
(
line
.
p2
))
||
(
p2
.
equals
(
line
.
p1
)
&&
p1
.
equals
(
line
.
p2
));
}
@Override
public
int
hashCode
()
{
return
p1
.
hashCode
()
*
p2
.
hashCode
();
}
}
// TODO: the following code can be deleted, this is only for visual checks
public
static
void
main
(
String
[]
args
)
{
// TODO Auto-generated method stub
int
height
=
1000
;
int
width
=
1000
;
int
max
=
Math
.
max
(
height
,
width
);
Set
<
VPoint
>
points
=
new
HashSet
<>();
/*points.add(new VPoint(20,20));
points.add(new VPoint(20,40));
points.add(new VPoint(75,53));
points.add(new VPoint(80,70));*/
Random
r
=
new
Random
();
for
(
int
i
=
0
;
i
<
10000
;
i
++)
{
VPoint
point
=
new
VPoint
(
width
*
r
.
nextDouble
(),
height
*
r
.
nextDouble
());
points
.
add
(
point
);
}
BowyerWatson
<
VPoint
>
bw
=
new
BowyerWatson
<
VPoint
>(
points
,
(
x
,
y
)
->
new
VPoint
(
x
,
y
));
bw
.
execute
();
Set
<
VLine
>
edges
=
bw
.
getEdges
();
JFrame
window
=
new
JFrame
();
window
.
setDefaultCloseOperation
(
WindowConstants
.
EXIT_ON_CLOSE
);
window
.
setBounds
(
0
,
0
,
max
,
max
);
window
.
getContentPane
().
add
(
new
Lines
(
edges
,
points
,
max
));
window
.
setVisible
(
true
);
}
private
static
class
Lines
extends
JComponent
{
private
Set
<
VLine
>
edges
;
private
Set
<
VPoint
>
points
;
private
final
int
max
;
public
Lines
(
final
Set
<
VLine
>
edges
,
final
Set
<
VPoint
>
points
,
final
int
max
){
this
.
edges
=
edges
;
this
.
points
=
points
;
this
.
max
=
max
;
}
public
void
paint
(
Graphics
g
)
{
Graphics2D
g2
=
(
Graphics2D
)
g
;
g2
.
setBackground
(
Color
.
white
);
g2
.
setStroke
(
new
BasicStroke
(
1.0f
));
g2
.
setColor
(
Color
.
gray
);
edges
.
stream
().
forEach
(
edge
->
{
Shape
k
=
new
VLine
(
edge
.
getP1
().
getX
(),
edge
.
getP1
().
getY
(),
edge
.
getP2
().
getX
(),
edge
.
getP2
().
getY
());
g2
.
draw
(
k
);
});
points
.
stream
().
forEach
(
point
->
{
VCircle
k
=
new
VCircle
(
point
.
getX
(),
point
.
getY
(),
1.0
);
g2
.
draw
(
k
);
});
}
}
public
void
removeTriangleIf
(
final
Predicate
<
Triple
<
P
,
P
,
P
>>
predicate
)
{
triangles
.
removeIf
(
predicate
);
}
}
VadereUtils/src/org/vadere/util/geometry/shapes/VTriangle.java
View file @
2db821e0
...
...
@@ -171,6 +171,10 @@ public class VTriangle extends VPolygon {
return
getCircumcenter
().
distance
(
point
)
<
getCircumscribedRadius
();
}
public
boolean
isInCircumscribedCycle
(
final
VPoint
point
)
{
return
getCircumcenter
().
distance
(
point
)
<
getCircumscribedRadius
();
}
/**
* Computes the inward facing normal vector for the given points of the
* triangle.
...
...
@@ -196,10 +200,6 @@ public class VTriangle extends VPolygon {
return
this
.
p1
.
equals
(
point
)
||
this
.
p2
.
equals
(
point
)
||
this
.
p3
.
equals
(
point
);
}
public
VLine
[]
getLines
()
{
return
lines
;
}
public
Stream
<
VLine
>
getLineStream
()
{
return
Arrays
.
stream
(
getLines
());
}
...
...
@@ -215,4 +215,8 @@ public class VTriangle extends VPolygon {
public
String
toString
()
{
return
p1
+
"-"
+
p2
+
"-"
+
p3
;
}
public
VLine
[]
getLines
()
{
return
lines
;
}
}
VadereUtils/src/org/vadere/util/triangulation/adaptive/IndexedVLine.java
0 → 100644
View file @
2db821e0
package
org.vadere.util.triangulation.adaptive
;
import
org.apache.commons.lang3.tuple.Pair
;
import
org.vadere.util.geometry.shapes.VLine
;
public
class
IndexedVLine
extends
VLine
{
private
final
IndexedVPoint
p1
;
private
final
IndexedVPoint
p2
;
public
IndexedVLine
(
IndexedVPoint
p1
,
IndexedVPoint
p2
)
{
super
(
p1
,
p2
);
this
.
p1
=
p1
;
this
.
p2
=
p2
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
obj
==
null
)
return
false
;
if
(
obj
==
this
)
return
true
;
if
(
obj
.
getClass
()
!=
getClass
())
return
false
;
IndexedVLine
line
=
(
IndexedVLine
)
obj
;
return
line
.
getP1
().
equals
(
getP1
())
&&
line
.
getP2
().
equals
(
getP2
())
||
line
.
getP2
().
equals
(
getP1
())
&&
line
.
getP1
().
equals
(
getP2
());
}
@Override
public
int
hashCode
()
{
return
p1
.
hashCode
()
*
p2
.
hashCode
();
}
public
Pair
<
Integer
,
Integer
>
getId
()
{
return
Pair
.
of
(
p1
.
getId
(),
p2
.
getId
());
}
}
VadereUtils/src/org/vadere/util/triangulation/adaptive/IndexedVPoint.java
0 → 100644
View file @
2db821e0
package
org.vadere.util.triangulation.adaptive
;
import
org.vadere.util.geometry.shapes.VPoint
;
/**
* Created by bzoennchen on 10.11.16.
*/
public
class
IndexedVPoint
extends
VPoint
{
private
int
id
;
public
IndexedVPoint
(
final
VPoint
point
,
final
int
id
){
this
(
point
.
getX
(),
point
.
getY
(),
id
);
}
public
IndexedVPoint
(
final
double
x
,
final
double
y
,
final
int
id
){
super
(
x
,
y
);
this
.
id
=
id
;
}
public
IndexedVPoint
subtract
(
VPoint
point
)
{
return
new
IndexedVPoint
(
super
.
subtract
(
point
),
id
);
}
public
int
getId
()
{
return
id
;
}
public
void
setId
(
int
id
)
{
this
.
id
=
id
;
}
}
VadereUtils/src/org/vadere/util/triangulation/adaptive/PSDistmesh.java
View file @
2db821e0
...
...
@@ -20,7 +20,7 @@ import java.util.*;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
public
class
PSDistmesh
{
public
class
PSDistmesh
{
private
Set
<
MeshPoint
>
points
=
new
HashSet
<>();
private
Set
<
MLine
<
MeshPoint
>>
lines
=
new
HashSet
<>();
private
IncrementalTriangulation
<
MeshPoint
,
PHalfEdge
<
MeshPoint
>,
PFace
<
MeshPoint
>>
bowyerWatson
;
...
...
@@ -96,7 +96,7 @@ public class PSDistmesh {
}
public
boolean
hasMaximalSteps
()
{
return
steps
>=
Parameters
.
MAX_NUMBER_OF_STEPS
;
return
steps
>=
1000
;
}
/**
...
...
VadereUtils/src/org/vadere/util/triangulation/adaptive/Parameters.java
View file @
2db821e0
...
...
@@ -4,18 +4,17 @@ package org.vadere.util.triangulation.adaptive;
* Created by Matimati-ka on 27.09.2016.
*/
public
class
Parameters
{
final
static
double
TOL
=
.
1
;
final
static
double
FSCALE
=
1.0
;
final
static
double
DELTAT
=
0.2
;
public
final
static
double
h0
=
0.15
;
public
final
static
boolean
uniform
=
false
;
public
final
static
String
method
=
"Distmesh"
;
// "Distmesh" or "Density"
final
static
double
qualityMeasurement
=
0.95
;
final
static
double
MINIMUM
=
0.25
;
final
static
double
DENSITYWEIGHT
=
2
;
final
static
int
NPOINTS
=
100000
;
final
static
int
SAMPLENUMBER
=
10
;
final
static
int
SAMPLEDIVISION
=
10
;
static
final
int
SEGMENTDIVISION
=
0
;
final
static
int
MAX_NUMBER_OF_STEPS
=
20
;
final
static
double
TOL
=
.
1
;
final
static
double
FSCALE
=
1.2
;
final
static
double
DELTAT
=
0.2
;
public
final
static
double
h0
=
0.15
;
public
final
static
boolean
uniform
=
false
;
public
final
static
String
method
=
"Density"
;
// "Distmesh" or "Density"
final
static
double
qualityMeasurement
=
0.875
;
final
static
double
MINIMUM
=
0.25
;
final
static
double
DENSITYWEIGHT
=
2
;
final
static
int
NPOINTS
=
100000
;
final
static
int
SAMPLENUMBER
=
10
;
final
static
int
SAMPLEDIVISION
=
10
;
static
final
int
SEGMENTDIVISION
=
0
;
}
VadereUtils/src/org/vadere/util/triangulation/adaptive/PerssonStrangDistmesh.java
View file @
2db821e0
This diff is collapsed.
Click to expand it.
VadereUtils/src/org/vadere/util/triangulation/adaptive/TestEnhancedVersion.java
View file @
2db821e0
...
...
@@ -4,25 +4,23 @@ import org.vadere.util.geometry.shapes.VRectangle;
import
org.vadere.util.geometry.shapes.VShape
;
import
javax.swing.*
;
import
java.util.
*
;
import
java.awt.*
;
import
java.util.
ArrayList
;
/**
* Created by Matimati-ka on 27.09.2016.
*/
public
class
TestEnhancedVersion
extends
JFrame
{
ArrayList
<
VShape
>
obstacles
;
private
TestEnhancedVersion
()
{
// VRectangle bbox = new VRectangle(0,0,100,100);
// ArrayList<VRectangle> obs = new ArrayList<VRectangle>() {{ add(new VRectangle(20,20,20,20));}};
double
h0
=
3.0
;
long
now
=
System
.
currentTimeMillis
()
;
double
h0
=
1
;
VRectangle
bbox
=
new
VRectangle
(
0
,
0
,
300
,
300
);
long
now
=
System
.
currentTimeMillis
();
VRectangle
bbox
=
new
VRectangle
(
0
,
0
,
300
,
300
);
// Path2D.Double test = new Path2D.Double();
// test.moveTo(30,30);
// test.lineTo(90,80);
...
...
@@ -32,39 +30,56 @@ public class TestEnhancedVersion extends JFrame {
// test.lineTo(30,30);
// VPolygon p = new VPolygon(test);
double
height
=
300
;
double
width
=
300
;
java
.
util
.
List
<
VShape
>
boundingBox
=
new
ArrayList
<
VShape
>()
{{
add
(
new
VRectangle
(
0
,
0
,
5
,
width
));
add
(
new
VRectangle
(
0
,
0
,
width
,
5
));
add
(
new
VRectangle
(
width
-
5
,
0
,
5
,
height
));
add
(
new
VRectangle
(
0
,
height
-
5
,
5
,
height
));
}};
PSDistmesh
meshGenerator
=
new
PSDistmesh
(
bbox
,
boundingBox
,
h0
,
false
);
ArrayList
<
VShape
>
obstacles
=
new
ArrayList
<
VShape
>()
{{
// add(new VRectangle(0.6*400, 0.6*400, 0.2*400, 5));
// add(new VRectangle(0.6*400, 0.65*400, 0.2*400, 5));
add
(
new
VRectangle
(
0.65
*
300
,
-
5
,
0.1
*
300
,
0.6
*
300
));
add
(
new
VRectangle
(
0.65
*
300
,
0.7
*
300
,
0.1
*
300
,
0.3
*
300
));
// add(p);
}};
ArrayList
<
VShape
>
fhIncluded
=
new
ArrayList
<
VShape
>()
{{
// add(p);
// add(new VRectangle(0.6*400, 0.6*400, 0.2*400, 5));
// add(new VRectangle(0.6*400, 0.65*400, 0.2*400, 5));
add
(
new
VRectangle
(
0.65
*
300
,
-
5
,
0.1
*
300
,
0.6
*
300
));
add
(
new
VRectangle
(
0.65
*
300
,
0.7
*
300
,
0.1
*
300
,
0.3
*
300
));
}};
PerssonStrangDistmesh
psd
=
new
PerssonStrangDistmesh
(
bbox
,
obstacles
,
h0
,
false
,
l
->
0.0
,
"Distmesh"
);
System
.
out
.
println
(
System
.
currentTimeMillis
()-
now
);
now
=
System
.
currentTimeMillis
();
System
.
out
.
println
(
System
.
currentTimeMillis
()-
now
);
PSDistmeshPanel
distmeshPanel
=
new
PSDistmeshPanel
(
meshGenerator
,
1000
,
800
);
JFrame
frame
=
distmeshPanel
.
display
();
frame
.
setVisible
(
true
);
double
quality
=
meshGenerator
.
qualityCheck
();
DrawPanel
JPanel
=
new
DrawPanel
(
psd
);
setSize
(
1000
,
800
);
add
(
JPanel
);
setDefaultCloseOperation
(
WindowConstants
.
EXIT_ON_CLOSE
);
setVisible
(
true
);
}
private
class
DrawPanel
extends
Canvas
{
private
PerssonStrangDistmesh
t
;
while
(
quality
<
0.95
)
{
System
.
out
.
println
(
"quality:"
+
quality
);
meshGenerator
.
step
();
/*try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
distmeshPanel
.
repaint
();
quality
=
meshGenerator
.
qualityCheck
();
private
DrawPanel
(
PerssonStrangDistmesh
t
)
{
this
.
t
=
t
;
}
}
@Override
public
void
paint
(
Graphics
g
)
{
Graphics2D
graphics
=
(
Graphics2D
)
g
;
graphics
.
translate
(
125
,
125
);
graphics
.
setColor
(
Color
.
BLACK
);
t
.
getTriangulation
().
getVTriangles
().
parallelStream
().
forEach
(
t
->
graphics
.
draw
(
t
));
// graphics.setColor(Color.RED);
// tc.triangulation.getTriangles().parallelStream().forEach(graphics::draw);
}
}
public
static
void
main
(
String
[]
args
)
{
new
TestEnhancedVersion
();
...
...
VadereUtils/src/org/vadere/util/triangulation/adaptive/TestEnhancedVersion2.java
View file @
2db821e0
...
...
@@ -65,8 +65,6 @@ public class TestEnhancedVersion2 extends JFrame {
setDefaultCloseOperation
(
WindowConstants
.
EXIT_ON_CLOSE
);
setVisible
(
true
);
new
Thread
(()
->
meshGenerator
.
execude
()).
start
();
while
(
true
)
{
try
{
Thread
.
sleep
(
1000
);
...
...
@@ -99,7 +97,7 @@ public class TestEnhancedVersion2 extends JFrame {
graphics
.
translate
(
5
,
5
);
graphics
.
setColor
(
Color
.
BLACK
);
meshGenerator
.
getTriangulation
().
getTriangles
().
parallelStream
().
forEach
(
t
->
graphics
.
draw
(
t
));
//
meshGenerator.getTriangulation().getTriangles().parallelStream().forEach(t -> graphics.draw(t));
graphics
.
setColor
(
Color
.
GRAY
);
for
(
VShape
obstacle
:
obstacles
)
{
...
...
Write
Preview
Supports
Markdown
0%
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!
Cancel
Please
register
or
sign in
to comment