package oripa.fold; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.vecmath.Vector2d; import oripa.geom.GeomUtil; import oripa.geom.Line; import oripa.value.OriLine; public class FolderTool { // public void setCrossLine(List<OriLine> crossLines, OriLine line, List<OriFace> sortedFaces) { // crossLines.clear(); // for (OriFace face : sortedFaces) { // ArrayList<Vector2d> vv = new ArrayList<Vector2d>(); // int crossCount = 0; // for (OriHalfedge he : face.halfedges) { // OriLine l = new OriLine(he.positionForDisplay.x, he.positionForDisplay.y, // he.next.positionForDisplay.x, he.next.positionForDisplay.y, PaintConfig.inputLineType); // // double params[] = new double[2]; // boolean res = GeomUtil.getCrossPointParam(line.p0, line.p1, l.p0, l.p1, params); // if (res == true && params[0] > -0.001 && params[1] > -0.001 && params[0] < 1.001 && params[1] < 1.001) { // double param = params[1]; // crossCount++; // // Vector2d crossV = new Vector2d(); // crossV.x = (1.0 - param) * he.vertex.preP.x + param * he.next.vertex.preP.x; // crossV.y = (1.0 - param) * he.vertex.preP.y + param * he.next.vertex.preP.y; // // boolean isNewPoint = true; // for (Vector2d v2d : vv) { // if (GeomUtil.Distance(v2d, crossV) < 1) { // isNewPoint = false; // break; // } // } // if (isNewPoint) { // vv.add(crossV); // } // } // } // // if (vv.size() >= 2) { // crossLines.add(new OriLine(vv.get(0), vv.get(1), PaintConfig.inputLineType)); // } // } // // } BoundBox calcFoldedBoundingBox(List<OriFace> faces) { Vector2d foldedBBoxLT = new Vector2d(Double.MAX_VALUE, Double.MAX_VALUE); Vector2d foldedBBoxRB = new Vector2d(-Double.MAX_VALUE, -Double.MAX_VALUE); for (OriFace face : faces) { for (OriHalfedge he : face.halfedges) { foldedBBoxLT.x = Math.min(foldedBBoxLT.x, he.tmpVec.x); foldedBBoxLT.y = Math.min(foldedBBoxLT.y, he.tmpVec.y); foldedBBoxRB.x = Math.max(foldedBBoxRB.x, he.tmpVec.x); foldedBBoxRB.y = Math.max(foldedBBoxRB.y, he.tmpVec.y); } } return new BoundBox(foldedBBoxLT, foldedBBoxRB); } boolean isLineCrossFace4(OriFace face, OriHalfedge heg, double size) { Vector2d p1 = heg.positionAfterFolded; Vector2d p2 = heg.next.positionAfterFolded; Vector2d dir = new Vector2d(); dir.sub(p2, p1); Line heLine = new Line(p1, dir); for (OriHalfedge he : face.halfedges) { // About the relation of contours (?) // Check if the line is on the countour of the face if (GeomUtil.DistancePointToLine(he.positionAfterFolded, heLine) < 1 && GeomUtil.DistancePointToLine(he.next.positionAfterFolded, heLine) < 1) { return false; } } Vector2d preCrossPoint = null; for (OriHalfedge he : face.halfedges) { // Checks if the line crosses any of the edges of the face Vector2d cp = GeomUtil.getCrossPoint(he.positionAfterFolded, he.next.positionAfterFolded, heg.positionAfterFolded, heg.next.positionAfterFolded); if (cp == null) { continue; } if (preCrossPoint == null) { preCrossPoint = cp; } else { if (GeomUtil.Distance(cp, preCrossPoint) > size * 0.001) { return true; } } } // Checkes if the line is in the interior of the face if (isOnFace(face, heg.positionAfterFolded, size)) { return true; } if (isOnFace(face, heg.next.positionAfterFolded, size)) { return true; } return false; } private boolean isOnFace(OriFace face, Vector2d v, double size) { int heNum = face.halfedges.size(); // Return false if the vector is on the contour of the face for (int i = 0; i < heNum; i++) { OriHalfedge he = face.halfedges.get(i); if (GeomUtil.DistancePointToSegment(v, he.positionAfterFolded, he.next.positionAfterFolded) < size * 0.001) { return false; } } OriHalfedge baseHe = face.halfedges.get(0); boolean baseFlg = GeomUtil.CCWcheck(baseHe.positionAfterFolded, baseHe.next.positionAfterFolded, v); for (int i = 1; i < heNum; i++) { OriHalfedge he = face.halfedges.get(i); if (GeomUtil.CCWcheck(he.positionAfterFolded, he.next.positionAfterFolded, v) != baseFlg) { return false; } } return true; } // Turn the model over public void filpAll(OrigamiModel origamiModel) { Vector2d maxV = new Vector2d(-Double.MAX_VALUE, -Double.MAX_VALUE); Vector2d minV = new Vector2d(Double.MAX_VALUE, Double.MAX_VALUE); List<OriFace> faces = origamiModel.getFaces(); for (OriFace face : faces) { face.z_order = -face.z_order; for (OriHalfedge he : face.halfedges) { maxV.x = Math.max(maxV.x, he.vertex.p.x); maxV.y = Math.max(maxV.y, he.vertex.p.y); minV.x = Math.min(minV.x, he.vertex.p.x); minV.y = Math.min(minV.y, he.vertex.p.y); } } double centerX = (maxV.x + minV.x) / 2; for (OriFace face : faces) { for (OriHalfedge he : face.halfedges) { he.positionForDisplay.x = 2 * centerX - he.positionForDisplay.x; } } for (OriFace face : faces) { face.faceFront = !face.faceFront; face.setOutline(); } Collections.sort(faces, new FaceOrderComparator()); Collections.reverse(origamiModel.getSortedFaces()); } // public void setFacesOutline( List<OriVertex> vertices, List<OriFace> faces, boolean isSlide) { int minDepth = Integer.MAX_VALUE; int maxDepth = -Integer.MAX_VALUE; for (OriFace f : faces) { minDepth = Math.min(minDepth, f.z_order); maxDepth = Math.max(minDepth, f.z_order); for (OriHalfedge he : f.halfedges) { he.positionForDisplay.set(he.vertex.p); } f.setOutline(); } if (isSlide) { double slideUnit = 10.0 / (maxDepth - minDepth); for (OriVertex v : vertices) { v.tmpFlg = false; v.tmpVec.set(v.p); } for (OriFace f : faces) { Vector2d faceCenter = new Vector2d(); for (OriHalfedge he : f.halfedges) { faceCenter.add(he.vertex.p); } faceCenter.scale(1.0 / f.halfedges.size()); for (OriHalfedge he : f.halfedges) { if (he.vertex.tmpFlg) { continue; } he.vertex.tmpFlg = true; he.vertex.tmpVec.x += slideUnit * f.z_order; he.vertex.tmpVec.y += slideUnit * f.z_order; Vector2d dirToCenter = new Vector2d(faceCenter); dirToCenter.sub(he.vertex.tmpVec); dirToCenter.normalize(); dirToCenter.scale(6.0); he.vertex.tmpVec.add(dirToCenter); } } for (OriFace f : faces) { for (OriHalfedge he : f.halfedges) { he.positionForDisplay.set(he.vertex.tmpVec); } f.setOutline(); } } } public boolean cleanDuplicatedLines(Collection<OriLine> creasePattern) { System.out.println("pre cleanDuplicatedLines " + creasePattern.size()); ArrayList<OriLine> tmpLines = new ArrayList<OriLine>(creasePattern.size()); for (OriLine l : creasePattern) { OriLine ll = l; boolean bSame = false; // Test if the line is already in tmpLines to prevent duplicity for (OriLine line : tmpLines) { if (GeomUtil.isSameLineSegment(line, ll)) { bSame = true; break; } } if (bSame) { continue; } tmpLines.add(ll); } if (creasePattern.size() == tmpLines.size()) { return false; } creasePattern.clear(); creasePattern.addAll(tmpLines); System.out.println("after cleanDuplicatedLines " + creasePattern.size()); return true; } }