예제 #1
0
파일: FaceEdge.cs 프로젝트: jeske/agg-sharp
        public FaceEdge(Face face, MeshEdge meshEdge, Vertex vertex)
        {
            this.containingFace = face;
            this.meshEdge = meshEdge;
            this.firstVertex = vertex;

            nextFaceEdge = null;
            prevFaceEdge = null;

            radialNextFaceEdge = radialPrevFaceEdge = this;
        }
예제 #2
0
		static public FaceTextureData Get(Face faceToGetTextureDataFor)
		{
			FaceTextureData plugin;
			facesWithTextureData.TryGetValue(faceToGetTextureDataFor, out plugin);

			if (plugin == null)
			{
				FaceTextureData newPlugin = new FaceTextureData();
				facesWithTextureData.Add(faceToGetTextureDataFor, newPlugin);

				return newPlugin;
			}

			return plugin;
		}
예제 #3
0
파일: MeshEdge.cs 프로젝트: jeske/agg-sharp
        public FaceEdge GetFaceEdge(Face faceToFindFaceEdgeFor)
        {
            foreach (FaceEdge faceEdge in faceToFindFaceEdgeFor.FaceEdges())
            {
                if (faceEdge.containingFace == faceToFindFaceEdgeFor)
                {
                    return faceEdge;
                }
            }

            return null;
        }
예제 #4
0
		public Face(Face faceToUseAsModel)
		{
		}
예제 #5
0
		public Face DeleteFace(Face faceToDelete)
		{
			throw new NotImplementedException();
		}
예제 #6
0
		private static void CreateFaceEdges(Vertex[] verticesToUse, List<MeshEdge> edgesToUse, Face createdFace)
		{
			FaceEdge prevFaceEdge = null;
			for (int i = 0; i < verticesToUse.Length - 1; i++)
			{
				MeshEdge currentMeshEdge = edgesToUse[i];
				FaceEdge currentFaceEdge = new FaceEdge(createdFace, currentMeshEdge, verticesToUse[i]);
				if (i == 0)
				{
					createdFace.firstFaceEdge = currentFaceEdge;
				}
				else
				{
					prevFaceEdge.nextFaceEdge = currentFaceEdge;
					currentFaceEdge.prevFaceEdge = prevFaceEdge;
				}
				currentFaceEdge.AddToRadialLoop(currentMeshEdge);
				prevFaceEdge = currentFaceEdge;
			}
			// make the last FaceEdge
			{
				MeshEdge currentMeshEdge = edgesToUse[verticesToUse.Length - 1];
				FaceEdge currentFaceEdge = new FaceEdge(createdFace, currentMeshEdge, verticesToUse[verticesToUse.Length - 1]);
				prevFaceEdge.nextFaceEdge = currentFaceEdge;
				currentFaceEdge.prevFaceEdge = prevFaceEdge;
				currentFaceEdge.nextFaceEdge = createdFace.firstFaceEdge;
				createdFace.firstFaceEdge.prevFaceEdge = currentFaceEdge;
				currentFaceEdge.AddToRadialLoop(currentMeshEdge);
			}
		}
예제 #7
0
		public void ReverseFaceEdges(Face faceToReverse)
		{
			FaceEdge temp = null;
			FaceEdge current = faceToReverse.firstFaceEdge;

			// swap next and prev for all nodes of
			// doubly linked list
			do
			{
				temp = current.prevFaceEdge;
				current.prevFaceEdge = current.nextFaceEdge;
				current.nextFaceEdge = temp;
				current = current.prevFaceEdge; // go to the next
			} while (current != faceToReverse.firstFaceEdge);

			faceToReverse.CalculateNormal();
		}
