Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
vadere
vadere
Commits
4de6f544
Commit
4de6f544
authored
Feb 28, 2017
by
Benedikt Zoennchen
Browse files
implementation of a very generic half-edge data structure
parent
9bc26ce4
Changes
16
Show whitespace changes
Inline
Side-by-side
VadereUtils/src/org/vadere/util/geometry/mesh/DAGElement.java
View file @
4de6f544
package
org.vadere.util.geometry.mesh
;
package
org.vadere.util.geometry.mesh
;
import
org.apache.commons.lang3.tuple.Triple
;
import
org.apache.commons.lang3.tuple.Triple
;
import
org.vadere.util.geometry.mesh.inter.IFace
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VTriangle
;
import
org.vadere.util.geometry.shapes.VTriangle
;
public
class
DAGElement
<
P
extends
IPoint
>
{
import
java.util.List
;
private
Face
<
P
>
face
;
public
class
DAGElement
<
P
extends
IPoint
,
F
extends
IFace
<
P
>>
{
private
F
face
;
private
Triple
<
P
,
P
,
P
>
vertices
;
private
Triple
<
P
,
P
,
P
>
vertices
;
private
VTriangle
triangle
;
private
VTriangle
triangle
;
public
DAGElement
(
final
Face
<
P
>
face
,
final
Triple
<
P
,
P
,
P
>
vertices
)
{
public
DAGElement
(
final
F
face
,
List
<
P
>
points
)
{
P
p1
=
points
.
get
(
0
);
P
p2
=
points
.
get
(
1
);
P
p3
=
points
.
get
(
2
);
this
.
face
=
face
;
this
.
vertices
=
Triple
.
of
(
p1
,
p2
,
p3
);
this
.
triangle
=
new
VTriangle
(
new
VPoint
(
p1
),
new
VPoint
(
p2
),
new
VPoint
(
p3
));
}
public
DAGElement
(
final
F
face
,
final
Triple
<
P
,
P
,
P
>
vertices
)
{
this
.
face
=
face
;
this
.
face
=
face
;
this
.
vertices
=
vertices
;
this
.
vertices
=
vertices
;
VPoint
p1
=
new
VPoint
(
vertices
.
getLeft
()
.
getX
(),
vertices
.
getLeft
().
getY
()
);
VPoint
p1
=
new
VPoint
(
vertices
.
getLeft
());
VPoint
p2
=
new
VPoint
(
vertices
.
getMiddle
()
.
getX
(),
vertices
.
getMiddle
().
getY
()
);
VPoint
p2
=
new
VPoint
(
vertices
.
getMiddle
());
VPoint
p3
=
new
VPoint
(
vertices
.
getRight
()
.
getX
(),
vertices
.
getRight
().
getY
()
);
VPoint
p3
=
new
VPoint
(
vertices
.
getRight
());
this
.
triangle
=
new
VTriangle
(
p1
,
p2
,
p3
);
this
.
triangle
=
new
VTriangle
(
p1
,
p2
,
p3
);
}
}
public
F
ace
<
P
>
getFace
()
{
public
F
getFace
()
{
return
face
;
return
face
;
}
}
...
...
VadereUtils/src/org/vadere/util/geometry/mesh/EdgeIterator.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
java.util.Iterator
;
/**
* @author Benedikt Zoennchen
*/
public
class
EdgeIterator
<
P
extends
IPoint
,
E
extends
IHalfEdge
<
P
>,
F
extends
IFace
<
P
>>
implements
Iterator
<
E
>
{
private
E
currentHalfEdge
;
private
E
edge
;
private
boolean
started
=
false
;
private
IMesh
<
P
,
E
,
F
>
mesh
;
public
EdgeIterator
(
final
IMesh
<
P
,
E
,
F
>
mesh
,
final
F
face
){
this
.
edge
=
mesh
.
getEdge
(
face
);
this
.
currentHalfEdge
=
edge
;
this
.
mesh
=
mesh
;
}
@Override
public
boolean
hasNext
()
{
return
currentHalfEdge
!=
null
&&
(!
started
||
!
currentHalfEdge
.
equals
(
edge
));
}
@Override
public
E
next
()
{
started
=
true
;
E
result
=
currentHalfEdge
;
currentHalfEdge
=
mesh
.
getNext
(
currentHalfEdge
);
return
result
;
}
}
\ No newline at end of file
VadereUtils/src/org/vadere/util/geometry/mesh/Face.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.jetbrains.annotations.NotNull
;
import
org.vadere.util.geometry.GeometryUtils
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
org.vadere.util.geometry.shapes.MLine
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VPolygon
;
import
org.vadere.util.geometry.shapes.VTriangle
;
import
java.awt.geom.Path2D
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
import
java.util.stream.StreamSupport
;
/**
* A Face is a region of a planar separation of the 2-D space, e.g. the region of a Polygon/Triangle and so on.
*
* @author Benedikt Zoennchen
* @param <P> the type of the coordinates the face uses.
*/
public
class
Face
<
P
extends
IPoint
>
implements
Iterable
<
PHalfEdge
<
P
>>,
IFace
<
P
>
{
public
static
<
P
extends
IPoint
>
Face
<
P
>
of
(
P
x
,
P
y
,
P
z
)
{
Face
superTriangle
=
new
Face
();
Face
borderFace
=
new
Face
(
true
);
PHalfEdge
xy
=
new
PHalfEdge
(
y
,
superTriangle
);
PHalfEdge
yz
=
new
PHalfEdge
(
z
,
superTriangle
);
PHalfEdge
zx
=
new
PHalfEdge
(
x
,
superTriangle
);
xy
.
setNext
(
yz
);
yz
.
setNext
(
zx
);
zx
.
setNext
(
xy
);
PHalfEdge
yx
=
new
PHalfEdge
(
x
,
borderFace
);
PHalfEdge
zy
=
new
PHalfEdge
(
y
,
borderFace
);
PHalfEdge
xz
=
new
PHalfEdge
(
z
,
borderFace
);
yx
.
setNext
(
xz
);
xz
.
setNext
(
zy
);
zy
.
setNext
(
yx
);
xy
.
setTwin
(
yx
);
yz
.
setTwin
(
zy
);
zx
.
setTwin
(
xz
);
superTriangle
.
setEdge
(
xy
);
borderFace
.
setEdge
(
yx
);
return
superTriangle
;
}
public
static
<
P
extends
IPoint
>
Face
<
P
>
getBorder
(
Class
<
P
>
p
)
{
return
new
Face
<>(
true
);
}
/**
* One of the half-edges bordering this face.
*/
private
PHalfEdge
<
P
>
edge
;
private
boolean
border
;
private
boolean
destroyed
=
false
;
/**
* Default constructor. To construct a face where you have already some half-edges
* bordering this face.
*
* @param edge one of the half-edges bordering this face.
*/
public
Face
(
@NotNull
final
PHalfEdge
<
P
>
edge
)
{
this
(
edge
,
false
);
}
public
Face
(
@NotNull
final
PHalfEdge
<
P
>
edge
,
boolean
border
)
{
this
.
border
=
border
;
this
.
edge
=
edge
;
}
/**
* This constructor can be used for constructing a new face without having
* constructed the bordering half-edges jet.
*/
public
Face
(
boolean
border
)
{
this
.
border
=
border
;
}
public
Face
()
{
this
.
border
=
false
;
}
public
boolean
isBorder
()
{
return
border
;
}
public
void
destroy
()
{
setEdge
(
null
);
destroyed
=
true
;
}
public
void
toBorder
()
{
border
=
true
;
}
/**
* Sets one of the half-edges bordering this face.
*
* @param edge half-edge bordering this face
*/
public
void
setEdge
(
final
PHalfEdge
<
P
>
edge
)
{
this
.
edge
=
edge
;
}
public
PHalfEdge
<
P
>
getEdge
()
{
return
edge
;
}
public
boolean
isDestroyed
()
{
return
destroyed
;
}
/**
* Computes the area of this face.
*
* @return the area of this face
*/
public
double
getArea
()
{
return
GeometryUtils
.
areaOfPolygon
(
getPoints
());
}
/**
*
* @return
*/
public
List
<
P
>
getPoints
()
{
return
streamPoints
().
collect
(
Collectors
.
toList
());
}
/**
* Returns true if and only if the point contained in this face.
*
* @param point the point which might be contained
* @return true if and only if the point contained in this face.
*/
public
boolean
contains
(
final
P
point
)
{
return
toPolygon
().
contains
(
point
);
}
/**
* Transforms this face into a Polygon object.
*
* @return the Polygon object defined by this face
*/
public
VPolygon
toPolygon
()
{
Path2D
path2D
=
new
Path2D
.
Double
();
path2D
.
moveTo
(
edge
.
getPrevious
().
getEnd
().
getX
(),
edge
.
getPrevious
().
getEnd
().
getY
());
for
(
PHalfEdge
edge
:
this
)
{
path2D
.
lineTo
(
edge
.
getEnd
().
getX
(),
edge
.
getEnd
().
getY
());
}
return
new
VPolygon
(
path2D
);
}
/**
* Transforms this face into a triangle. Assumption: The face is a valid triangle.
*
* @throws IllegalArgumentException if the face does not define a valid triangle
* @return a triangle which is defined by this face
*/
public
VTriangle
toTriangle
()
{
List
<
PHalfEdge
<
P
>>
edges
=
getEdges
();
if
(
edges
.
size
()
!=
3
)
{
throw
new
IllegalArgumentException
(
"this face is not a feasible triangle."
);
}
else
{
VPoint
p1
=
new
VPoint
(
edges
.
get
(
0
).
getEnd
().
getX
(),
edges
.
get
(
0
).
getEnd
().
getY
());
VPoint
p2
=
new
VPoint
(
edges
.
get
(
1
).
getEnd
().
getX
(),
edges
.
get
(
1
).
getEnd
().
getY
());
VPoint
p3
=
new
VPoint
(
edges
.
get
(
2
).
getEnd
().
getX
(),
edges
.
get
(
2
).
getEnd
().
getY
());
return
new
VTriangle
(
p1
,
p2
,
p3
);
}
}
@Override
public
Iterator
<
PHalfEdge
<
P
>>
iterator
()
{
return
new
HalfEdgeIterator
();
}
public
Stream
<
PHalfEdge
<
P
>>
stream
()
{
Iterable
<
PHalfEdge
<
P
>>
iterable
=
()
->
iterator
();
return
StreamSupport
.
stream
(
iterable
.
spliterator
(),
false
);
}
public
List
<
PHalfEdge
<
P
>>
getEdges
()
{
return
stream
().
collect
(
Collectors
.
toList
());
}
public
Stream
<
MLine
<
P
>>
streamLines
()
{
return
stream
().
map
(
halfEdge
->
new
MLine
(
halfEdge
.
getPrevious
().
getEnd
(),
halfEdge
.
getEnd
()));
}
public
Stream
<
P
>
streamPoints
()
{
return
stream
().
map
(
edge
->
edge
.
getEnd
());
}
@Override
public
String
toString
()
{
return
stream
().
map
(
edge
->
edge
.
getEnd
().
toString
()).
reduce
(
""
,
(
s1
,
s2
)
->
s1
+
" "
+
s2
);
}
private
class
HalfEdgeIterator
implements
Iterator
<
PHalfEdge
<
P
>>
{
private
PHalfEdge
<
P
>
currentHalfEdge
;
private
boolean
started
=
false
;
private
HalfEdgeIterator
(){
this
.
currentHalfEdge
=
edge
;
}
@Override
public
boolean
hasNext
()
{
return
currentHalfEdge
!=
null
&&
(!
started
||
!
currentHalfEdge
.
equals
(
edge
));
}
@Override
public
PHalfEdge
<
P
>
next
()
{
started
=
true
;
PHalfEdge
result
=
currentHalfEdge
;
currentHalfEdge
=
currentHalfEdge
.
getNext
();
return
result
;
}
}
}
VadereUtils/src/org/vadere/util/geometry/mesh/FaceIterator.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.Set
;
import
java.util.function.Predicate
;
/**
* @author Benedikt Zoennchen
*
* @param <P>
*/
public
class
FaceIterator
<
P
extends
IPoint
>
implements
Iterator
<
Face
<
P
>>
{
private
LinkedList
<
Face
<
P
>>
facesToVisit
;
private
Set
<
Face
<
P
>>
visitedFaces
;
private
Predicate
<
Face
<
P
>>
facePredicate
;
public
FaceIterator
(
final
Face
<
P
>
face
,
final
Predicate
<
Face
<
P
>>
facePredicate
)
{
facesToVisit
=
new
LinkedList
<>();
Face
<
P
>
startFace
=
face
.
isBorder
()
?
face
.
getEdge
().
getTwin
().
getFace
()
:
face
;
if
(
startFace
.
isDestroyed
())
{
throw
new
IllegalArgumentException
(
"this face is already destroyed."
);
}
facesToVisit
.
add
(
startFace
);
visitedFaces
=
new
HashSet
<>();
this
.
facePredicate
=
facePredicate
;
}
public
FaceIterator
(
final
Face
<
P
>
face
)
{
this
(
face
,
f
->
true
);
}
@Override
public
boolean
hasNext
()
{
return
!
facesToVisit
.
isEmpty
();
}
@Override
public
Face
<
P
>
next
()
{
Face
<
P
>
nextFace
=
facesToVisit
.
removeFirst
();
visitedFaces
.
add
(
nextFace
);
for
(
PHalfEdge
<
P
>
he
:
nextFace
)
{
Face
<
P
>
twinFace
=
he
.
getTwin
().
getFace
();
if
(
twinFace
.
isBorder
()
||
twinFace
.
isDestroyed
()
||
!
facePredicate
.
test
(
twinFace
))
{
visitedFaces
.
add
(
twinFace
);
}
if
(!
visitedFaces
.
contains
(
twinFace
))
{
facesToVisit
.
add
(
twinFace
);
}
visitedFaces
.
add
(
twinFace
);
}
return
nextFace
;
}
}
VadereUtils/src/org/vadere/util/geometry/mesh/IFace.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
org.vadere.util.geometry.shapes.VPolygon
;
import
java.awt.geom.Path2D
;
/**
* @author Benedikt Zoennchen
* @param <P>
*/
public
interface
IFace
<
P
extends
IPoint
>
{
}
VadereUtils/src/org/vadere/util/geometry/mesh/IHalfEdge.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.vadere.util.geometry.shapes.IPoint
;
public
interface
IHalfEdge
<
P
extends
IPoint
>
{}
VadereUtils/src/org/vadere/util/geometry/mesh/IMesh.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.apache.commons.collections.IteratorUtils
;
import
org.jetbrains.annotations.NotNull
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VPolygon
;
import
java.awt.geom.Path2D
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Optional
;
/**
* @author Benedikt Zoennchen
* @param <P>
*/
public
interface
IMesh
<
P
extends
IPoint
,
E
extends
IHalfEdge
<
P
>,
F
extends
IFace
<
P
>>
extends
Iterable
<
F
>
{
E
getNext
(
@NotNull
E
halfEdge
);
E
getPrev
(
@NotNull
E
halfEdge
);
E
getTwin
(
@NotNull
E
halfEdge
);
F
getFace
(
@NotNull
E
halfEdge
);
E
getEdge
(
@NotNull
P
vertex
);
E
getEdge
(
@NotNull
F
face
);
P
getVertex
(
@NotNull
E
halfEdge
);
default
F
getTwinFace
(
@NotNull
E
halfEdge
)
{
return
getFace
(
getTwin
(
halfEdge
));
}
boolean
isBoundary
(
@NotNull
F
face
);
boolean
isBoundary
(
@NotNull
E
halfEdge
);
boolean
isDestroyed
(
@NotNull
F
face
);
void
setTwin
(
@NotNull
E
halfEdge
,
@NotNull
E
twin
);
void
setNext
(
@NotNull
E
halfEdge
,
@NotNull
E
next
);
void
setPrev
(
@NotNull
E
halfEdge
,
@NotNull
E
prev
);
void
setFace
(
@NotNull
E
halfEdge
,
@NotNull
F
face
);
void
setEdge
(
@NotNull
F
face
,
@NotNull
E
edge
);
void
setEdge
(
@NotNull
P
vertex
,
@NotNull
E
edge
);
void
setVertex
(
@NotNull
E
halfEdge
,
@NotNull
P
vertex
);
List
<
E
>
getEdges
(
@NotNull
P
vertex
);
default
List
<
E
>
getEdges
(
@NotNull
F
face
)
{
return
IteratorUtils
.
toList
(
new
EdgeIterator
(
this
,
face
));
}
default
List
<
F
>
getFaces
(
@NotNull
E
edge
)
{
return
IteratorUtils
.
toList
(
new
NeighbourFaceIterator
(
this
,
edge
));
}
default
List
<
E
>
getNeighbours
(
@NotNull
E
edge
)
{
return
IteratorUtils
.
toList
(
new
NeighbourIterator
(
this
,
edge
));
}
default
Iterable
<
E
>
getNeighbourIt
(
E
edge
)
{
return
()
->
new
NeighbourIterator
(
this
,
edge
);
}
default
Iterable
<
E
>
getEdgeIt
(
F
face
)
{
return
()
->
new
EdgeIterator
(
this
,
face
);
}
default
Iterable
<
F
>
getIncidentFacesIt
(
@NotNull
E
edge
)
{
return
()
->
new
NeighbourFaceIterator
<>(
this
,
edge
);
}
E
createEdge
(
@NotNull
P
vertex
);
E
createEdge
(
@NotNull
P
vertex
,
@NotNull
F
face
);
F
createFace
();
void
destroyFace
(
@NotNull
F
face
);
void
destroyEdge
(
@NotNull
E
edge
);
List
<
F
>
getFaces
();
@Override
default
Iterator
<
F
>
iterator
()
{
return
getFaces
().
iterator
();
}
default
VPolygon
toPolygon
(
F
face
)
{
Path2D
path2D
=
new
Path2D
.
Double
();
E
edge
=
getEdge
(
face
);
E
prev
=
getPrev
(
edge
);
path2D
.
moveTo
(
getVertex
(
prev
).
getX
(),
getVertex
(
prev
).
getY
());
path2D
.
lineTo
(
getVertex
(
edge
).
getX
(),
getVertex
(
edge
).
getY
());
while
(!
edge
.
equals
(
prev
))
{
edge
=
getNext
(
edge
);
P
p
=
getVertex
(
edge
);
path2D
.
lineTo
(
p
.
getX
(),
p
.
getY
());
}
return
new
VPolygon
(
path2D
);
}
default
Optional
<
F
>
locate
(
final
double
x
,
final
double
y
)
{
for
(
F
face
:
getFaces
())
{
VPolygon
polygon
=
toPolygon
(
face
);
if
(
polygon
.
contains
(
new
VPoint
(
x
,
y
)))
{
return
Optional
.
of
(
face
);
}
}
return
Optional
.
empty
();
}
}
VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourFaceIterator.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
java.util.Iterator
;
/**
* This iterator assumes that the this edge is completely surrounded by faces.
*
* @author Benedikt Zoennchen
*/
public
class
NeighbourFaceIterator
<
P
extends
IPoint
,
E
extends
IHalfEdge
<
P
>,
F
extends
IFace
<
P
>>
implements
Iterator
<
F
>
{
private
NeighbourIterator
<
P
,
E
,
F
>
neighbourIterator
;
private
IMesh
<
P
,
E
,
F
>
mesh
;
public
NeighbourFaceIterator
(
final
IMesh
<
P
,
E
,
F
>
mesh
,
E
edge
)
{
this
.
neighbourIterator
=
new
NeighbourIterator
<>(
mesh
,
edge
);
this
.
mesh
=
mesh
;
}
@Override
public
boolean
hasNext
()
{
return
neighbourIterator
.
hasNext
();
}
@Override
public
F
next
()
{
return
mesh
.
getFace
(
neighbourIterator
.
next
());
}
}
\ No newline at end of file
VadereUtils/src/org/vadere/util/geometry/mesh/NeighbourIterator.java
deleted
100644 → 0
View file @
9bc26ce4
package
org.vadere.util.geometry.mesh
;
import
org.vadere.util.geometry.shapes.IPoint
;
import
java.util.Iterator
;
/**
* @author Benedikt Zoennchen
* @param <P>
* @param <E>
* @param <F>
*/
public
class
NeighbourIterator
<
P
extends
IPoint
,
E
extends
IHalfEdge
<
P
>,
F
extends
IFace
<
P
>>
implements
Iterator
<
E
>
{
private
IMesh
<
P
,
E
,
F
>
mesh
;
private
E
current
;
private
E
edge
;
private
boolean
first
;
public
NeighbourIterator
(
final
IMesh
<
P
,
E
,
F
>
mesh
,
final
E
edge
)
{
this
.
mesh
=
mesh
;
this
.
edge
=
edge
;
this
.
current
=
mesh
.
getNext
(
edge
);
this
.
first
=
true
;
}
@Override
public
boolean
hasNext
()
{
return
(
first
||
current
!=
mesh
.
getNext
(
edge
));
}