//---------------------------------CONSTRUCTORS---------------------------------// /** * Constructs a face with unknown status. * * @param v1 a face vertex * @param v2 a face vertex * @param v3 a face vertex */ public Face(Vertex v1, Vertex v2, Vertex v3) { this.v1 = v1; this.v2 = v2; this.v3 = v3; status = UNKNOWN; }
/** * Gets an array with the adjacent vertices * * @return array of the adjacent vertices */ public Vertex[] getAdjacentVertices() { Vertex[] vertices = new Vertex[adjacentVertices.Count]; for (int i = 0; i < adjacentVertices.Count; i++) { vertices[i] = adjacentVertices[i]; } return vertices; }
/** * Checks if an vertex is equal to another. To be equal, they have to have the same * coordinates(with some tolerance) and color * * @param anObject the other vertex to be tested * @return true if they are equal, false otherwise. */ public bool equals(Vertex vertex) { return Math.Abs(x - vertex.x) < TOL && Math.Abs(y - vertex.y) < TOL && Math.Abs(z - vertex.z) < TOL && color.Equals(vertex.color); }
//-----------------------------------OVERRIDES----------------------------------// /** * Clones the vertex object * * @return cloned vertex object */ public Vertex Clone() { Vertex clone = new Vertex(); clone.x = x; clone.y = y; clone.z = z; clone.color = color.Clone(); clone.status = status; clone.adjacentVertices = new List<Vertex>(); for (int i = 0; i < adjacentVertices.Count; i++) { clone.adjacentVertices.Add(adjacentVertices[i].Clone()); } return clone; }
//----------------------------------OTHERS--------------------------------------// /** * Sets a vertex as being adjacent to it * * @param adjacentVertex an adjacent vertex */ public void addAdjacentVertex(Vertex adjacentVertex) { if (!adjacentVertices.Contains(adjacentVertex)) { adjacentVertices.Add(adjacentVertex); } }
/** Swaps the starting point and the ending point */ private void swapEnds() { double distTemp = startDist; startDist = endDist; endDist = distTemp; int typeTemp = startType; startType = endType; endType = typeTemp; Vertex vertexTemp = startVertex; startVertex = endVertex; endVertex = vertexTemp; Point3d posTemp = startPos; startPos = endPos; endPos = posTemp; }
//---------------------------------PRIVATES-------------------------------------// /** * Sets an end as vertex (starting point if none end were defined, ending point otherwise) * * @param vertex the vertex that is an segment end * @return false if all the ends were already defined, true otherwise */ private bool setVertex(Vertex vertex) { //none end were defined - define starting point as VERTEX if (index == 0) { startVertex = vertex; startType = VERTEX; startDist = line.computePointToPointDistance(vertex.getPosition()); startPos = startVertex.getPosition(); index++; return true; } //starting point were defined - define ending point as VERTEX if (index == 1) { endVertex = vertex; endType = VERTEX; endDist = line.computePointToPointDistance(vertex.getPosition()); endPos = endVertex.getPosition(); index++; //defining middle based on the starting point //VERTEX-VERTEX-VERTEX if (startVertex.equals(endVertex)) { middleType = VERTEX; } //VERTEX-EDGE-VERTEX else if (startType == VERTEX) { middleType = EDGE; } //the ending point distance should be smaller than starting point distance if (startDist > endDist) { swapEnds(); } return true; } else { return false; } }
/** * Sets an end as edge (starting point if none end were defined, ending point otherwise) * * @param vertex1 one of the vertices of the intercepted edge * @param vertex2 one of the vertices of the intercepted edge * @return false if all ends were already defined, true otherwise */ private bool setEdge(Vertex vertex1, Vertex vertex2) { Point3d point1 = vertex1.getPosition(); Point3d point2 = vertex2.getPosition(); Vector3d edgeDirection = new Vector3d(point2.x - point1.x, point2.y - point1.y, point2.z - point1.z); Line edgeLine = new Line(edgeDirection, point1); if (index == 0) { startVertex = vertex1; startType = EDGE; startPos = line.computeLineIntersection(edgeLine); startDist = line.computePointToPointDistance(startPos); middleType = FACE; index++; return true; } else if (index == 1) { endVertex = vertex1; endType = EDGE; endPos = line.computeLineIntersection(edgeLine); endDist = line.computePointToPointDistance(endPos); middleType = FACE; index++; //the ending point distance should be smaller than starting point distance if (startDist > endDist) { swapEnds(); } return true; } else { return false; } }
/// <summary> /// 拥有相同位置的顶点被认为相等 /// </summary> /// <param name="vertex"></param> /// <returns></returns> public bool Equals(Vertex vertex) => Position.Equals(vertex.Position, EqualityTolerance);
//-------------------------------------OTHERS-----------------------------------// /** Invert face direction (normal direction) */ public void invert() { Vertex vertexTemp = v2; v2 = v1; v1 = vertexTemp; }
/** * Computes closest distance from a vertex to a plane * * @param vertex vertex used to compute the distance * @param face face representing the plane where it is contained * @return the closest distance from the vertex to the plane */ private double computeDistance(Vertex vertex, Face face) { Vector3d normal = face.getNormal(); double a = normal.x; double b = normal.y; double c = normal.z; double d = -(a * face.v1.x + b * face.v1.y + c * face.v1.z); return a * vertex.x + b * vertex.y + c * vertex.z + d; }
/** * Face breaker for VERTEX-FACE-EDGE / EDGE-FACE-VERTEX * * @param facePos face position on the faces array * @param newPos new vertex position * @param endVertex vertex used for splitting */ private void breakFaceInTwo(int facePos, Point3d newPos, Vertex endVertex) { Face face = faces[facePos]; faces.RemoveAt(facePos); Vertex vertex = addVertex(newPos, face.v1.getColor(), Vertex.BOUNDARY); if (endVertex.equals(face.v1)) { addFace(face.v1, vertex, face.v3); addFace(vertex, face.v2, face.v3); } else if (endVertex.equals(face.v2)) { addFace(face.v2, vertex, face.v1); addFace(vertex, face.v3, face.v1); } else { addFace(face.v3, vertex, face.v2); addFace(vertex, face.v1, face.v2); } }
/** * Face breaker for EDGE-FACE-EDGE * * @param facePos face position on the faces array * @param newPos1 new vertex position * @param newPos2 new vertex position * @param startVertex vertex used the new faces creation * @param endVertex vertex used for the new faces creation */ private void breakFaceInThree(int facePos, Point3d newPos1, Point3d newPos2, Vertex startVertex, Vertex endVertex) { Face face = faces[facePos]; faces.RemoveAt(facePos); Vertex vertex1 = addVertex(newPos1, face.v1.getColor(), Vertex.BOUNDARY); Vertex vertex2 = addVertex(newPos2, face.v1.getColor(), Vertex.BOUNDARY); if (startVertex.equals(face.v1) && endVertex.equals(face.v2)) { addFace(face.v1, vertex1, vertex2); addFace(face.v1, vertex2, face.v3); addFace(vertex1, face.v2, vertex2); } else if (startVertex.equals(face.v2) && endVertex.equals(face.v1)) { addFace(face.v1, vertex2, vertex1); addFace(face.v1, vertex1, face.v3); addFace(vertex2, face.v2, vertex1); } else if (startVertex.equals(face.v2) && endVertex.equals(face.v3)) { addFace(face.v2, vertex1, vertex2); addFace(face.v2, vertex2, face.v1); addFace(vertex1, face.v3, vertex2); } else if (startVertex.equals(face.v3) && endVertex.equals(face.v2)) { addFace(face.v2, vertex2, vertex1); addFace(face.v2, vertex1, face.v1); addFace(vertex2, face.v3, vertex1); } else if (startVertex.equals(face.v3) && endVertex.equals(face.v1)) { addFace(face.v3, vertex1, vertex2); addFace(face.v3, vertex2, face.v2); addFace(vertex1, face.v1, vertex2); } else { addFace(face.v3, vertex2, vertex1); addFace(face.v3, vertex1, face.v2); addFace(vertex2, face.v1, vertex1); } }
/** * Method used to add a vertex properly for internal methods * * @param pos vertex position * @param color vertex color * @param status vertex status * @return the vertex inserted (if a similar vertex already exists, this is returned) */ private Vertex addVertex(Point3d pos, Color3f color, int status) { int i; //if already there is an equal vertex, it is not inserted Vertex vertex = new Vertex(pos, color, status); for (i = 0; i < vertices.Count; i++) { if (vertex.equals(vertices[i])) break; } if (i == vertices.Count) { vertices.Add(vertex); return vertex; } else { vertex = vertices[i]; vertex.setStatus(status); return vertex; } }
//------------------------------------ADDS----------------------------------------// /** * Method used to add a face properly for internal methods * * @param v1 a face vertex * @param v2 a face vertex * @param v3 a face vertex */ private Face addFace(Vertex v1, Vertex v2, Vertex v3) { if (!(v1.equals(v2) || v1.equals(v3) || v2.equals(v3))) { Face face = new Face(v1, v2, v3); if (face.getArea() > TOL) { faces.Add(face); return face; } else { return null; } } else { return null; } }