예제 #8
0
		public Face CreateFace(Vertex[] verticesToUse, CreateOption createOption = CreateOption.ReuseExisting)
		{
			if (verticesToUse.Length == 3
				&& (verticesToUse[0].Position == verticesToUse[1].Position
				|| verticesToUse[1].Position == verticesToUse[2].Position
				|| verticesToUse[2].Position == verticesToUse[0].Position))
			{
				return null;
			}
			if (verticesToUse.Length < 3)
			{
				throw new ArgumentException("A face cannot have less than 3 vertices.");
			}

			List<MeshEdge> edgesToUse = new List<MeshEdge>();
			for (int i = 0; i < verticesToUse.Length - 1; i++)
			{
				edgesToUse.Add(CreateMeshEdge(verticesToUse[i], verticesToUse[i + 1], createOption));
			}
			edgesToUse.Add(CreateMeshEdge(verticesToUse[verticesToUse.Length - 1], verticesToUse[0], createOption));

			// make the face and set it's data
			Face createdFace = new Face();

			CreateFaceEdges(verticesToUse, edgesToUse, createdFace);

			createdFace.CalculateNormal();

			faces.Add(createdFace);

			return createdFace;
		}
예제 #9
0
		public void SplitFace(Face faceToSplit, Vertex splitStartVertex, Vertex splitEndVertex, out MeshEdge meshEdgeCreatedDuringSplit, out Face faceCreatedDuringSplit)
		{
			if (!ContainsVertex(splitStartVertex) || !ContainsVertex(splitEndVertex))
			{
				throw new Exception("The mesh must contain the vertices you intend to split between.");
			}

			// we may want to be able to double up an edge for some operations (we'll have to see).
			if (FindMeshEdges(splitStartVertex, splitEndVertex).Count > 0)
			{
				// this also ensures that the face is more than 2 sided.
				throw new Exception("You cannot split a face on an existing edge.");
			}

			FaceEdge faceEdgeAfterSplitStart = null;
			FaceEdge faceEdgeAfterSplitEnd = null;
			int count = 0;
			foreach (FaceEdge faceEdge in faceToSplit.FaceEdges())
			{
				if (faceEdge.firstVertex == splitStartVertex)
				{
					faceEdgeAfterSplitStart = faceEdge;
					count++;
				}
				else if (faceEdge.firstVertex == splitEndVertex)
				{
					faceEdgeAfterSplitEnd = faceEdge;
					count++;
				}
				if (count == 2)
				{
					break; // stop if we found both face edges
				}
			}

			meshEdgeCreatedDuringSplit = CreateMeshEdge(splitStartVertex, splitEndVertex);
			faceCreatedDuringSplit = new Face(faceToSplit);

			faces.Add(faceCreatedDuringSplit);

			FaceEdge newFaceEdgeExistingFace = new FaceEdge(faceToSplit, meshEdgeCreatedDuringSplit, splitStartVertex);
			FaceEdge newFaceEdgeForNewFace = new FaceEdge(faceCreatedDuringSplit, meshEdgeCreatedDuringSplit, splitEndVertex);

			// get the new edges injected into the existing loop, spliting it in two.
			newFaceEdgeExistingFace.prevFaceEdge = faceEdgeAfterSplitStart.prevFaceEdge;
			newFaceEdgeForNewFace.prevFaceEdge = faceEdgeAfterSplitEnd.prevFaceEdge;

			faceEdgeAfterSplitStart.prevFaceEdge.nextFaceEdge = newFaceEdgeExistingFace;
			faceEdgeAfterSplitEnd.prevFaceEdge.nextFaceEdge = newFaceEdgeForNewFace;

			newFaceEdgeExistingFace.nextFaceEdge = faceEdgeAfterSplitEnd;
			newFaceEdgeForNewFace.nextFaceEdge = faceEdgeAfterSplitStart;

			faceEdgeAfterSplitStart.prevFaceEdge = newFaceEdgeForNewFace;
			faceEdgeAfterSplitEnd.prevFaceEdge = newFaceEdgeExistingFace;

			// make sure the first face edge of each face is valid
			faceToSplit.firstFaceEdge = newFaceEdgeExistingFace;
			faceCreatedDuringSplit.firstFaceEdge = newFaceEdgeForNewFace;

			// make sure the FaceEdges of the new face all point to the new face.
			foreach (FaceEdge faceEdge in faceCreatedDuringSplit.firstFaceEdge.NextFaceEdges())
			{
				faceEdge.containingFace = faceCreatedDuringSplit;
			}

			newFaceEdgeExistingFace.AddToRadialLoop(meshEdgeCreatedDuringSplit);
			newFaceEdgeForNewFace.AddToRadialLoop(meshEdgeCreatedDuringSplit);
		}
