use of org.fxyz.utils.FloatCollector in project FXyzLib by Birdasaur.
the class TriangulatedMesh method createMesh.
private TriangleMesh createMesh(int level) {
TriangleMesh m0 = null;
if (level > 0) {
m0 = createMesh(level - 1);
}
if (level == 0) {
//check for duplicates or too close
List<Integer> duplicates = IntStream.range(0, pointsExterior.size()).boxed().filter(i -> pointsExterior.get(i).substract(pointsExterior.get(i == pointsExterior.size() - 1 ? 0 : i + 1)).magnitude() < 100 * EPSILON).map(i -> i).collect(Collectors.toList());
duplicates.stream().sorted(Collections.reverseOrder()).forEach(i -> pointsExterior.remove(i.intValue()));
List<PolygonPoint> list = pointsExterior.stream().map(p -> new PolygonPoint(p.x, p.y)).collect(Collectors.toList());
Polygon poly = new Polygon(list);
if (bounds.get() != null) {
maxX = bounds.get().getMaxX();
minX = bounds.get().getMinX();
maxY = bounds.get().getMaxY();
minY = bounds.get().getMinY();
} else {
maxX = pointsExterior.stream().mapToDouble(p -> p.x).max().getAsDouble();
maxY = pointsExterior.stream().mapToDouble(p -> p.y).max().getAsDouble();
minX = pointsExterior.stream().mapToDouble(p -> p.x).min().getAsDouble();
minY = pointsExterior.stream().mapToDouble(p -> p.y).min().getAsDouble();
}
double rad = getHoleRadius();
if (pointsHoles != null) {
steinerPoints = 0;
numHoles = pointsHoles.size();
// holes
pointsHoles.forEach(pHole -> {
List<PolygonPoint> hole = pHole.stream().distinct().map(p -> new PolygonPoint(p.x, p.y)).collect(Collectors.toList());
holePoints.add(hole.size());
Polygon polyIn = new Polygon(hole);
poly.addHole(polyIn);
holes.add(hole);
});
} else if (rad > 0d) {
steinerPoints = 0;
numHoles = 1;
int num = 200;
holePoints.add(num);
// circular hole
List<PolygonPoint> hole = IntStream.range(0, num).mapToObj(i -> new PolygonPoint((maxX + minX) / 2d + rad * Math.cos((num - i) * 2d * Math.PI / num), (maxY + minY) / 2d + rad * Math.sin((num - i) * 2d * Math.PI / num))).collect(Collectors.toList());
Polygon polyIn = new Polygon(hole);
poly.addHole(polyIn);
holes.add(hole);
} else {
double radSteiner = Math.sqrt(Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)) / 8d;
// steiner points
steiner = IntStream.range(0, steinerPoints).mapToObj(i -> new PolygonPoint((maxX + minX) / 2d + radSteiner * Math.cos(i * 2d * Math.PI / steinerPoints), (maxY + minY) / 2d + radSteiner * Math.sin(i * 2d * Math.PI / steinerPoints))).collect(Collectors.toList());
poly.addSteinerPoints(steiner);
}
PolygonSet ps = new PolygonSet(poly);
Poly2Tri.triangulate(ps);
Polygon polRes = ps.getPolygons().get(0);
List<DelaunayTriangle> tri = polRes.getTriangles();
points1 = polRes.getPoints();
extPoints = points1.size();
if (pointsHoles != null || rad > 0d) {
holes.forEach(hole -> hole.forEach(points1::add));
} else {
steiner.forEach(points1::add);
}
int totalHolePoints = holePoints.stream().reduce(0, Integer::sum);
int numPoints = extPoints + steinerPoints + totalHolePoints;
FloatCollector pointsBottom = points1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY(), 0d)).collect(() -> new FloatCollector(points1.size() * 3), FloatCollector::add, FloatCollector::join);
FloatCollector pointsTop = points1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY(), height.get())).collect(() -> new FloatCollector(points1.size() * 3), FloatCollector::add, FloatCollector::join);
pointsBottom.join(pointsTop);
points0 = pointsBottom.toArray();
numVertices = points0.length / 3;
FloatCollector texBottom = points1.stream().flatMapToDouble(p -> DoubleStream.of((p.getX() - minX) / (maxX - minX), (p.getY() - minY) / (maxY - minY))).collect(() -> new FloatCollector(points1.size() * 2), FloatCollector::add, FloatCollector::join);
FloatCollector texTop = points1.stream().flatMapToDouble(p -> DoubleStream.of((p.getX() - minX) / (maxX - minX), (p.getY() - minY) / (maxY - minY))).collect(() -> new FloatCollector(points1.size() * 2), FloatCollector::add, FloatCollector::join);
texBottom.join(texTop);
texCoord0 = texBottom.toArray();
numTexCoords = texCoord0.length / 2;
texCoord1 = IntStream.range(0, numTexCoords).mapToObj(i -> new Point2D(texCoord0[2 * i], texCoord0[2 * i + 1])).collect(Collectors.toList());
List<int[]> listIndices = tri.stream().map((DelaunayTriangle t) -> {
int[] pIndex = new int[3];
for (int j = 0; j < 3; j++) {
final TriangulationPoint dt = t.points[j];
int[] toArray = IntStream.range(0, points1.size()).filter(i -> points1.get(i).equals(dt)).toArray();
if (toArray.length > 0) {
pIndex[j] = toArray[0];
} else {
System.out.println("Error " + points1);
}
}
return pIndex;
}).collect(Collectors.toList());
// faces
// base
IntStream streamBottom = listIndices.stream().map(i -> IntStream.of(i[0], i[0], i[2], i[2], i[1], i[1])).flatMapToInt(i -> i);
// top
IntStream streamTop = listIndices.stream().map(i -> IntStream.of(numPoints + i[0], numPoints + i[0], numPoints + i[1], numPoints + i[1], numPoints + i[2], numPoints + i[2])).flatMapToInt(i -> i);
// vertical, exterior
IntStream streamExtWalls = IntStream.range(0, extPoints - 1).mapToObj(i -> IntStream.of(i, i, i + 1, i + 1, i + 1 + numPoints, i + 1 + numPoints, i, i, i + 1 + numPoints, i + 1 + numPoints, i + numPoints, i + numPoints)).flatMapToInt(i -> i);
// vertical, exterior, close polygon
IntStream streamExtWallsClose = IntStream.of(extPoints - 1, extPoints - 1, 0, 0, 0 + numPoints, 0 + numPoints, extPoints - 1, extPoints - 1, 0 + numPoints, 0 + numPoints, numPoints + extPoints - 1, numPoints + extPoints - 1);
if (totalHolePoints > 0) {
// vertical, interior
// holes
int acuHolePoints0 = extPoints + steinerPoints, acuHolePoints1;
IntStream streamIntWalls = IntStream.empty();
for (List<PolygonPoint> hole : holes) {
acuHolePoints1 = acuHolePoints0 + hole.size() - 1;
IntStream streamIntWallsHole = IntStream.range(acuHolePoints0, acuHolePoints1).mapToObj(i -> IntStream.of(i, i, i + 1 + numPoints, i + 1 + numPoints, i + 1, i + 1, i, i, i + numPoints, i + numPoints, i + 1 + numPoints, i + 1 + numPoints)).flatMapToInt(i -> i);
streamIntWalls = IntStream.concat(streamIntWalls, streamIntWallsHole);
acuHolePoints0 = acuHolePoints1 + 1;
}
// vertical, interior, close holes
// holes
acuHolePoints0 = extPoints + steinerPoints;
IntStream streamIntWallsClose = IntStream.empty();
for (List<PolygonPoint> hole : holes) {
acuHolePoints1 = acuHolePoints0 + hole.size() - 1;
IntStream streamIntWallsCloseHole = IntStream.of(acuHolePoints1, acuHolePoints1, numPoints + acuHolePoints0, numPoints + acuHolePoints0, acuHolePoints0, acuHolePoints0, acuHolePoints1, acuHolePoints1, numPoints + acuHolePoints1, numPoints + acuHolePoints1, numPoints + acuHolePoints0, numPoints + acuHolePoints0);
streamIntWallsClose = IntStream.concat(streamIntWallsClose, streamIntWallsCloseHole);
acuHolePoints0 = acuHolePoints1 + 1;
}
faces0 = IntStream.concat(streamBottom, IntStream.concat(streamTop, IntStream.concat(streamExtWalls, IntStream.concat(streamExtWallsClose, IntStream.concat(streamIntWalls, streamIntWallsClose))))).toArray();
} else {
faces0 = IntStream.concat(streamBottom, IntStream.concat(streamTop, IntStream.concat(streamExtWalls, streamExtWallsClose))).toArray();
}
numFaces = faces0.length / 6;
} else if (m0 != null) {
points0 = new float[numVertices * m0.getPointElementSize()];
m0.getPoints().toArray(points0);
texCoord0 = new float[numTexCoords * m0.getTexCoordElementSize()];
m0.getTexCoords().toArray(texCoord0);
faces0 = new int[numFaces * m0.getFaceElementSize()];
m0.getFaces().toArray(faces0);
}
List<Point3D> points1 = IntStream.range(0, numVertices).mapToObj(i -> new Point3D(points0[3 * i], points0[3 * i + 1], points0[3 * i + 2])).collect(Collectors.toList());
texCoord1 = IntStream.range(0, numTexCoords).mapToObj(i -> new Point2D(texCoord0[2 * i], texCoord0[2 * i + 1])).collect(Collectors.toList());
List<Face3> faces1 = IntStream.range(0, numFaces).mapToObj(i -> new Face3(faces0[6 * i], faces0[6 * i + 2], faces0[6 * i + 4])).collect(Collectors.toList());
index.set(points1.size());
map.clear();
listFaces.clear();
listVertices.clear();
listVertices.addAll(points1);
faces1.forEach(face -> {
int v1 = face.p0;
int v2 = face.p1;
int v3 = face.p2;
if (level > 0) {
int a = getMiddle(v1, points1.get(v1), v2, points1.get(v2));
int b = getMiddle(v2, points1.get(v2), v3, points1.get(v3));
int c = getMiddle(v3, points1.get(v3), v1, points1.get(v1));
listFaces.add(new Face3(v1, a, c));
listFaces.add(new Face3(v2, b, a));
listFaces.add(new Face3(v3, c, b));
listFaces.add(new Face3(a, b, c));
} else {
listFaces.add(new Face3(v1, v2, v3));
}
});
map.clear();
numVertices = listVertices.size();
numFaces = listFaces.size();
List<Face3> textures1 = IntStream.range(0, faces0.length / 6).mapToObj(i -> new Face3(faces0[6 * i + 1], faces0[6 * i + 3], faces0[6 * i + 5])).collect(Collectors.toList());
index.set(texCoord1.size());
listTextures.clear();
textures1.forEach(face -> {
int v1 = face.p0;
int v2 = face.p1;
int v3 = face.p2;
if (level > 0) {
int a = getMiddle(v1, texCoord1.get(v1), v2, texCoord1.get(v2));
int b = getMiddle(v2, texCoord1.get(v2), v3, texCoord1.get(v3));
int c = getMiddle(v3, texCoord1.get(v3), v1, texCoord1.get(v1));
listTextures.add(new Face3(v1, a, c));
listTextures.add(new Face3(v2, b, a));
listTextures.add(new Face3(v3, c, b));
listTextures.add(new Face3(a, b, c));
} else {
listTextures.add(new Face3(v1, v2, v3));
}
});
map.clear();
texCoord0 = texCoord1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY())).collect(() -> new FloatCollector(texCoord1.size() * 2), FloatCollector::add, FloatCollector::join).toArray();
numTexCoords = texCoord0.length / 2;
textureCoords = texCoord0;
if (level == getLevel()) {
areaMesh.setWidth(maxX - minX);
areaMesh.setHeight(maxY - minY);
rectMesh.setWidth((int) Math.sqrt(texCoord0.length));
rectMesh.setHeight(texCoord0.length / ((int) Math.sqrt(texCoord0.length)));
smoothingGroups = getSmoothingGroups(listVertices, listFaces);
}
return createMesh();
}
Aggregations