[Bprocessor-commit] gl/src/net/sourceforge/bprocessor/gl/tool HoleTool.java,NONE,1.1
Status: Pre-Alpha
Brought to you by:
henryml
From: Nordholt <nor...@us...> - 2005-08-30 13:00:55
|
Update of /cvsroot/bprocessor/gl/src/net/sourceforge/bprocessor/gl/tool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4304 Added Files: HoleTool.java Log Message: Initial import --- NEW FILE: HoleTool.java --- //--------------------------------------------------------------------------------- // $Id: HoleTool.java,v 1.1 2005/08/30 13:00:33 nordholt Exp $ // // Copyright (c) 2005 The BProcessor Team (http://bprocessor.sourceforge.net) // Released under the Lesser GNU Public License v2.1 //--------------------------------------------------------------------------------- package net.sourceforge.bprocessor.gl.tool; import net.sourceforge.bprocessor.model.Edge; import net.sourceforge.bprocessor.model.Vertex; import net.sourceforge.bprocessor.model.Surface; import net.sourceforge.bprocessor.gl.GLView; import net.sourceforge.bprocessor.model.SurfaceFacade; import java.util.ArrayList; import java.util.List; import java.util.Iterator; import java.util.Set; import org.apache.log4j.Logger; /** * The tool to cut holes in surfaces. */ public class HoleTool extends DrawTool { /** The Logger */ private static Logger log = Logger.getLogger(HoleTool.class); /** * The Constructor * @param glv The 3D canvas */ public HoleTool(GLView glv) { super(glv); } /** * Add the last edge to the edgelist => hole. * A hole must to inside an other surface and must be a closed shape. * @param coord The end coordinate */ protected void endSurface(double[] coord) { /* * Override this method to check that only full surfaces are drawn, and * that these surfaces are overlap some other surface. */ //Much of this code is taken from DrawTool Edge activeEdge = glv.getView().getActiveEdge(); //no hole has only one edge. if (edges.size() > 1) { Vertex to = vertexCollide(coord); if (to != null) { // we have to change excisting surface edges.add(activeEdge); Vertex old = activeEdge.getTo(); activeEdge.setTo(null); updateEdge(activeEdge); removeVertex(old); activeEdge.setTo(to); updateEdge(activeEdge); Surface hole = createSurface(edges); Surface surface = insideCheck(hole); if (surface != null) { surface.addHole(hole); hole.setIsInner(true); } else { deleteSurface(hole); } } else { to = activeEdge.getTo(); removeEdge(activeEdge); removeVertex(to); } } glv.getView().setAlignVertex(null); glv.getView().setActiveEdge(null); edges = new ArrayList(); } /** * Gets the surface this hole is inside if any other wise returns null. * @param hole the we wish to check is ok. * @return the surface */ private Surface insideCheck(Surface hole) { Set surfaces = SurfaceFacade.getInstance().findAll(); Iterator it = surfaces.iterator(); Surface surf = null; while (it.hasNext()) { surf = (Surface)it.next(); if (hole.getId() != surf.getId()) { if (planeCheck(hole, surf)) { if (containedCheck(hole, surf)) { return surf; } } } } return null; } /** * Checks if a hole is contained in a surface, given that the hole and the * surface is in the same plane. * @param hole the hole * @param surf the surface * @return boolean indicating werther or not the hole is contained in the plane. */ private boolean containedCheck(Surface hole, Surface surf) { /*this is done by aplying the crossing numbers algorithm on every vertex *of the hole. Using the edges of the hole as rays we cover two vertecies *at a time. */ List holeEdges = hole.getEdges(); Iterator holeIt = holeEdges.iterator(); Edge holeEdge = null; boolean contained = true; if (holeIt.hasNext()) { holeEdge = (Edge)holeIt.next(); contained = crossingNumbers(holeEdge, surf); } while (holeIt.hasNext() && contained) { holeEdge = (Edge)holeIt.next(); if (holeIt.hasNext()) { holeEdge = (Edge)holeIt.next(); if (!crossingNumbers(holeEdge, surf)) { contained = false; } } } return contained; } /** * The crossing numbers algorithm to check if an edge is contained in an other surface. * @param edge the edge. * @param surf the surface. * @return a boolean werther or not the edge is contained */ private boolean crossingNumbers(Edge edge, Surface surf) { List surfEdges = surf.getEdges(); Iterator surfIt = surfEdges.iterator(); Edge holeEdge = edge; Vertex holeOr = holeEdge.getTo(); Vertex holeDir = holeEdge.getFrom().minus(holeOr); holeDir.scale(1 / holeDir.length()); boolean contained = true; int crossings = 0; while (surfIt.hasNext() && contained) { Edge surfEdge = (Edge)surfIt.next(); //in order to find intersections we get a parametrizied version of the edges //the origin point and direction vector for the surface edge Vertex surfOr = surfEdge.getTo(); Vertex surfDir = surfEdge.getFrom().minus(surfOr); surfDir.scale(1 / surfDir.length()); //formulars for finding intersections taken from http://www.realtimerendering.com/int/#I304 Vertex dirCross = surfDir.cross(holeDir); double denominator = dirCross.length() * dirCross.length(); if (denominator != 0) { Vertex orSubs = holeOr.minus(surfOr); double surfDet = orSubs.determinant(holeDir, dirCross); double holeDet = orSubs.determinant(surfDir, dirCross); double tSurf = surfDet / denominator; double tHole = holeDet / denominator; //checking if there is an intersection and if it is within the line segments if ((tSurf > 0) && (tHole > 0) && collide((surfOr.getX() + surfDir.getX() * tSurf), (holeOr.getX() + holeDir.getX() * tHole)) && collide((surfOr.getY() + surfDir.getY() * tSurf), (holeOr.getY() + holeDir.getY() * tHole)) && collide((surfOr.getZ() + surfDir.getZ() * tSurf), (holeOr.getZ() + holeDir.getZ() * tHole))) { //the parameters for the "from" point on the edges double tSurfFrom = 0; double tHoleFrom = 0; if (surfDir.getX() != 0) { tSurfFrom = ((surfEdge.getFrom().getX() - surfOr.getX()) / surfDir.getX()); } else if (surfDir.getY() != 0) { tSurfFrom = ((surfEdge.getFrom().getY() - surfOr.getY()) / surfDir.getY()); } else if (surfDir.getZ() != 0 && holeDir.getZ() != 0) { tSurfFrom = ((surfEdge.getFrom().getZ() - surfOr.getZ()) / surfDir.getZ()); } else { log.warn("outer surface edge has a zero vector direction vector"); } if (holeDir.getX() != 0) { tHoleFrom = ((holeEdge.getFrom().getX() - holeOr.getX()) / holeDir.getX()); } else if (holeDir.getY() != 0) { tHoleFrom = ((holeEdge.getFrom().getY() - holeOr.getY()) / holeDir.getY()); } else if (holeDir.getZ() != 0) { tHoleFrom = ((holeEdge.getFrom().getZ() - holeOr.getZ()) / holeDir.getZ()); } else { log.warn("inner surface edge has a zero vector direction vector"); } if (tHoleFrom > tHole) { contained = false; } else if (tSurfFrom > tSurf) { crossings++; } } } } if (crossings % 2 == 0) { contained = false; } return contained; } /** * Checks if a hole and a surface is in the same plane. * @param hole the hole * @param surf the surface * @return boolean indicating werther or not the hole and plane is in the same plane */ private boolean planeCheck(Surface hole, Surface surf) { //finding an equation for the plane of surface hole Vertex normal = hole.normal(); //doing a lot to get edges here, //we really just need a point in the plane List holeEdges = hole.getEdges(); Iterator it = holeEdges.iterator(); if (it.hasNext()) { Edge holeEdge = (Edge)it.next(); Vertex point = holeEdge.getTo(); /* * equation for the plane of hole is now * normal.getX()*(x - point.getX()) + * normal.getY()*(y - point.getY()) + * normal.getZ()*(z - point.getZ()) == 0 */ List edges = surf.getEdges(); Iterator edgeIt = edges.iterator(); boolean inPlane = true; while (edgeIt.hasNext() && inPlane) { Edge edge = (Edge)edgeIt.next(); Vertex to = edge.getTo(); Vertex from = edge.getFrom(); //might have to use an EPSILON here instead if ((normal.getX() * (to.getX() - point.getX()) + normal.getY() * (to.getY() - point.getY()) + normal.getZ() * (to.getZ() - point.getZ()) != 0) && (normal.getX() * (from.getX() - point.getX()) + normal.getY() * (from.getY() - point.getY()) + normal.getZ() * (from.getZ() - point.getZ()) != 0)) { inPlane = false; } } return inPlane; } else { return false; } } } |