예제 #10
0
		public void UnsplitFace(Face faceToKeep, Face faceToDelete, MeshEdge meshEdgeToDelete)
		{
			if (faceToKeep == faceToDelete)
			{
				throw new Exception("Can't join face to itself");
			}

			// validate the edgeToDelete is in both faces, edgeToDelete is only in these two faces, the two faces only share this one edge and no other edges

			FaceEdge faceEdgeToDeleteOnFaceToKeep = meshEdgeToDelete.GetFaceEdge(faceToKeep);
			FaceEdge faceEdgeToDeleteOnFaceToDelete = meshEdgeToDelete.GetFaceEdge(faceToDelete);

			if (faceEdgeToDeleteOnFaceToKeep.firstVertex == faceEdgeToDeleteOnFaceToDelete.firstVertex)
			{
				throw new Exception("The faces have oposite windings and you cannot merge the edge");
			}

			faceEdgeToDeleteOnFaceToKeep.prevFaceEdge.nextFaceEdge = faceEdgeToDeleteOnFaceToDelete.nextFaceEdge;
			faceEdgeToDeleteOnFaceToDelete.nextFaceEdge.prevFaceEdge = faceEdgeToDeleteOnFaceToKeep.prevFaceEdge;

			faceEdgeToDeleteOnFaceToKeep.nextFaceEdge.prevFaceEdge = faceEdgeToDeleteOnFaceToDelete.prevFaceEdge;
			faceEdgeToDeleteOnFaceToDelete.prevFaceEdge.nextFaceEdge = faceEdgeToDeleteOnFaceToKeep.nextFaceEdge;

			// if the face we are deleting is the one that the face to keep was looking at as its starting face edge, move it to the next face edge
			if (faceToKeep.firstFaceEdge == faceEdgeToDeleteOnFaceToKeep)
			{
				faceToKeep.firstFaceEdge = faceToKeep.firstFaceEdge.nextFaceEdge;
			}

			// make sure the FaceEdges all point to the kept face.
			foreach (FaceEdge faceEdge in faceToKeep.firstFaceEdge.NextFaceEdges())
			{
				faceEdge.containingFace = faceToKeep;
			}

			DeleteMeshEdge(meshEdgeToDelete);

			// clear the data on the deleted face edge to help with debugging
			faceEdgeToDeleteOnFaceToKeep.meshEdge.VertexOnEnd[0] = null;
			faceEdgeToDeleteOnFaceToKeep.meshEdge.VertexOnEnd[1] = null;
			faceToDelete.firstFaceEdge = null;
			// take the face out of the face list
			faces.Remove(faceToDelete);
		}
예제 #11
0
파일: Mesh.cs 프로젝트: CNCBrasil/agg-sharp
		public bool DeleteMeshEdgeFromFace(Face faceToDeleteEdgeFrom, MeshEdge meshEdgeToDelete)
		{
			throw new NotImplementedException();
		}
