use of org.twak.camp.Output.SharedEdge in project chordatlas by twak.
the class GreebleEdge method roowWallGreeble.
public static void roowWallGreeble(Output output, MeshBuilder roof, MeshBuilder wall) {
MultiMap<Point3d, SharedEdge> boundary = new MultiMap<>();
Set<SharedEdge> roofWallBoundary = new HashSet<>();
for (Face f1 : output.faces.values()) for (Loop<SharedEdge> sl : f1.edges) for (Loopable<SharedEdge> se : sl.loopableIterator()) {
Face f2 = se.get().getOther(f1);
if (isWall(f1) ^ isWall(f2)) {
boundary.put(se.get().getStart(f1), se.get());
roofWallBoundary.add(se.get());
}
}
for (SharedEdge se : roofWallBoundary) {
if (se.start.z < 1 || se.end.z < 1)
// something strange here...
continue;
Face f1 = se.left, f2 = se.right;
if (f1 == null || f2 == null)
continue;
EdgePoint bs = findAdjacent(se.start, se.end, boundary), be = findAdjacent(se.end, se.start, boundary);
if (bs != null && be != null) {
LinearForm3D cutS, cutE;
if (isOverhang(bs.se))
// between two angles
cutS = cut(bs.pt, se.start, se.end);
else
// flat at end
cutS = new LinearForm3D(LinearForm3D.linePerp(toXZ(se.end), toXZ(se.start)));
if (isOverhang(be.se))
cutE = cut(se.start, se.end, be.pt);
else
// flat at end
cutE = new LinearForm3D(LinearForm3D.linePerp(toXZ(se.start), toXZ(se.end)));
LinearForm3D right = new LinearForm3D(toXZ(f1.edge.getPlaneNormal()), toXZ(f1.edge.start)), left = new LinearForm3D(toXZ(f2.edge.getPlaneNormal()), toXZ(f2.edge.start));
Tube.tube(roof, Collections.singleton(cutS), Collections.singleton(cutE), new Line3d(toXZ(se.start), toXZ(se.end)), left, right, isOverhang(se) ? new OverhangCross() : new LipCross());
}
}
}
use of org.twak.camp.Output.SharedEdge in project chordatlas by twak.
the class GreebleEdge method roofGreeble.
public static boolean roofGreeble(Face f, MeshBuilder roof) {
boolean isWall = isWall(f);
for (Loop<SharedEdge> sl : f.edges) {
for (Loopable<SharedEdge> sel : sl.loopableIterator()) {
SharedEdge se = sel.get();
boolean otherIsWall = isWall(se.getOther(f));
if (!isWall && !otherIsWall) {
Face oF = se.getOther(f);
if (oF == null || order(f, oF) || f.edge.getPlaneNormal().angle(oF.edge.getPlaneNormal()) < 0.4)
continue;
List<LinearForm3D> start = new ArrayList(), end = new ArrayList<>();
{
SharedEdge fPrev = se.getAdjEdge(f, false), fNext = se.getAdjEdge(f, true), ofPrev = se.getAdjEdge(oF, false), ofNext = se.getAdjEdge(oF, true);
if (fNext == null || fPrev == null || ofNext == null || ofPrev == null)
continue;
double overHang = -0.03;
if (isWall(fNext.getOther(f)))
end.add(toLF(fNext.getOther(f), overHang));
else
end.add(roofTween(fNext, se, f));
if (isWall(ofPrev.getOther(oF)))
end.add(toLF(ofPrev.getOther(oF), overHang));
else
end.add(roofTween(se, ofPrev, oF));
if (isWall(fPrev.getOther(f)))
start.add(toLF(fPrev.getOther(f), overHang));
else
start.add(roofTween(se, fPrev, f));
if (isWall(ofNext.getOther(oF)))
start.add(toLF(ofNext.getOther(oF), overHang));
else
start.add(roofTween(ofNext, se, oF));
}
Point3d s = se.getStart(f), e = se.getEnd(f);
if (end.contains(null) || start.contains(null))
continue;
Tube.tube(roof, end, start, new Line3d(new Point3d(s.x, s.z, s.y), new Point3d(e.x, e.z, e.y)), toLF(f, 0), toLF(oF, 0), new CrossGen() {
@Override
public List<Point2d> gen(Vector2d left, Vector2d right) {
Vector2d l = new Vector2d(left);
l.normalize();
Vector2d lP = new Vector2d(l.y, -l.x);
Vector2d r = new Vector2d(right);
r.normalize();
Vector2d rP = new Vector2d(-r.y, r.x);
List<Point2d> out = new ArrayList();
double width = 0.15, height = 0.03;
Vector2d rn = new Vector2d(r);
rn.negate();
// height / Math.sin ( ( Math.PI - l.angle( rn ) ) /2 );
double cenOffset = 0.02;
Vector2d cen = new Vector2d(lP);
cen.add(rP);
cen.normalize();
for (double[] coords : new double[][] { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, -width }, { 0, 0, 0, height, -width }, { 0, 0, cenOffset, 0, 0 }, { -width, height, 0, 0, 0 }, { -width, 0, 0, 0, 0 } }) {
Point2d tmp = new Point2d(l), tmp2;
tmp.scale(coords[0]);
tmp2 = new Point2d(lP);
tmp2.scale(coords[1]);
tmp.add(tmp2);
tmp2 = new Point2d(cen);
tmp2.scale(coords[2]);
tmp.add(tmp2);
tmp2 = new Point2d(rP);
tmp2.scale(coords[3]);
tmp.add(tmp2);
tmp2 = new Point2d(r);
tmp2.scale(coords[4]);
tmp.add(tmp2);
out.add(tmp);
}
return out;
}
});
}
}
}
return true;
}
use of org.twak.camp.Output.SharedEdge in project chordatlas by twak.
the class GreebleHelper method findPerimeter.
public static LoopL<LPoint3d> findPerimeter(Face f) {
LoopL<LPoint3d> out = new LoopL<>();
for (Loop<SharedEdge> loop : f.edges) {
Loop<LPoint3d> lout = new Loop<>();
out.add(lout);
for (SharedEdge se : loop) {
String label;
Face other = se.getOther(f);
if (other == null || se.start.z < 0.1 && se.end.z < 0.1)
label = FLOOR_EDGE;
else if (GreebleEdge.isWall(other))
label = WALL_EDGE;
else
label = ROOF_EDGE;
Point3d pt = se.getStart(f);
if (pt != null)
lout.append(new LPoint3d(pt, label));
}
}
return out;
}
Aggregations