Notice: If you are member of any public project or group, please make sure that your GitLab username is not the same as the LRZ identifier/Kennung (see https://gitlab.lrz.de/profile/account). Please change your username if necessary. For more information see the section "Public projects / Öffentliche Projekte" at https://doku.lrz.de/display/PUBLIC/GitLab . Thank you!

Commit 5c863f00 authored by BZoennchen's avatar BZoennchen

split Mesh IO into multiple classes.

parent 0195ad51
Pipeline #129129 passed with stages
in 112 minutes and 5 seconds
......@@ -6,7 +6,7 @@ import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.postvisualization.PostVisualisation;
import org.vadere.meshing.utils.io.poly.PolyGenerator;
import org.vadere.meshing.utils.io.poly.PSLGGenerator;
import org.vadere.state.scenario.Obstacle;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VRectangle;
......@@ -67,7 +67,7 @@ public class ActionGeneratePoly extends AbstractAction {
List<Obstacle> obstacles = new ArrayList<>(model.getTopography().getObstacles());
obstacles.removeAll(model.getTopography().getBoundaryObstacles());
String polyString = PolyGenerator.toPSLG(
String polyString = PSLGGenerator.toPSLG(
new VPolygon(bound),
obstacles.stream()
.map(obs -> obs.getShape())
......
......@@ -3,7 +3,7 @@ package org.vadere.meshing.examples;
import org.vadere.meshing.mesh.impl.PSLG;
import org.vadere.meshing.mesh.triangulation.EdgeLengthFunctionApprox;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PRuppertsTriangulator;
import org.vadere.meshing.utils.io.poly.PolyGenerator;
import org.vadere.meshing.utils.io.poly.PSLGGenerator;
import java.io.IOException;
import java.io.InputStream;
......@@ -16,7 +16,7 @@ public class BackgroundMeshExamples {
public static void greenlandLFS() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/kaiserslautern.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
double theta = 10;
PRuppertsTriangulator ruppert = new PRuppertsTriangulator(
......
......@@ -8,7 +8,8 @@ import org.vadere.meshing.mesh.triangulation.improver.eikmesh.gen.GenEikMesh;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.impl.PEikMesh;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PDelaunayTriangulator;
import org.vadere.meshing.utils.io.movie.MovRecorder;
import org.vadere.meshing.utils.io.poly.PolyGenerator;
import org.vadere.meshing.utils.io.poly.MeshPolyReader;
import org.vadere.meshing.utils.io.poly.MeshPolyWriter;
import org.vadere.meshing.utils.io.tex.TexGraphGenerator;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.meshing.mesh.gen.PFace;
......@@ -283,11 +284,18 @@ public class EikMeshExamples {
// (optional) define the gui to display the mesh
meshImprover.generate();
String polyString = PolyGenerator.to2DPoly(meshImprover.getMesh());
InputStream inputStream = new ByteArrayInputStream(polyString.getBytes(Charset.forName("UTF-8")));
var meshSuppliert = PMeshSuppliert.defaultMeshSupplier;
var mesh = PolyGenerator.toMesh(inputStream, meshSuppliert);
var writer = new MeshPolyWriter<PVertex, PHalfEdge, PFace>();
var reader = new MeshPolyReader<>(meshSuppliert);
String polyString = writer.to2DPoly(meshImprover.getMesh());
InputStream inputStream = new ByteArrayInputStream(polyString.getBytes(Charset.forName("UTF-8")));
System.out.println(polyString);
var mesh = reader.readMesh(inputStream);
var meshPanel = new PMeshPanel(mesh, 1000, 800);
// generate the mesh
......
......@@ -9,7 +9,7 @@ import org.vadere.meshing.mesh.triangulation.improver.eikmesh.EikMeshPoint;
import org.vadere.meshing.mesh.triangulation.improver.eikmesh.impl.PEikMesh;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PDelaunayTriangulator;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PRuppertsTriangulator;
import org.vadere.meshing.utils.io.poly.PolyGenerator;
import org.vadere.meshing.utils.io.poly.PSLGGenerator;
import org.vadere.meshing.utils.io.tex.TexGraphGenerator;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.shapes.VLine;
......@@ -89,7 +89,7 @@ public class EikMeshPlots {
public static void kaiserslautern() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/kaiserslautern.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......@@ -117,7 +117,7 @@ public class EikMeshPlots {
public static void bridge() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/bridge.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......@@ -152,7 +152,7 @@ public class EikMeshPlots {
public static void eikMeshA(double h0) throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/a.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
PEikMesh meshImprover = new PEikMesh(pslg.getSegmentBound(), h0, pslg.getHoles());
meshImprover.generate();
......@@ -311,7 +311,7 @@ public class EikMeshPlots {
public static void ruppertsAndEikMeshKaiserslautern() throws IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/a.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VLine> lines = pslg.getAllSegments();
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......
......@@ -20,7 +20,7 @@ import org.vadere.meshing.mesh.triangulation.triangulator.impl.PDelaunayTriangul
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PVoronoiSegmentInsertion;
import org.vadere.meshing.mesh.triangulation.triangulator.impl.PRuppertsTriangulator;
import org.vadere.meshing.utils.io.movie.MovRecorder;
import org.vadere.meshing.utils.io.poly.PolyGenerator;
import org.vadere.meshing.utils.io.poly.PSLGGenerator;
import org.vadere.meshing.utils.io.tex.TexGraphGenerator;
import org.vadere.util.data.cellgrid.IPotentialPoint;
import org.vadere.util.data.cellgrid.PathFindingTag;
......@@ -223,7 +223,7 @@ public class MeshExamples {
public static void constrainedDelaunayTriangulation() throws IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/a.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VLine> constrains = pslg.getAllSegments();
var cdt = new PContrainedDelaunayTriangulator(
pslg,
......@@ -306,7 +306,7 @@ public class MeshExamples {
public static void ruppertsTriangulationKaiserslautern() throws IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/kaiserslautern.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VLine> lines = pslg.getAllSegments();
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......@@ -356,7 +356,7 @@ public class MeshExamples {
public static void ruppertsTriangulationPoly() throws IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/a.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VLine> segments = pslg.getAllSegments();
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......@@ -400,7 +400,7 @@ public class MeshExamples {
public static void ruppertsTriangulationPolyGreenland() throws IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/greenland.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
double theta = 20;
PRuppertsTriangulator ruppert = new PRuppertsTriangulator(
pslg,
......@@ -495,7 +495,7 @@ public class MeshExamples {
public static void eikMeshA() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/a.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
// IPointConstructor<EikMeshPoint> pointConstructor = (x, y) -> new EikMeshPoint(x, y);
......@@ -549,7 +549,7 @@ public class MeshExamples {
public static void eikMeshEik() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/eikmesh.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
// IPointConstructor<EikMeshPoint> pointConstructor = (x, y) -> new EikMeshPoint(x, y);
......@@ -603,7 +603,7 @@ public class MeshExamples {
public static void eikMeshKaiserslauternApprox() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/kaiserslautern.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......@@ -671,7 +671,7 @@ public class MeshExamples {
public static void eikMeshKaiserslautern() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/kaiserslautern.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......@@ -741,7 +741,7 @@ public class MeshExamples {
public static void eikMeshGreenland() throws IOException, InterruptedException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/greenland.poly");
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
IPointConstructor<EikMeshPoint> pointConstructor = (x, y) -> new EikMeshPoint(x, y);
// (1) construct background mesh distance function
......@@ -802,7 +802,7 @@ public class MeshExamples {
public static void dirichletRefinment() throws InterruptedException, IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/a.poly");
boolean duplicatedLines = false;
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VLine> lines = pslg.getAllSegments();
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......@@ -836,7 +836,7 @@ public class MeshExamples {
public static void delaunayRefinment() throws InterruptedException, IOException {
final InputStream inputStream = MeshExamples.class.getResourceAsStream("/poly/a.poly");
boolean duplicatedLines = false;
PSLG pslg = PolyGenerator.toPSLGtoVShapes(inputStream);
PSLG pslg = PSLGGenerator.toPSLGtoVShapes(inputStream);
Collection<VLine> lines = pslg.getAllSegments();
Collection<VPolygon> holes = pslg.getHoles();
VPolygon segmentBound = pslg.getSegmentBound();
......
......@@ -2169,12 +2169,11 @@ public interface IMesh<V extends IVertex, E extends IHalfEdge, F extends IFace>
* Creates a very simple mesh consisting of two triangles ((-100, 0), (100, 0), (0, 1)) and ((0, -1), (-100, 0), (100, 0))
*
* @param mesh the mesh used to create the triangle. This mesh should be empty.
* @param <P> the type of the point
* @param <V> the type of the vertex
* @param <E> the type of the edge
* @param <F> the type of the face
*/
static <P extends IPoint, CE, CF, V extends IVertex, E extends IHalfEdge, F extends IFace> void createSimpleTriMesh(
static <V extends IVertex, E extends IHalfEdge, F extends IFace> void createSimpleTriMesh(
@NotNull final IMesh<V, E, F> mesh
) {
F face1;
......
package org.vadere.meshing.utils.io.poly;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.vadere.meshing.mesh.inter.IFace;
import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* The {@link MeshPSLGWriter} transforms a {@link IMesh} into a ascii-PSLG {@link String} and writes into a file.
*
* @param <V> the type of the vertices
* @param <E> the type of the half-edges
* @param <F> the type of the faces
*/
public class MeshPSLGWriter<V extends IVertex, E extends IHalfEdge, F extends IFace> {
private final static String SEPARATOR = " ";
private final static int DIMENSION = 2;
/**
* Transforms a {@link IMesh} into a PSLG-{@link String}. Note that in the PSLG-format faces aren't saved explicit.
*
* @param mesh the mesh
*
* @return a PSLG-{@link String}
*/
public String toPSLG(@NotNull final IMesh<V, E, F> mesh) {
return toPSLG(mesh, 0, null);
}
/**
* Transforms a {@link IMesh} into a PSLG-{@link String}. Note that in the PSLG-format faces aren't saved explicit.
*
* @param mesh the mesh
* @param nAttributes number of vertex attributes
* @param attrNameFunc a function attributeIndex -> attributeName
*
* @return a PSLG-{@link String}
*/
public String toPSLG(
@NotNull final IMesh<V, E, F> mesh,
int nAttributes,
@Nullable final Function<Integer, String> attrNameFunc){
assert nAttributes <= 0 || attrNameFunc != null;
int boundaryMarker = 0; // no boundary marker
StringBuilder builder = new StringBuilder();
builder.append("#node\n");
builder.append(mesh.getNumberOfVertices() + SEPARATOR + DIMENSION + SEPARATOR + nAttributes + SEPARATOR + boundaryMarker + "\n");
Map<V, Integer> map = new HashMap<>();
int id = 1;
for(V v : mesh.getVertices()) {
map.put(v, id);
builder.append(String.format(Locale.US, "%d" + SEPARATOR +"%f" + SEPARATOR + "%f", id, v.getX(), v.getY()));
for(int j = 1; j <= nAttributes; j++) {
builder.append(String.format(Locale.US, SEPARATOR + "%f", mesh.getDoubleData(v, attrNameFunc.apply(j))));
}
builder.append("\n");
id++;
}
List<VLine> lines = mesh.getLines().stream().collect(Collectors.toList());
builder.append("\n" + lines.size() + SEPARATOR + boundaryMarker);
for(int index = 1; index <= lines.size(); index++) {
VLine line = lines.get(index-1);
Integer from = map.get(line.getVPoint1());
assert from != null;
if(from == null) {
throw new IllegalArgumentException("could not find index for point " + line.getVPoint1());
}
Integer to = map.get(line.getVPoint2());
assert to != null;
if(to == null) {
throw new IllegalArgumentException("could not find index for point " + line.getVPoint2());
}
builder.append("\n" + index + SEPARATOR + from + SEPARATOR + to);
}
builder.append("#holes\n");
List<F> holes = mesh.getHoles();
builder.append(holes.size()+"\n");
builder.append("#interior points for each hole\n");
id = 1;
for(F hole : holes) {
VPolygon polygon = mesh.toPolygon(hole);
VPoint p = GeometryUtils.getInteriorPoint(polygon);
builder.append(String.format(Locale.US, "%d" + SEPARATOR +"%f" + SEPARATOR + "%f\n", id, p.getX(), p.getY()));
}
return builder.toString();
}
}
package org.vadere.meshing.utils.io.poly;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.vadere.meshing.mesh.inter.IFace;
import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.meshing.mesh.inter.IVertex;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* The {@link MeshPolyReader} reads a ascii-poly file and transforms it into a {@link IMesh}.
* It is the counterpart to {@link MeshPolyWriter}.
*
* @param <V> the type of the vertices
* @param <E> the type of the half-edges
* @param <F> the type of the faces
*/
public class MeshPolyReader<V extends IVertex, E extends IHalfEdge, F extends IFace> {
private final static String SPLITTER = "\\s+";
private final static String COMMENT_MARKER = "#";
/**
* a Functions id -> vertex which gives for a specific vertex id the correct vertex
*/
private final Map<Integer, V> vertices;
/**
* a Function (startVertexId, endVertexId) -> halfEdge which gives for a specific pair of ids the correct half-edge
*/
private final Map<Pair<Integer, Integer>, E> edges;
/**
* the mesh for which the face will be added
*/
private IMesh<V, E, F> mesh;
private final Supplier<IMesh<V, E, F>> meshSupplier;
public MeshPolyReader(@NotNull final Supplier<IMesh<V, E, F>> meshSupplier) {
this.meshSupplier = meshSupplier;
this.edges = new HashMap<>();
this.vertices = new HashMap<>();
}
/**
* Adds a face to the mesh by parsing the String <tt>line</tt> which should represent a face.
*
* @param line a String that represents the face
* @param face the face object which was already be added
*/
private void addFace(@NotNull final String line, @NotNull final F face) {
String[] split = line.split(SPLITTER);
int nVertices = Integer.parseInt(split[0].strip());
assert nVertices == split.length-1;
List<Integer> vertexIds = new ArrayList<>(nVertices);
for(int i = 0; i < nVertices; i++) {
vertexIds.add(Integer.parseInt(split[i+1].strip()));
}
List<E> ccwEdges = new ArrayList<>(nVertices);
for(int i = 0; i < nVertices; i++) {
int i1 = vertexIds.get(i);
int i2 = vertexIds.get((i+1) % nVertices);
V v1 = vertices.get(i1);
V v2 = vertices.get(i2);
E edge = mesh.createEdge(v2);
mesh.setFace(edge, face);
mesh.setEdge(face, edge);
if(mesh.getEdge(v2) == null || !mesh.isBoundary(mesh.getEdge(v2))) {
mesh.setEdge(v2, edge);
}
edges.put(Pair.of(i1, i2), edge);
if(edges.containsKey(Pair.of(i2, i1))) {
E twin = edges.get(Pair.of(i2, i1));
mesh.setTwin(edge, twin);
}
ccwEdges.add(edge);
}
for(int i = 0; i < nVertices; i++) {
E edge = ccwEdges.get(i);
E next = ccwEdges.get((i+1)%nVertices);
mesh.setNext(edge, next);
}
}
/**
* Reads a PSLG (.poly) from an {@link InputStream} and converts the file into a {@link IMesh}.
*
* @param inputStream the input stream
*
* @return a {@link Math} containing all segments and holes of the PSLG
*
* @throws IOException
*/
public IMesh<V, E, F> readMesh(@NotNull final InputStream inputStream) throws IOException {
return toMesh(inputStream, null);
}
public IMesh<V, E, F> readMesh(@NotNull final InputStream inputStream, @NotNull final Function<Integer, String> attrNameFunc) throws IOException {
return toMesh(inputStream, attrNameFunc);
}
/**
* Reads a PSLG (.poly) from an {@link InputStream} and converts the file into a {@link IMesh}.
*
* @param inputStream the input stream
* @return a {@link Math} containing all segments and holes of the PSLG
*
* @throws IOException
*/
private IMesh<V, E, F> toMesh(
@NotNull final InputStream inputStream,
@Nullable final Function<Integer, String> attrNameFunc) throws IOException {
mesh = meshSupplier.get();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = readLine(reader);
String[] split = line.split(SPLITTER);
int nVertex = Integer.parseInt(split[0].strip());
int dimension = Integer.parseInt(split[1].strip());
int boundaryMarker = Integer.parseInt(split[2].strip());
int targetMarker = Integer.parseInt(split[3].strip());
int nAttributes = Integer.parseInt(split[4].strip());
if(nAttributes > 1) {
throw new IOException("number of attributes > 1, is not jet supported.");
}
for(int i = 0; i < nVertex; i++) {
String vertexLine = readLine(reader);
split = vertexLine.split(SPLITTER);
int id = Integer.parseInt(split[0].strip());
int boundaryMark = Integer.parseInt(split[1].strip());
int targetMark = Integer.parseInt(split[2].strip());
double x = Double.parseDouble(split[3].strip());
double y = Double.parseDouble(split[4].strip());
V vertex = mesh.insertVertex(x, y);
vertices.put(id, vertex);
// TODO: ? boundaryMark?
if(attrNameFunc != null) {
for(int j = 1; j <= nAttributes; j++) {
mesh.setDoubleData(vertex, attrNameFunc.apply(j), Double.parseDouble(split[4+j]));
}
}
}
// border
// this is always 1
String nBorderString = readLine(reader);
assert Integer.parseInt(nBorderString.strip()) == 1;
String borderVertices = readLine(reader);
addFace(borderVertices, mesh.getBorder());
// triangles
Integer nTriangles = Integer.parseInt(readLine(reader).strip());
for(int i = 0; i < nTriangles; i++) {
F face = mesh.createFace();
addFace(readLine(reader), face);
}
// holes
Integer nHoles = Integer.parseInt(readLine(reader).strip());
for(int i = 0; i < nHoles; i++) {
F face = mesh.createFace(true);
addFace(readLine(reader), face);
}
edges.clear();
vertices.clear();
assert mesh.isValid();
return mesh;
}
private static String readLine(@NotNull final BufferedReader reader) throws IOException {
String st;
while ((st = reader.readLine()) != null) {
st = st.strip();
if(!st.startsWith(COMMENT_MARKER) || st.strip().equals("")) {
break;
}
}
return st.strip();
}
}
package org.vadere.meshing.utils.io.poly;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.vadere.meshing.mesh.inter.IFace;
import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* The {@link MeshPolyWriter} transforms a {@link IMesh} into a ascii-poly {@link String} and writes into a file.
* It is the counterpart to {@link MeshPolyReader}.
*
* @param <V> the type of the vertices
* @param <E> the type of the half-edges
* @param <F> the type of the faces
*/
public class MeshPolyWriter<V extends IVertex, E extends IHalfEdge, F extends IFace> {
private final static String SEPARATOR = " ";
private final static int DIMENSION = 2;
public MeshPolyWriter() {}
/**
* Transforms a {@link IMesh} into a Poly-{@link String}.
*
* @param mesh the mesh
*
* @return a PSLG-{@link String}
*/
public String to2DPoly(@NotNull final IMesh<V, E, F> mesh) {
return to2DPoly(mesh, 0, null, v -> false);
}
/**
* Transforms a {@link IMesh} into a Poly-{@link String}.
*
* @param mesh the mesh
* @param nAttributes number of vertex attributes
* @param attrNameFunc a function attributeIndex -> attributeName
* @param targetPredicate mark a specific vertex to be a target vertex
*
* @return a PSLG-{@link String}
*/
public String to2DPoly(
@NotNull final IMesh<V, E, F> mesh,
int nAttributes,
@Nullable final Function<Integer, String> attrNameFunc,
@NotNull Predicate<V> targetPredicate) {
int dimension = 2;
int boundaryMarker = 1;
int targetMarker = 2;
StringBuilder builder = new StringBuilder();
builder.append("#nVertices dimension boundaryMarker targetMarker nAttributes\n");
builder.append(mesh.getNumberOfVertices() + SEPARATOR + dimension + SEPARATOR + boundaryMarker + SEPARATOR + targetMarker + SEPARATOR + nAttributes + "\n");
Map<V, Integer> map = new HashMap<>();
int id = 1;
for(V v : mesh.getVertices()) {
int boundary = mesh.isAtBoundary(v) ? 1 : 0;
int target = targetPredicate.test(v) ? targetMarker : 0;
map.put(v, id);
builder.append(String.format(Locale.US, "%d" + SEPARATOR + "%d" + SEPARATOR + "%d" + SEPARATOR + "%f" + SEPARATOR + "%f", id, boundary, target, v.getX(), v.getY()));
for (int j = 1; j <= nAttributes; j++) {
builder.append(String.format(Locale.US, SEPARATOR + "%f", mesh.getDoubleData(v, attrNameFunc.apply(j))));
}
builder.append("\n");
id++;
}
// 1 boundary
builder.append("# nBorders\n");
builder.append(1+"\n");
builder.append(mesh.getPoints(mesh.getBorder()).size() + SEPARATOR);
for(V v : mesh.getVertices(mesh.getBorder())) {
builder.append(map.get(v) + SEPARATOR);
}
builder.delete(builder.length()-SEPARATOR.length(), builder.length());
builder.append("\n");
builder.append("# nTriangels\n");
builder.append(mesh.getNumberOfFaces()+"\n");
builder.append("# nVertices vertexIds\n");
for(F face : mesh.getFaces()) {
//builder.append("1 0\n");
builder.append(mesh.getPoints(face).size() + SEPARATOR);
for(V v : mesh.getVertices(face)) {
builder.append(map.get(v) + SEPARATOR);
}
builder.delete(builder.length()-SEPARATOR.length(), builder.length());
builder.append("\n");
}
builder.append("# nHoles\n");
List<F> holes = mesh.getHoles();
builder.append(holes.size()+"\n");
//
for(F hole : holes) {
int size = mesh.getPoints(hole).size();
builder.append(size + SEPARATOR);
for(V V : mesh.getVertices(hole)) {
builder.append(map.get(V) + SEPARATOR);
}
builder.delete(builder.length()-SEPARATOR.length(), builder.length());
builder.append("\n");
}
builder.append("# interior points for each hole\n");
id = 1;
for(F hole : holes) {
VPolygon polygon = mesh.toPolygon(hole);
VPoint p = GeometryUtils.getInteriorPoint(polygon);
builder.append(String.format(Locale.US, "%d" + SEPARATOR +"%f" + SEPARATOR + "%f\n", id, p.getX(), p.getY()));