예제 #12
0
        /// <summary>
        /// Split the face at the given plane.
        /// </summary>
        /// <param name="face">The face to split.</param>
        /// <param name="faceVertices">The list containing the vertices for the face.</param>
        /// <param name="plane">The plane to split at.</param>
        /// <param name="newFaces">The new faces created will be added to this list, not the mesh.</param>
        /// <param name="newVertices">The new vertices will be added to this list, not the mesh.</param>
        /// <param name="onPlaneDistance">Treat any distance less than this as not crossing the plane.</param>
        /// <param name="clipFace">An optional function that can be called to check if the given
        /// face should be clipped.</param>
        /// <returns>True if the face crosses the plane else false.</returns>
        public static bool Split(this Face face, List <Vector3Float> faceVertices, Plane plane, List <Face> newFaces, List <Vector3Float> newVertices, double onPlaneDistance, Func <Mesh.SplitData, bool> clipFace = null)
        {
            var v = new Vector3Float[]
            {
                faceVertices[face.v0],
                faceVertices[face.v1],
                faceVertices[face.v2]
            };

            // get the distance from the crossing plane
            var dist = v.Select(a => plane.GetDistanceFromPlane(a)).ToArray();

            // bool if each point is clipped
            var clipPoint = dist.Select(a => Math.Abs(a) > onPlaneDistance).ToArray();

            // bool if there is a clip on a line segment (between points)
            var clipSegment = clipPoint.Select((a, i) =>
            {
                var nextI = (i + 1) % 3;
                // if both points are clipped and they are on opposite sides of the clip plane
                return(clipPoint[i] && clipPoint[nextI] && ((dist[i] < 0 && dist[nextI] > 0) || (dist[i] > 0 && dist[nextI] < 0)));
            }).ToArray();

            // the number of segments that need to be clipped
            var segmentsClipped = clipSegment[0] ? 1 : 0;

            segmentsClipped += clipSegment[1] ? 1 : 0;
            segmentsClipped += clipSegment[2] ? 1 : 0;

            void ClipEdge(int vi0)
            {
                var vi1           = (vi0 + 1) % 3;
                var vi2           = (vi0 + 2) % 3;
                var totalDistance = Math.Abs(dist[vi0]) + Math.Abs(dist[vi1]);
                var ratioTodist0  = Math.Abs(dist[vi0]) / totalDistance;
                var newPoint      = v[vi0] + (v[vi1] - v[vi0]) * ratioTodist0;

                // add the new vertex
                newVertices.Add(newPoint);
            }

            switch (segmentsClipped)
            {
            // if 2 sides are clipped we will add 2 new vertices and 3 polygons
            case 2:
                if (clipFace?.Invoke(new Mesh.SplitData(face, dist)) != false)
                {
                    // find the side we are not going to clip
                    int vi0 = clipSegment[0] && clipSegment[1] ? 2
                                                        : clipSegment[0] && clipSegment[2] ? 1 : 0;
                    var vi1 = (vi0 + 1) % 3;
                    var vi2 = (vi0 + 2) % 3;
                    // get the current count
                    var vertexStart = newVertices.Count;
                    // add the existing vertices
                    newVertices.Add(v[vi0]);
                    newVertices.Add(v[vi1]);
                    newVertices.Add(v[vi2]);
                    // clip the edges, will add the new points
                    ClipEdge(vi1);
                    ClipEdge(vi2);
                    // add the new faces
                    newFaces.Add(new Face(vertexStart, vertexStart + 1, vertexStart + 3, newVertices));
                    newFaces.Add(new Face(vertexStart, vertexStart + 3, vertexStart + 4, newVertices));
                    newFaces.Add(new Face(vertexStart + 3, vertexStart + 2, vertexStart + 4, newVertices));
                    return(true);
                }

                break;

            // if 1 side is clipped we will add 1 new vertex and 2 polygons
            case 1:
            {
                // find the side we are going to clip
                int vi0 = clipSegment[0] ? 0 : clipSegment[1] ? 1 : 2;
                var vi1 = (vi0 + 1) % 3;
                var vi2 = (vi0 + 2) % 3;
                // get the current count
                var vertexStart = newVertices.Count;
                // add the existing vertices
                newVertices.Add(v[vi0]);
                newVertices.Add(v[vi1]);
                newVertices.Add(v[vi2]);
                // clip the edge, will add the new point
                ClipEdge(vi0);
                // add the new faces
                newFaces.Add(new Face(vertexStart, vertexStart + 3, vertexStart + 2, newVertices));
                newFaces.Add(new Face(vertexStart + 3, vertexStart + 1, vertexStart + 2, newVertices));
            }

                return(true);
            }

            return(false);
        }
예제 #13
0
 public SplitData(Face face, double[] dist)
 {
     this.Face = face;
     this.Dist = dist;
 }
예제 #14
0
        public void ReverseFace(int faceIndex)
        {
            var hold = Faces[faceIndex];

            Faces[faceIndex] = new Face(hold.v0, hold.v2, hold.v1, hold.normal);
        }
예제 #15
0
		public MeshFaceTraceable(Face face)
		{
			this.face = face;
		}