11.08., 9:00 - 11:00: Due to updates GitLab will be unavailable for some minutes between 09:00 and 11:00.

Commit d46f4882 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

small performance improvements of the EikMesh algorithm.

parent 1b2630ed
Pipeline #271855 failed with stages
in 2 minutes and 10 seconds
...@@ -50,9 +50,9 @@ import java.util.stream.Collectors; ...@@ -50,9 +50,9 @@ import java.util.stream.Collectors;
public class MeshQuantityPrinting { public class MeshQuantityPrinting {
public static void main(String... args) throws InterruptedException, IOException { public static void main(String... args) throws InterruptedException, IOException {
spaceFillingCurve2(); //spaceFillingCurve2();
//uniformMeshDiscFunction(0.10); //uniformMeshDiscFunction(0.10);
//uniformMeshDiscFunctionDistMesh(0.05); uniformMeshDiscFunctionDistMesh(0.05);
//distMeshFail(0.05); //distMeshFail(0.05);
//delaunyTri("/poly/a.poly"); //delaunyTri("/poly/a.poly");
} }
...@@ -260,9 +260,9 @@ public class MeshQuantityPrinting { ...@@ -260,9 +260,9 @@ public class MeshQuantityPrinting {
int iteration = 1; int iteration = 1;
while (iteration < maxIteration+1) { while (iteration < maxIteration+1) {
distmesh.improve(); distmesh.improve();
if(iteration + 1 == maxIteration+1) { /*if(iteration + 1 == maxIteration+1) {
distmesh.reTriangulate(true); distmesh.reTriangulate(true);
} }*/
bufferedWriterIllegalEdges.write(iteration + " " + distmesh.getNumberOfIllegalTriangles() + "\n"); bufferedWriterIllegalEdges.write(iteration + " " + distmesh.getNumberOfIllegalTriangles() + "\n");
bufferedWriterQualities1.write(printQualities(iteration, distmesh, f -> GeometryUtils.qualityOf(f))); bufferedWriterQualities1.write(printQualities(iteration, distmesh, f -> GeometryUtils.qualityOf(f)));
bufferedWriterQualities2.write(printQualities(iteration, distmesh, f -> GeometryUtils.qualityLongestEdgeInCircle(f.p1, f.p2, f.p3))); bufferedWriterQualities2.write(printQualities(iteration, distmesh, f -> GeometryUtils.qualityLongestEdgeInCircle(f.p1, f.p2, f.p3)));
......
...@@ -321,7 +321,7 @@ public class IncrementalTriangulation<V extends IVertex, E extends IHalfEdge, F ...@@ -321,7 +321,7 @@ public class IncrementalTriangulation<V extends IVertex, E extends IHalfEdge, F
// remove all faces outside the hole // remove all faces outside the hole
VPolygon polygon = getMesh().toPolygon(hole); VPolygon polygon = getMesh().toPolygon(hole);
Predicate<F> removePredicate = face -> !polygon.contains(getMesh().toTriangle(face).midPoint()); Predicate<F> removePredicate = face -> !polygon.contains(getMesh().toMidpoint(face));
cdt.getTriangulation().shrinkBorder(removePredicate, true); cdt.getTriangulation().shrinkBorder(removePredicate, true);
IMesh<V, E, F> holeMesh = incrementalTriangulation.getMesh(); IMesh<V, E, F> holeMesh = incrementalTriangulation.getMesh();
......
...@@ -545,6 +545,9 @@ public interface IMesh<V extends IVertex, E extends IHalfEdge, F extends IFace> ...@@ -545,6 +545,9 @@ public interface IMesh<V extends IVertex, E extends IHalfEdge, F extends IFace>
* @return (optional) a boundary edge * @return (optional) a boundary edge
*/ */
default Optional<E> getBoundaryEdge(@NotNull final V vertex) { default Optional<E> getBoundaryEdge(@NotNull final V vertex) {
if(isBoundary(getEdge(vertex))) {
return Optional.of(getEdge(vertex));
}
return streamEdges(vertex).filter(e -> isBoundary(e)).findAny(); return streamEdges(vertex).filter(e -> isBoundary(e)).findAny();
} }
...@@ -1360,6 +1363,24 @@ public interface IMesh<V extends IVertex, E extends IHalfEdge, F extends IFace> ...@@ -1360,6 +1363,24 @@ public interface IMesh<V extends IVertex, E extends IHalfEdge, F extends IFace>
return new VTriangle(new VPoint(vertices.get(0)), new VPoint(vertices.get(1)), new VPoint(vertices.get(2))); return new VTriangle(new VPoint(vertices.get(0)), new VPoint(vertices.get(1)), new VPoint(vertices.get(2)));
} }
default VPoint toMidpoint(@NotNull final F face) {
assert getVertices(face).size() == 3 : "number of vertices of " + face + " is " + getVertices(face).size();
E edge = getEdge(face);
V v1 = getVertex(edge);
V v2 = getVertex(getNext(edge));
V v3 = getVertex(getPrev(edge));
return GeometryUtils.getTriangleMidpoint(getX(v1), getY(v1), getX(v2), getY(v2), getX(v3), getY(v3));
}
default VPoint toCircumcenter(@NotNull final F face) {
assert getVertices(face).size() == 3 : "number of vertices of " + face + " is " + getVertices(face).size();
E edge = getEdge(face);
V v1 = getVertex(edge);
V v2 = getVertex(getNext(edge));
V v3 = getVertex(getPrev(edge));
return GeometryUtils.getCircumcenter(getX(v1), getY(v1), getX(v2), getY(v2), getX(v3), getY(v3));
}
/** /**
* Returns the midpoint {@link VPoint} of a triangle defined by the face. * Returns the midpoint {@link VPoint} of a triangle defined by the face.
* Assumption: The face represents a triangle, i.e. it has exactly 3 distinct points. This * Assumption: The face represents a triangle, i.e. it has exactly 3 distinct points. This
...@@ -2362,6 +2383,17 @@ public interface IMesh<V extends IVertex, E extends IHalfEdge, F extends IFace> ...@@ -2362,6 +2383,17 @@ public interface IMesh<V extends IVertex, E extends IHalfEdge, F extends IFace>
} }
default String toPythonValues(@NotNull final Function<V, Double> evalPoint) {
StringBuilder builder = new StringBuilder();
List<V> vertices = getVertices();
for(V v : vertices) {
builder.append(evalPoint.apply(v) + ",");
}
builder.delete(builder.length()-1, builder.length());
builder.append("\n");
return builder.toString();
}
/** /**
* Constructs and returns a string which can be used to construct a matplotlib Triangulation * Constructs and returns a string which can be used to construct a matplotlib Triangulation
* which is helpful to plot the mesh. * which is helpful to plot the mesh.
......
...@@ -116,7 +116,7 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -116,7 +116,7 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
* @param vertex v * @param vertex v
*/ */
default void adjustVertex(@NotNull final V vertex) { default void adjustVertex(@NotNull final V vertex) {
getMesh().streamEdges(vertex).filter(edge -> isAtBoundary(edge)).findAny().ifPresent(edge -> getMesh().setEdge(vertex, edge)); getMesh().streamEdges(vertex).filter(edge -> getMesh().isBoundary(edge)).findAny().ifPresent(edge -> getMesh().setEdge(vertex, edge));
} }
/** /**
...@@ -632,14 +632,15 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -632,14 +632,15 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
* @param face they face which will be transformed into a hole * @param face they face which will be transformed into a hole
* @param mergeCondition the merge condition * @param mergeCondition the merge condition
* @param deleteIsoletedVertices if true isolated vertices, i.e. vertices without any edges, will be removed from the mesh * @param deleteIsoletedVertices if true isolated vertices, i.e. vertices without any edges, will be removed from the mesh
* @param vertexAdjust true means that boundary vertices will get their boundary edge as edge, false means there is no guarantee that this adjustment is made
* @return (optional) the hole or face itself it the face does not fulfill the merge condition * @return (optional) the hole or face itself it the face does not fulfill the merge condition
* or empty if due to the creation of the hole all faces will be removed! * or empty if due to the creation of the hole all faces will be removed!
*/ */
default Optional<F> createHole(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsoletedVertices) { default Optional<F> createHole(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsoletedVertices, final boolean vertexAdjust) {
if(mergeCondition.test(face)) { if(mergeCondition.test(face)) {
getMesh().toHole(face); getMesh().toHole(face);
shrinkBoundary(face, mergeCondition, deleteIsoletedVertices); shrinkBoundary(face, mergeCondition, deleteIsoletedVertices, vertexAdjust);
return Optional.of(face); return Optional.of(face);
} }
else { else {
...@@ -665,6 +666,10 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -665,6 +666,10 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
}*/ }*/
} }
default Optional<F> createHole(@NotNull final F face, @NotNull final Predicate<F> mergeCondition, final boolean deleteIsoletedVertices) {
return createHole(face, mergeCondition, deleteIsoletedVertices, true);
}
/** /**
* Shrinks the border as long as the removeCondition is satisfied i.e. a face will be removed if * Shrinks the border as long as the removeCondition is satisfied i.e. a face will be removed if
* it is at the border (during the shrinking process) and satisfies the condition. Like a virus this * it is at the border (during the shrinking process) and satisfies the condition. Like a virus this
...@@ -675,9 +680,14 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -675,9 +680,14 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
* *
* @param removeCondition the remove condition * @param removeCondition the remove condition
* @param deleteIsolatedVertices true then isolated vertices (they are not connected to an edge) will be removed. * @param deleteIsolatedVertices true then isolated vertices (they are not connected to an edge) will be removed.
* @param vertexAdjust true means that boundary vertices will get their boundary edge as edge, false means there is no guarantee that this adjustment is made
*/ */
default void shrinkBorder(final Predicate<F> removeCondition, final boolean deleteIsolatedVertices, final boolean vertexAdjust) {
shrinkBoundary(getMesh().getBorder(), removeCondition, deleteIsolatedVertices, vertexAdjust);
}
default void shrinkBorder(final Predicate<F> removeCondition, final boolean deleteIsolatedVertices) { default void shrinkBorder(final Predicate<F> removeCondition, final boolean deleteIsolatedVertices) {
shrinkBoundary(getMesh().getBorder(), removeCondition, deleteIsolatedVertices); shrinkBorder(removeCondition, deleteIsolatedVertices, true);
} }
default void shrinkBoundary(final Predicate<F> removeCondition, final boolean deleteIsolatedVertices) { default void shrinkBoundary(final Predicate<F> removeCondition, final boolean deleteIsolatedVertices) {
...@@ -697,8 +707,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -697,8 +707,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
* *
* @param removeCondition the remove condition * @param removeCondition the remove condition
* @param deleteIsolatedVertices true then isolated vertices (they are not connected to an edge) will be removed. * @param deleteIsolatedVertices true then isolated vertices (they are not connected to an edge) will be removed.
* @param adjustVertices true means that boundary vertices will get their boundary edge as edge, false means there is no guarantee that this adjustment is made
*/ */
default void shrinkBoundary(@NotNull final F boundary, final Predicate<F> removeCondition, final boolean deleteIsolatedVertices) { default void shrinkBoundary(@NotNull final F boundary, final Predicate<F> removeCondition, final boolean deleteIsolatedVertices, final boolean adjustVertices) {
assert getMesh().isBoundary(boundary); assert getMesh().isBoundary(boundary);
List<F> boundaryFaces = getMesh().getFaces(boundary); List<F> boundaryFaces = getMesh().getFaces(boundary);
...@@ -715,13 +726,17 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -715,13 +726,17 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
nextNeighbouringFaces.add(face); nextNeighbouringFaces.add(face);
} }
} }
removeFaceAtBoundary(neighbouringFace, boundary, deleteIsolatedVertices); removeFaceAtBoundary(neighbouringFace, boundary, deleteIsolatedVertices, adjustVertices);
} }
} }
neighbouringFaces = nextNeighbouringFaces; neighbouringFaces = nextNeighbouringFaces;
} while (!neighbouringFaces.isEmpty()); } while (!neighbouringFaces.isEmpty());
} }
default void shrinkBoundary(@NotNull final F boundary, final Predicate<F> removeCondition, final boolean deleteIsolatedVertices) {
shrinkBoundary(boundary, removeCondition, deleteIsolatedVertices, true);
}
default void removeFacesAtBoundary(@NotNull final Predicate<F> mergePredicate, @NotNull final Predicate<F> errorPredicate) throws IllegalMeshException { default void removeFacesAtBoundary(@NotNull final Predicate<F> mergePredicate, @NotNull final Predicate<F> errorPredicate) throws IllegalMeshException {
mergeFaces(getMesh().getBorder(), mergePredicate, errorPredicate, true, 1); mergeFaces(getMesh().getBorder(), mergePredicate, errorPredicate, true, 1);
for(F face : getMesh().getHoles()) { for(F face : getMesh().getHoles()) {
...@@ -1215,8 +1230,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -1215,8 +1230,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
* @param face the face that will be removed from the mesh * @param face the face that will be removed from the mesh
* @param boundary the boundary which has to be a neighbouring boundary of the face * @param boundary the boundary which has to be a neighbouring boundary of the face
* @param deleteIsolatedVertices true means that all vertices with degree smaller equals 1 will be removed as well * @param deleteIsolatedVertices true means that all vertices with degree smaller equals 1 will be removed as well
* @param adjustVertices true means that boundary vertices will get their boundary edge as edge, false means there is no guarantee that this adjustment is made
*/ */
default void removeFaceAtBoundary(@NotNull final F face, @NotNull final F boundary, final boolean deleteIsolatedVertices) { default void removeFaceAtBoundary(@NotNull final F face, @NotNull final F boundary, final boolean deleteIsolatedVertices, final boolean adjustVertices) {
if(!getMesh().isDestroyed(face)) { if(!getMesh().isDestroyed(face)) {
assert getMesh().streamFaces(face).filter(neighbour -> neighbour.equals(boundary)).count() > 0; assert getMesh().streamFaces(face).filter(neighbour -> neighbour.equals(boundary)).count() > 0;
...@@ -1357,7 +1373,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -1357,7 +1373,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
getMesh().destroyEdge(h1); getMesh().destroyEdge(h1);
// adjust vertices such that we speed up the querry isBoundary(vertex). // adjust vertices such that we speed up the querry isBoundary(vertex).
vertices.stream().filter(getMesh()::isAlive).forEach(v -> adjustVertex(v)); if(adjustVertices) {
vertices.stream().filter(getMesh()::isAlive).forEach(v -> adjustVertex(v));
}
} }
} }
...@@ -1371,6 +1389,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext ...@@ -1371,6 +1389,9 @@ public interface IPolyConnectivity<V extends IVertex, E extends IHalfEdge, F ext
} }
} }
default void removeFaceAtBoundary(@NotNull final F face, @NotNull final F boundary, final boolean deleteIsolatedVertices) {
removeFaceAtBoundary(face, boundary, deleteIsolatedVertices);
}
/** /**
* Removes a face from the mesh by removing all boundary edges of the face. * Removes a face from the mesh by removing all boundary edges of the face.
......
...@@ -1953,7 +1953,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -1953,7 +1953,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
* @return all visited faces in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>. * @return all visited faces in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>.
*/ */
default LinkedList<E> straightWalk2DGatherDirectional(@NotNull final F face, @NotNull final VPoint direction, @NotNull final Predicate<E> additionalStopCondition) { default LinkedList<E> straightWalk2DGatherDirectional(@NotNull final F face, @NotNull final VPoint direction, @NotNull final Predicate<E> additionalStopCondition) {
VPoint q = getMesh().toTriangle(face).midPoint(); VPoint q = getMesh().toMidpoint(face);
assert getMesh().toTriangle(face).contains(q); assert getMesh().toTriangle(face).contains(q);
Predicate<E> defaultStopCondion = e -> isRightOf(q.x, q.y, e); Predicate<E> defaultStopCondion = e -> isRightOf(q.x, q.y, e);
......
...@@ -112,7 +112,7 @@ public class Distmesh { ...@@ -112,7 +112,7 @@ public class Distmesh {
} }
public void reTriangulate(boolean force) { public void reTriangulate(boolean force) {
if(true || force || firstStep || maxMovementLen / initialEdgeLen > Parameters.TOL) { if(force || firstStep || maxMovementLen / initialEdgeLen > Parameters.TOL) {
firstStep = false; firstStep = false;
nTriangulations++; nTriangulations++;
......
...@@ -17,7 +17,7 @@ public class Parameters { ...@@ -17,7 +17,7 @@ public class Parameters {
public final static boolean uniform = false; public final static boolean uniform = false;
public final static String method = "Distmesh"; // "Distmesh" or "Density" public final static String method = "Distmesh"; // "Distmesh" or "Density"
public final static double qualityMeasurement = 0.95; public final static double qualityMeasurement = 0.95;
public final static double qualityConvergence = 0.001; public final static double qualityConvergence = 0.01;
public final static double MINIMUM = 0.25; public final static double MINIMUM = 0.25;
public final static double DENSITYWEIGHT = 2; public final static double DENSITYWEIGHT = 2;
public final static int NPOINTS = 100000; public final static int NPOINTS = 100000;
...@@ -25,5 +25,6 @@ public class Parameters { ...@@ -25,5 +25,6 @@ public class Parameters {
public final static int SAMPLEDIVISION = 10; public final static int SAMPLEDIVISION = 10;
public final static int SEGMENTDIVISION = 0; public final static int SEGMENTDIVISION = 0;
//TODO increase this //TODO increase this
public final static int MAX_NUMBER_OF_STEPS = 100; public final static int MAX_NUMBER_OF_STEPS = 200;
public final static int HIGHEST_LEGAL_TEST = 10;
} }
...@@ -26,7 +26,7 @@ public interface IEikMeshImprover<V extends IVertex, E extends IHalfEdge, F exte ...@@ -26,7 +26,7 @@ public interface IEikMeshImprover<V extends IVertex, E extends IHalfEdge, F exte
} }
default Predicate<F> outsidePredicate(@NotNull final IDistanceFunction distanceFunc) { default Predicate<F> outsidePredicate(@NotNull final IDistanceFunction distanceFunc) {
return f -> distanceFunc.apply(getMesh().toTriangle(f).midPoint()) > 0; return f -> distanceFunc.apply(getMesh().toMidpoint(f)) > 0;
} }
default Predicate<F> lowQualityPredicate() { default Predicate<F> lowQualityPredicate() {
......
...@@ -138,6 +138,6 @@ public class RunTimeCPU extends JFrame { ...@@ -138,6 +138,6 @@ public class RunTimeCPU extends JFrame {
} }
public static void main(String[] args) { public static void main(String[] args) {
stepUniformRing(0.05, 0.05, 0.05); stepUniformRing(0.05, 0.05, 0.05);
} }
} }
...@@ -7,6 +7,7 @@ import org.vadere.meshing.mesh.gen.AMesh; ...@@ -7,6 +7,7 @@ import org.vadere.meshing.mesh.gen.AMesh;
import org.vadere.meshing.mesh.gen.AVertex; import org.vadere.meshing.mesh.gen.AVertex;
import org.vadere.meshing.mesh.inter.IMeshSupplier; import org.vadere.meshing.mesh.inter.IMeshSupplier;
import org.vadere.meshing.mesh.inter.IPointConstructor; import org.vadere.meshing.mesh.inter.IPointConstructor;
import org.vadere.meshing.mesh.triangulation.improver.distmesh.DistmeshPanel;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.gen.GenEikMesh; import org.vadere.meshing.mesh.triangulation.improver.eikmesh.gen.GenEikMesh;
import org.vadere.meshing.mesh.gen.MeshPanel; import org.vadere.meshing.mesh.gen.MeshPanel;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.EikMeshPoint; import org.vadere.meshing.mesh.triangulation.improver.eikmesh.EikMeshPoint;
...@@ -29,6 +30,10 @@ public class RunTimeCPU extends JFrame { ...@@ -29,6 +30,10 @@ public class RunTimeCPU extends JFrame {
private static final Logger log = Logger.getLogger(RunTimeCPU.class); private static final Logger log = Logger.getLogger(RunTimeCPU.class);
static {
log.setInfo();
}
/** /**
* Each geometry is contained this bounding box. * Each geometry is contained this bounding box.
*/ */
...@@ -79,7 +84,6 @@ public class RunTimeCPU extends JFrame { ...@@ -79,7 +84,6 @@ public class RunTimeCPU extends JFrame {
private static void stepAdaptiveRingEikMesh(double startLen, double endLen, double stepLen) { private static void stepAdaptiveRingEikMesh(double startLen, double endLen, double stepLen) {
IMeshSupplier<AVertex, AHalfEdge, AFace> supplier = () -> new AMesh(); IMeshSupplier<AVertex, AHalfEdge, AFace> supplier = () -> new AMesh();
IDistanceFunction distanceFunc = p -> Math.abs(0.7 - Math.sqrt(p.getX() * p.getX() + p.getY() * p.getY())) - 0.3; IDistanceFunction distanceFunc = p -> Math.abs(0.7 - Math.sqrt(p.getX() * p.getX() + p.getY() * p.getY())) - 0.3;
IEdgeLengthFunction adaptiveEdgeLength = p -> 1.0 + Math.max(-distanceFunc.apply(p), 0) * 8.0;
List<VShape> obstacles = new ArrayList<>(); List<VShape> obstacles = new ArrayList<>();
double initialEdgeLength = startLen; double initialEdgeLength = startLen;
...@@ -91,6 +95,8 @@ public class RunTimeCPU extends JFrame { ...@@ -91,6 +95,8 @@ public class RunTimeCPU extends JFrame {
while (initialEdgeLength >= minInitialEdgeLength) { while (initialEdgeLength >= minInitialEdgeLength) {
initlialEdgeLengths.add(initialEdgeLength); initlialEdgeLengths.add(initialEdgeLength);
final double currentEdgeLen = initialEdgeLength;
IEdgeLengthFunction adaptiveEdgeLength = p -> currentEdgeLen + Math.max(-distanceFunc.apply(p), 0) * 0.4;
GenEikMesh<AVertex, AHalfEdge, AFace> meshGenerator = new GenEikMesh<>( GenEikMesh<AVertex, AHalfEdge, AFace> meshGenerator = new GenEikMesh<>(
distanceFunc, distanceFunc,
adaptiveEdgeLength, adaptiveEdgeLength,
...@@ -98,6 +104,10 @@ public class RunTimeCPU extends JFrame { ...@@ -98,6 +104,10 @@ public class RunTimeCPU extends JFrame {
bbox, obstacles, bbox, obstacles,
supplier); supplier);
while (!meshGenerator.isInitialized()) {
meshGenerator.initialize();
}
StopWatch overAllTime = new StopWatch(); StopWatch overAllTime = new StopWatch();
int steps = 0; int steps = 0;
...@@ -121,12 +131,12 @@ public class RunTimeCPU extends JFrame { ...@@ -121,12 +131,12 @@ public class RunTimeCPU extends JFrame {
nVertices.add(meshGenerator.getMesh().getVertices().size()); nVertices.add(meshGenerator.getMesh().getVertices().size());
runTimes.add( overAllTime.getTime()); runTimes.add( overAllTime.getTime());
/*PSMeshingPanel<MeshPoint, AVertex<MeshPoint>, AHalfEdge<MeshPoint>, AFace<MeshPoint>> distmeshPanel = new PSMeshingPanel(meshGenerator.getMesh(), f -> false, 1000, 800, bbox); MeshPanel<AVertex, AHalfEdge, AFace> distmeshPanel = new MeshPanel<>(meshGenerator.getMesh(),1000, 800);
JFrame frame = distmeshPanel.display(); JFrame frame = distmeshPanel.display();
frame.setVisible(true); frame.setVisible(true);
frame.setTitle("uniformRing()"); frame.setTitle("uniformRing()");
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
distmeshPanel.repaint();*/ distmeshPanel.repaint();
initialEdgeLength = initialEdgeLength * 0.5; initialEdgeLength = initialEdgeLength * 0.5;
...@@ -142,7 +152,7 @@ public class RunTimeCPU extends JFrame { ...@@ -142,7 +152,7 @@ public class RunTimeCPU extends JFrame {
private static void stepAdaptiveRingDistMesh(double startLen, double endLen, double stepLen) { private static void stepAdaptiveRingDistMesh(double startLen, double endLen, double stepLen) {
IMeshSupplier<AVertex, AHalfEdge, AFace> supplier = () -> new AMesh(); IMeshSupplier<AVertex, AHalfEdge, AFace> supplier = () -> new AMesh();
IDistanceFunction distanceFunc = p -> Math.abs(0.7 - Math.sqrt(p.getX() * p.getX() + p.getY() * p.getY())) - 0.3; IDistanceFunction distanceFunc = p -> Math.abs(0.7 - Math.sqrt(p.getX() * p.getX() + p.getY() * p.getY())) - 0.3;
IEdgeLengthFunction adaptiveEdgeLength = p -> 1.0 + Math.max(-distanceFunc.apply(p), 0) * 8.0; //IEdgeLengthFunction adaptiveEdgeLength = p -> 1.0 + Math.max(-distanceFunc.apply(p), 0) * 0.4;
List<VShape> obstacles = new ArrayList<>(); List<VShape> obstacles = new ArrayList<>();
double initialEdgeLength = startLen; double initialEdgeLength = startLen;
...@@ -154,6 +164,8 @@ public class RunTimeCPU extends JFrame { ...@@ -154,6 +164,8 @@ public class RunTimeCPU extends JFrame {
while (initialEdgeLength >= minInitialEdgeLength) { while (initialEdgeLength >= minInitialEdgeLength) {
initlialEdgeLengths.add(initialEdgeLength); initlialEdgeLengths.add(initialEdgeLength);
final double currentEdgeLen = initialEdgeLength;
IEdgeLengthFunction adaptiveEdgeLength = p -> currentEdgeLen + Math.max(-distanceFunc.apply(p), 0) * 0.1;
Distmesh meshGenerator = new Distmesh(distanceFunc, Distmesh meshGenerator = new Distmesh(distanceFunc,
adaptiveEdgeLength, adaptiveEdgeLength,
initialEdgeLength, initialEdgeLength,
...@@ -169,24 +181,24 @@ public class RunTimeCPU extends JFrame { ...@@ -169,24 +181,24 @@ public class RunTimeCPU extends JFrame {
meshGenerator.step(); meshGenerator.step();
overAllTime.suspend(); overAllTime.suspend();
steps++; steps++;
} while (!meshGenerator.hasMaximalSteps()); } while (steps <= 100);
log.info("#vertices: " + meshGenerator.getPoints().size()); log.info("#vertices: " + meshGenerator.getPoints().size());
log.info("quality: " + meshGenerator.getQuality()); log.info("quality: " + meshGenerator.getQuality());
log.info("#step: " + steps); log.info("#step: " + steps);
log.info("#tris: " + meshGenerator.getNumberOfReTriangulations()); log.info("#tris: " + meshGenerator.getNumberOfReTriangulations());
log.info("overall time: " + overAllTime.getTime() + "[ms]"); log.info("overall time: " + overAllTime.getTime() + "[ms]");
log.info("step avg time: " + overAllTime.getTime() / steps + "[ms]"); log.info("step avg time: " + overAllTime.getTime() / steps + "[ms]\n");
nVertices.add(meshGenerator.getPoints().size()); nVertices.add(meshGenerator.getPoints().size());
runTimes.add( overAllTime.getTime()); runTimes.add( overAllTime.getTime());
/*PSDistmeshPanel distmeshPanel = new PSDistmeshPanel(meshGenerator, 1000, 800, bbox, t -> false); DistmeshPanel distmeshPanel = new DistmeshPanel(meshGenerator, 1000, 800, bbox, t -> false);
JFrame frame = distmeshPanel.display(); JFrame frame = distmeshPanel.display();
frame.setVisible(true); frame.setVisible(true);
frame.setTitle("uniformRing()"); frame.setTitle("uniformRing()");
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
distmeshPanel.repaint();*/ distmeshPanel.repaint();
initialEdgeLength = initialEdgeLength * 0.5; initialEdgeLength = initialEdgeLength * 0.5;
...@@ -200,7 +212,8 @@ public class RunTimeCPU extends JFrame { ...@@ -200,7 +212,8 @@ public class RunTimeCPU extends JFrame {
} }
public static void main(String[] args) { public static void main(String[] args) {
stepAdaptiveRingDistMesh(0.1, 0.005, 0.01); //stepAdaptiveRingDistMesh(0.1, 0.005, 0.01);
//stepAdaptiveRingEikMesh(0.1, 0.005, 0.01); stepAdaptiveRingEikMesh(0.1, 0.005, 0.01);
//stepAdaptiveRingEikMesh(0.005, 0.005, 0.01);
} }
} }
...@@ -96,10 +96,10 @@ public class GenRegularRefinement<V extends IVertex, E extends IHalfEdge, F exte ...@@ -96,10 +96,10 @@ public class GenRegularRefinement<V extends IVertex, E extends IHalfEdge, F exte
//this.edgeRefinementPredicate = e -> getLevel(e) == (maxLevel-1) && edgeRefinementPredicate.test(e); //this.edgeRefinementPredicate = e -> getLevel(e) == (maxLevel-1) && edgeRefinementPredicate.test(e);
//this.edgeAddToRefine = e -> getLevel(e) == (maxLevel-1) && edgeRefinementPredicate.test(e); //this.edgeAddToRefine = e -> getLevel(e) == (maxLevel-1) && edgeRefinementPredicate.test(e);
VPoint p = new VPoint(5,5); //VPoint p = new VPoint(5,5);
this.edgeRefinementPredicate = e -> !getMesh().isBoundary(e) && getMesh().toTriangle(getMesh().getFace(e)).midPoint().distance(p) < 3.0 && (!isGreen(e) || getMesh().toLine(e).length() > 0.5);
//this.edgeRefinementPredicate = e -> !getMesh().isBoundary(e) && getMesh().toTriangle(getMesh().getFace(e)).midPoint().distance(p) < 3.0 && (!isGreen(e) || getMesh().toLine(e).length() > 0.5);
this.edgeRefinementPredicate = e -> getLevel(e) == (maxLevel-1) && (edgeRefinementPredicate.test(e));
this.finished = false; this.finished = false;
this.coarse = false; this.coarse = false;
this.toRefine = new LinkedList<>(); this.toRefine = new LinkedList<>();
......
...@@ -527,6 +527,7 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH ...@@ -527,6 +527,7 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH
List<F> sierpinksyFaceOrder = sfc.asList().stream().map(node -> getMesh().getFace(node.getEdge())).collect(Collectors.toList()); List<F> sierpinksyFaceOrder = sfc.asList().stream().map(node -> getMesh().getFace(node.getEdge())).collect(Collectors.toList());
shrinkBorder(); shrinkBorder();
createHoles(); createHoles();
adjustBoundaryVertexEdges();
//triangulation.smoothBorder(); //triangulation.smoothBorder();
sierpinksyFaceOrder.removeIf(face -> getMesh().isDestroyed(face) || getMesh().isHole(face)); sierpinksyFaceOrder.removeIf(face -> getMesh().isDestroyed(face) || getMesh().isHole(face));
...@@ -617,8 +618,8 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH ...@@ -617,8 +618,8 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH
* Note the border is part of the whole boundary which is defined by the border and the holes.</p> * Note the border is part of the whole boundary which is defined by the border and the holes.</p>
*/ */
private void shrinkBorder() { private void shrinkBorder() {
Predicate<F> removePredicate = face -> distFunc.apply(triangulation.getMesh().toTriangle(face).midPoint()) > 0; Predicate<F> removePredicate = face -> distFunc.apply(triangulation.getMesh().toMidpoint(face)) > 0;
triangulation.shrinkBorder(removePredicate, true); triangulation.shrinkBorder(removePredicate, true, false);
} }
@Override @Override
...@@ -652,6 +653,7 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH ...@@ -652,6 +653,7 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH
GenConstrainSplitter<V, E, F> cdt = new GenConstrainSplitter<>(getTriangulation(), lines, GeometryUtils.DOUBLE_EPS, sfc); GenConstrainSplitter<V, E, F> cdt = new GenConstrainSplitter<>(getTriangulation(), lines, GeometryUtils.DOUBLE_EPS, sfc);
cdt.generate(false); cdt.generate(false);
getTriangulation().setCanIllegalPredicate(e -> true);
projections.putAll(cdt.getProjections()); projections.putAll(cdt.getProjections());
constrains.addAll(cdt.getConstrains()); constrains.addAll(cdt.getConstrains());
...@@ -661,9 +663,21 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH ...@@ -661,9 +663,21 @@ public class GenUniformRefinementTriangulatorSFC<V extends IVertex, E extends IH
List<F> faces = triangulation.getMesh().getFaces(); List<F> faces = triangulation.getMesh().getFaces();
for(F face : faces) { for(F face : faces) {
if(!triangulation.getMesh().isDestroyed(face) && !triangulation.getMesh().isHole(face)) { if(!triangulation.getMesh().isDestroyed(face) && !triangulation.getMesh().isHole(face)) {
triangulation.createHole(face, f -> distFunc.apply(triangulation.getMesh().toTriangle(f).midPoint()) > 0, true); triangulation.createHole(face, f -> distFunc.apply(triangulation.getMesh().toMidpoint(f)) > 0, true, false);
}
}
}
private void adjustBoundaryVertexEdges() {
for(F hole : getMesh().getHoles()) {
for(V v : getMesh().getVertexIt(hole)) {
triangulation.adjustVertex(v);
} }
} }
for(V v : getMesh().getVertexIt(getMesh().getBorder())) {
triangulation.adjustVertex(v);
}