Commit 0d6a7c35 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

small bug fix for the mesh, tex mesh generator

parent b7e4a4a2
......@@ -114,6 +114,7 @@ public class IncrementalTriangulation<P extends IPoint, V extends IVertex<P>, E
p1 = mesh.insertVertex(bound.getX() + 2 * max + gap, bound.getY() - gap);
p2 = mesh.insertVertex(bound.getX() + (max+2*gap)/2, bound.getY() + 2 * max + gap);
// counter clockwise!
superTriangle = mesh.createFace(p0, p1, p2);
borderFace = mesh.getTwinFace(mesh.getEdge(superTriangle));
......
......@@ -19,6 +19,7 @@ import java.util.stream.Stream;
public class PMesh<P extends IPoint> implements IMesh<P, PVertex<P>, PHalfEdge<P>, PFace<P>> {
private List<PFace<P>> faces;
//private List<PFace<P>> borderFaces;
private PFace<P> boundary;
private List<PHalfEdge<P>> edges;
private IPointConstructor<P> pointConstructor;
......@@ -26,6 +27,7 @@ public class PMesh<P extends IPoint> implements IMesh<P, PVertex<P>, PHalfEdge<P
public PMesh(final IPointConstructor<P> pointConstructor) {
this.faces = new ArrayList<>();
//this.borderFaces = new ArrayList<>();
this.edges = new ArrayList<>();
this.vertices = new HashSet<>();
this.boundary = new PFace<>(true);
......@@ -290,4 +292,9 @@ public class PMesh<P extends IPoint> implements IMesh<P, PVertex<P>, PHalfEdge<P
public List<PFace<P>> getFaces() {
return streamFaces().filter(face -> !face.isBorder()).filter(face -> !face.isDestroyed()).collect(Collectors.toList());
}
@Override
public List<PHalfEdge<P>> getBoundaryEdges() {
return streamEdges().filter(edge -> edge.isBoundary()).filter(edge -> !edge.isDestroyed()).collect(Collectors.toList());
}
}
......@@ -22,6 +22,7 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
/**
......@@ -40,6 +41,7 @@ public class UniformRefinementTriangulation<P extends IPoint, V extends IVertex<
private IMesh<P, V, E, F> mesh;
private static final Logger logger = LogManager.getLogger(UniformRefinementTriangulation.class);
private final IDistanceFunction distFunc;
private final static Random random = new Random();
public UniformRefinementTriangulation(
final ITriangulation<P, V, E, F> triangulation,
......@@ -64,7 +66,7 @@ public class UniformRefinementTriangulation<P extends IPoint, V extends IVertex<
for(E edge : mesh.getEdgeIt(mesh.getBoundary())) {
if(!isCompleted(edge) && !points.contains(mesh.getVertex(edge))) {
toRefineEdges.add(edge);
toRefineEdges.add(mesh.getTwin(edge));
}
}
......@@ -142,17 +144,20 @@ public class UniformRefinementTriangulation<P extends IPoint, V extends IVertex<
return shape.intersects(line) || shape.contains(line.getP1()) || shape.contains(line.getP2());
}
private boolean isCompleted(final E edge) {
private boolean isCompleted(E edge) {
if(mesh.isBoundary(edge)){
edge = mesh.getTwin(edge);
}
F face = mesh.getFace(edge);
F twin = mesh.getTwinFace(edge);
VTriangle triangle = mesh.toTriangle(face);
VTriangle twinTriangle = mesh.toTriangle(twin);
VLine line = mesh.toLine(edge);
return line.length() <= lenFunc.apply(line.midPoint())
|| (!triangle.intersect(bbox) && !twinTriangle.intersect(bbox))
|| boundary.stream().anyMatch(shape -> shape.contains(triangle.getBounds2D()) || shape.contains(twinTriangle.getBounds2D()));
return (line.length() <= lenFunc.apply(line.midPoint()) && random.nextDouble() < 0.96)
|| (!triangle.intersect(bbox) && (mesh.isBoundary(twin) || !mesh.toTriangle(twin).intersect(bbox)))
|| boundary.stream().anyMatch(shape -> shape.contains(triangle.getBounds2D()) || (!mesh.isBoundary(twin) && shape.contains(mesh.toTriangle(twin).getBounds2D())));
}
private Collection<E> refine(final E edge) {
......
......@@ -269,15 +269,82 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
return remFace;
}
/**
* Removes a face from the mesh by removing all boundary edges of the face.
* If there are no boundary edges the face will be converted to be a part of the boundary
* itself i.e. a hole.
* Mesh changing method.
*
* @param face the face that will be removed from the mesh
* @param deleteIsolatedVertices true means that all vertices with degree <= 1 will be removed as well
*/
default void makeHole(final V vertex) {
List<F> toDeleteFaces = getMesh().getFaces(vertex);
for(F face : toDeleteFaces) {
removeFace(face, true);
}
}
/*default void fill_hole (final V v, final List<E> deletedEdges)
{
// uses the fact that the hole is starshaped
// with repect to v->point()
typedef std::list<Edge> Hole;
Face_handle ff, fn;
int ii , in;
Vertex_handle v0, v1, v2;
Bounded_side side;
//stack algorithm to create faces
// create face v0,v1,v2
//if v0,v1,v2 are finite vertices
// and form a left_turn
// and triangle v0v1v2 does not contain v->point()
if( hole.size() != 3) {
typename Hole::iterator hit = hole.begin();
typename Hole::iterator next= hit;
while( hit != hole.end() && hole.size() != 3) {
ff = (*hit).first;
ii = (*hit).second;
v0 = ff->vertex(cw(ii));
v1 = ff->vertex(ccw(ii));
if( !is_infinite(v0) && !is_infinite(v1)) {
next=hit; next++;
if(next == hole.end()) next=hole.begin();
fn = (*next).first;
in = (*next).second;
v2 = fn->vertex(ccw(in));
if ( !is_infinite(v2) &&
orientation(v0->point(), v1->point(), v2->point()) == LEFT_TURN ) {
side = bounded_side(v0->point(),
v1->point(),
v2->point(),
v->point());
if( side == ON_UNBOUNDED_SIDE ||
(side == ON_BOUNDARY && orientation(v0->point(),
v->point(),
v2->point()) == COLLINEAR &&
collinear_between(v0->point(),v->point(),v2->point()) ))
{
//create face
Face_handle newf = create_face(ff,ii,fn,in);
typename Hole::iterator tempo=hit;
hit = hole.insert(hit,Edge(newf,1)); //push newf
hole.erase(tempo); //erase ff
hole.erase(next); //erase fn
if (hit != hole.begin() ) --hit;
continue;
}
}
}
++hit;
}
}*/
/**
* Removes a face from the mesh by removing all boundary edges of the face.
* If there are no boundary edges the face will be converted to be a part of the boundary
* itself i.e. a hole.
* Mesh changing method.
*
* @param face the face that will be removed from the mesh
* @param deleteIsolatedVertices true means that all vertices with degree <= 1 will be removed as well
*/
default void removeFace(@NotNull final F face, final boolean deleteIsolatedVertices) {
assert !getMesh().isDestroyed(face);
......@@ -286,6 +353,18 @@ public interface IPolyConnectivity<P extends IPoint, V extends IVertex<P>, E ext
F boundary = getMesh().createFace(true);
/*for(E edge : getMesh().getEdgeIt(face)) {
if(getMesh().isBoundary(getMesh().getTwin(edge))) {
boundary = getMesh().getTwinFace(edge);
break;
}
}
// no boundary around
if(boundary == null) {
boundary = getMesh().createFace(true);
}*/
for(E edge : getMesh().getEdgeIt(face)) {
getMesh().setFace(edge, boundary);
if(getMesh().isBoundary(getMesh().getTwin(edge))) {
......
......@@ -9,6 +9,7 @@ import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VTriangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
......@@ -476,15 +477,23 @@ public interface ITriConnectivity<P extends IPoint, V extends IVertex<P>, E exte
@Override
default Optional<F> locateFace(final double x, final double y) {
Optional<F> optFace;
if(getMesh().getNumberOfFaces() > 1) {
return locateFace(x, y, getMesh().getFace());
optFace = locateFace(x, y, getMesh().getFace());
}
else if(getMesh().getNumberOfFaces() == 1) {
return Optional.of(getMesh().getFace());
optFace = Optional.of(getMesh().getFace());
}
else {
optFace = Optional.empty();
}
if(optFace.isPresent() && getMesh().isBoundary(optFace.get())) {
return Optional.empty();
}
else {
return optFace;
}
}
/*default Optional<P> locateVertex(double x, double y, F startFace) {
......@@ -592,6 +601,31 @@ public interface ITriConnectivity<P extends IPoint, V extends IVertex<P>, E exte
return face;
}
default F walkThroughHole(double x1, double y1, @NotNull F borderFace) {
assert getMesh().isBoundary(borderFace);
double minDistance = Double.MAX_VALUE;
F choosenFace = borderFace;
for(E edge : getMesh().getEdgeIt(borderFace)) {
V v1 = getMesh().getVertex(getMesh().getPrev(edge));
V v2 = getMesh().getVertex(edge);
// get out of the hole/border. Note: non-border faces are ccw oriented but border-faces are cw oriented!
if (GeometryUtils.isRightOf(v2, v1, x1, y1)) {
double distance = GeometryUtils.distanceToLineSegment(v1, v2, x1, y1);
if(distance < minDistance) {
minDistance = distance;
choosenFace = getMesh().getTwinFace(edge);
}
}
}
return choosenFace;
}
default F marchRandom2D(double x1, double y1, F startFace) {
boolean first = true;
F face = startFace;
......@@ -599,6 +633,19 @@ public interface ITriConnectivity<P extends IPoint, V extends IVertex<P>, E exte
int count = 0;
while (true) {
if(getMesh().isBoundary(face)) {
F tmpFace = walkThroughHole(x1, y1, face);
if(getMesh().isBoundary(tmpFace)) {
assert tmpFace == face;
return tmpFace;
}
else {
face = tmpFace;
}
}
count++;
boolean goLeft = random.nextBoolean();
//boolean goLeft = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment