コード例 #1
0
    public static List <Contour> SubdivideContours(List <Contour> a_rOuterContours, float a_fStep)
    {
        List <Contour> oIteratedContoursList = new List <Contour>(a_rOuterContours.Count);

        foreach (Contour rOuterContour in a_rOuterContours)
        {
            // Simplify the new outer contour
            List <Vector2> oOuterContourVertices = new List <Vector2>(rOuterContour.Vertices);

            List <Vector2> oIteratedContourVertices = new List <Vector2>();
            for (int i = 0; i < oOuterContourVertices.Count; ++i)
            {
                Vector2 f2SegmentBegin = oOuterContourVertices[i];
                Vector2 f2SegmentEnd   = oOuterContourVertices[(i + 1) % oOuterContourVertices.Count];

                Vector2 f2SegmentDirection = f2SegmentEnd - f2SegmentBegin;
                float   fSegmentLength     = f2SegmentDirection.magnitude;

                int iSubdivisionCount = Mathf.RoundToInt(fSegmentLength / a_fStep);
                //iSubdivisionCount = 2;
                oIteratedContourVertices.Add(f2SegmentBegin);
                if (iSubdivisionCount > 1)
                {
                    f2SegmentDirection /= fSegmentLength;
                    float fSubdivisionStep = fSegmentLength / (float)(iSubdivisionCount);
                    for (int iSubdivision = 1; iSubdivision < iSubdivisionCount; ++iSubdivision)
                    {
                        oIteratedContourVertices.Add(f2SegmentBegin + f2SegmentDirection * fSubdivisionStep * iSubdivision);
                    }
                }
            }

            if (oIteratedContourVertices.Count > 2)
            {
                // Create the contour
                Contour oIteratedContour = new Contour(rOuterContour.Region);
                oIteratedContour.AddLast(oIteratedContourVertices);

                // Add the contour to the list
                oIteratedContoursList.Add(oIteratedContour);
            }
        }

        return(oIteratedContoursList);
    }
コード例 #2
0
	public static List<Contour> SimplifyContours( List<Contour> a_rOuterContours, float a_fAccuracy )
	{
		List<Contour> oSimplifiedContoursList = new List<Contour>( a_rOuterContours.Count );

		foreach( Contour rOuterContour in a_rOuterContours )
		{
			// Simplify the new outer contour
			List<Vector2> oOuterContourVertices = new List<Vector2>( rOuterContour.Vertices );

			List<Vector2> oSimplifiedOuterContourVertices = RamerDouglasPeuker( oOuterContourVertices, 0, oOuterContourVertices.Count - 1, a_fAccuracy );

			if( oSimplifiedOuterContourVertices.Count > 2 )
			{	
				// Create the contour
				Contour oSimplifiedOuterContour = new Contour( rOuterContour.Region );
				oSimplifiedOuterContour.AddLast( oSimplifiedOuterContourVertices );
	
				// Add the contour to the list
				oSimplifiedContoursList.Add( oSimplifiedOuterContour );
			}
		}

		return oSimplifiedContoursList;
	}
    public static List <Contour> SimplifyContours(List <Contour> a_rOuterContours, float a_fAccuracy)
    {
        List <Contour> oSimplifiedContoursList = new List <Contour>(a_rOuterContours.Count);

        foreach (Contour rOuterContour in a_rOuterContours)
        {
            // Simplify the new outer contour
            List <Vector2> oOuterContourVertices = new List <Vector2>(rOuterContour.Vertices);

            List <Vector2> oSimplifiedOuterContourVertices = RamerDouglasPeuker(oOuterContourVertices, 0, oOuterContourVertices.Count - 1, a_fAccuracy);

            if (oSimplifiedOuterContourVertices.Count > 2)
            {
                // Create the contour
                Contour oSimplifiedOuterContour = new Contour(rOuterContour.Region);
                oSimplifiedOuterContour.AddLast(oSimplifiedOuterContourVertices);

                // Add the contour to the list
                oSimplifiedContoursList.Add(oSimplifiedOuterContour);
            }
        }

        return(oSimplifiedContoursList);
    }
コード例 #4
0
    // Finds a pair of inner contour vertex / outer contour vertex that are mutually visible
    public static Contour InsertInnerContourIntoOuterContour(Contour a_rOuterContour, Contour a_rInnerContour)
    {
        // Look for the inner vertex of maximum x-value
        Vector2 f2InnerContourVertexMax = Vector2.one * int.MinValue;
        CircularLinkedListNode <Vector2> rMutualVisibleInnerContourVertexNode = null;

        CircularLinkedList <Vector2>     rInnerContourVertexList = a_rInnerContour.Vertices;
        CircularLinkedListNode <Vector2> rInnerContourVertexNode = rInnerContourVertexList.First;

        do
        {
            // x-value
            Vector2 f2InnerContourVertex = rInnerContourVertexNode.Value;

            // New max x found
            if (f2InnerContourVertexMax.x < f2InnerContourVertex.x)
            {
                f2InnerContourVertexMax = f2InnerContourVertex;
                rMutualVisibleInnerContourVertexNode = rInnerContourVertexNode;
            }

            // Go to next vertex
            rInnerContourVertexNode = rInnerContourVertexNode.Next;
        }while(rInnerContourVertexNode != rInnerContourVertexList.First);

        // Visibility ray
        Ray     oInnerVertexVisibilityRay = new Ray(f2InnerContourVertexMax, Vector3.right);
        float   fClosestDistance          = int.MaxValue;
        Vector2 f2ClosestOuterEdgeStart   = Vector2.zero;
        Vector2 f2ClosestOuterEdgeEnd     = Vector2.zero;

        Contour rOuterCutContour = new Contour(a_rOuterContour.Region);

        rOuterCutContour.AddLast(a_rOuterContour.Vertices);

        CircularLinkedList <Vector2>     rOuterCutContourVertexList   = rOuterCutContour.Vertices;
        CircularLinkedListNode <Vector2> rOuterContourVertexEdgeStart = null;

        // Raycast from the inner contour vertex to every edge
        CircularLinkedListNode <Vector2> rOuterContourVertexNode = rOuterCutContourVertexList.First;

        do
        {
            // Construct outer edge from current and next outer contour vertices
            Vector2 f2OuterEdgeStart = rOuterContourVertexNode.Value;
            Vector2 f2OuterEdgeEnd   = rOuterContourVertexNode.Next.Value;
            Vector2 f2OuterEdge      = f2OuterEdgeEnd - f2OuterEdgeStart;

            // Orthogonal vector to edge (pointing to polygon interior)
            Vector2 f2OuterEdgeNormal = Uni2DMathUtils.PerpVector2(f2OuterEdge);

            // Vector from edge start to inner vertex
            Vector2 f2OuterEdgeStartToInnerVertex = f2InnerContourVertexMax - f2OuterEdgeStart;

            // If the inner vertex is on the left of the edge (interior),
            // test if there's any intersection
            if (Vector2.Dot(f2OuterEdgeStartToInnerVertex, f2OuterEdgeNormal) >= 0.0f)
            {
                float fDistanceT;

                // If visibility intersects outer edge...
                if (Uni2DMathUtils.Raycast2DSegment(oInnerVertexVisibilityRay, f2OuterEdgeStart, f2OuterEdgeEnd, out fDistanceT) == true)
                {
                    // Is it the closest intersection we found?
                    if (fClosestDistance > fDistanceT)
                    {
                        fClosestDistance             = fDistanceT;
                        rOuterContourVertexEdgeStart = rOuterContourVertexNode;

                        f2ClosestOuterEdgeStart = f2OuterEdgeStart;
                        f2ClosestOuterEdgeEnd   = f2OuterEdgeEnd;
                    }
                }
            }

            // Go to next edge
            rOuterContourVertexNode = rOuterContourVertexNode.Next;
        }while(rOuterContourVertexNode != rOuterCutContourVertexList.First);

        // Take the vertex of maximum x-value from the closest intersected edge
        Vector2 f2ClosestVisibleOuterContourVertex;
        CircularLinkedListNode <Vector2> rMutualVisibleOuterContourVertexNode;

        if (f2ClosestOuterEdgeStart.x < f2ClosestOuterEdgeEnd.x)
        {
            f2ClosestVisibleOuterContourVertex   = f2ClosestOuterEdgeEnd;
            rMutualVisibleOuterContourVertexNode = rOuterContourVertexEdgeStart.Next;
        }
        else
        {
            f2ClosestVisibleOuterContourVertex   = f2ClosestOuterEdgeStart;
            rMutualVisibleOuterContourVertexNode = rOuterContourVertexEdgeStart;
        }

        // Looking for points inside the triangle defined by inner vertex, intersection point an closest outer vertex
        // If a point is inside this triangle, at least one is a reflex vertex
        // The closest reflex vertex which minimises the angle this-vertex/inner vertex/intersection vertex
        // would be choosen as the mutual visible vertex
        Vector3 f3IntersectionPoint = oInnerVertexVisibilityRay.GetPoint(fClosestDistance);
        Vector2 f2InnerContourVertexToIntersectionPoint           = new Vector2(f3IntersectionPoint.x, f3IntersectionPoint.y) - f2InnerContourVertexMax;
        Vector2 f2NormalizedInnerContourVertexToIntersectionPoint = f2InnerContourVertexToIntersectionPoint.normalized;

        float fMaxDotAngle = float.MinValue;
        float fMinDistance = float.MaxValue;

        rOuterContourVertexNode = rOuterCutContourVertexList.First;
        do
        {
            Vector2 f2OuterContourVertex = rOuterContourVertexNode.Value;

            // if vertex not part of triangle
            if (f2OuterContourVertex != f2ClosestVisibleOuterContourVertex)
            {
                // if vertex is inside triangle...
                if (Uni2DMathUtils.IsPointInsideTriangle(f2InnerContourVertexMax, f3IntersectionPoint, f2ClosestVisibleOuterContourVertex, f2OuterContourVertex) == true)
                {
                    // if vertex is reflex
                    Vector2 f2PreviousOuterContourVertex = rOuterContourVertexNode.Previous.Value;
                    Vector2 f2NextOuterContourVertex     = rOuterContourVertexNode.Next.Value;

                    if (IsReflexVertex(f2OuterContourVertex, f2PreviousOuterContourVertex, f2NextOuterContourVertex) == true)
                    {
                        // Use dot product as distance
                        Vector2 f2InnerContourVertexToReflexVertex = f2OuterContourVertex - f2InnerContourVertexMax;

                        // INFO: f2NormalizedInnerContourVertexToIntersectionPoint == Vector3.right (if everything is right)
                        float fDistance = Vector2.Dot(f2NormalizedInnerContourVertexToIntersectionPoint, f2InnerContourVertexToReflexVertex);
                        float fDotAngle = Vector2.Dot(f2NormalizedInnerContourVertexToIntersectionPoint, f2InnerContourVertexToReflexVertex.normalized);

                        // New mutual visible vertex if angle smaller (e.g. dot angle larger) than min or equal and closer
                        if (fDotAngle > fMaxDotAngle || (fDotAngle == fMaxDotAngle && fDistance < fMinDistance))
                        {
                            fMaxDotAngle = fDotAngle;
                            fMinDistance = fDistance;
                            rMutualVisibleOuterContourVertexNode = rOuterContourVertexNode;
                        }
                    }
                }
            }

            // Go to next vertex
            rOuterContourVertexNode = rOuterContourVertexNode.Next;
        }while(rOuterContourVertexNode != rOuterCutContourVertexList.First);

        // Insert now the cut into the polygon
        // The cut starts from the outer contour mutual visible vertex to the inner vertex
        CircularLinkedListNode <Vector2> rOuterContourVertexNodeToInsertBefore = rMutualVisibleOuterContourVertexNode.Next;

        // Loop over the inner contour starting from the inner contour vertex...
        rInnerContourVertexNode = rMutualVisibleInnerContourVertexNode;
        do
        {
            // ... add the inner contour vertex before the outer contour vertex after the cut
            rOuterCutContourVertexList.AddBefore(rOuterContourVertexNodeToInsertBefore, rInnerContourVertexNode.Value);
            rInnerContourVertexNode = rInnerContourVertexNode.Next;
        }while(rInnerContourVertexNode != rMutualVisibleInnerContourVertexNode);

        // Close the cut by doubling the inner and outer contour vertices
        rOuterCutContourVertexList.AddBefore(rOuterContourVertexNodeToInsertBefore, rMutualVisibleInnerContourVertexNode.Value);
        rOuterCutContourVertexList.AddBefore(rOuterContourVertexNodeToInsertBefore, rMutualVisibleOuterContourVertexNode.Value);

        return(rOuterCutContour);
    }
コード例 #5
0
	// Finds a pair of inner contour vertex / outer contour vertex that are mutually visible
	public static Contour InsertInnerContourIntoOuterContour( Contour a_rOuterContour, Contour a_rInnerContour )
	{
		// Look for the inner vertex of maximum x-value
		Vector2 f2InnerContourVertexMax = Vector2.one * int.MinValue;
		CircularLinkedListNode<Vector2> rMutualVisibleInnerContourVertexNode = null;

		CircularLinkedList<Vector2> rInnerContourVertexList = a_rInnerContour.Vertices;
		CircularLinkedListNode<Vector2> rInnerContourVertexNode = rInnerContourVertexList.First;
		
		do
		{
			// x-value
			Vector2 f2InnerContourVertex = rInnerContourVertexNode.Value;

			// New max x found
			if( f2InnerContourVertexMax.x < f2InnerContourVertex.x )
			{
				f2InnerContourVertexMax = f2InnerContourVertex;
				rMutualVisibleInnerContourVertexNode = rInnerContourVertexNode;
			}

			// Go to next vertex
			rInnerContourVertexNode = rInnerContourVertexNode.Next;
		}
		while( rInnerContourVertexNode != rInnerContourVertexList.First );

		// Visibility ray
		Ray oInnerVertexVisibilityRay = new Ray( f2InnerContourVertexMax, Vector3.right );
		float fClosestDistance = int.MaxValue;
		Vector2 f2ClosestOuterEdgeStart = Vector2.zero;
		Vector2 f2ClosestOuterEdgeEnd = Vector2.zero;

		Contour rOuterCutContour = new Contour( a_rOuterContour.Region );
		rOuterCutContour.AddLast( a_rOuterContour.Vertices );

		CircularLinkedList<Vector2> rOuterCutContourVertexList = rOuterCutContour.Vertices;
		CircularLinkedListNode<Vector2> rOuterContourVertexEdgeStart = null;

		// Raycast from the inner contour vertex to every edge
		CircularLinkedListNode<Vector2> rOuterContourVertexNode = rOuterCutContourVertexList.First;
		do
		{
			// Construct outer edge from current and next outer contour vertices
			Vector2 f2OuterEdgeStart = rOuterContourVertexNode.Value;
			Vector2 f2OuterEdgeEnd = rOuterContourVertexNode.Next.Value;
			Vector2 f2OuterEdge = f2OuterEdgeEnd - f2OuterEdgeStart;

			// Orthogonal vector to edge (pointing to polygon interior)
			Vector2 f2OuterEdgeNormal = Uni2DMathUtils.PerpVector2( f2OuterEdge );

			// Vector from edge start to inner vertex
			Vector2 f2OuterEdgeStartToInnerVertex = f2InnerContourVertexMax - f2OuterEdgeStart;

			// If the inner vertex is on the left of the edge (interior),
			// test if there's any intersection
			if( Vector2.Dot( f2OuterEdgeStartToInnerVertex, f2OuterEdgeNormal ) >= 0.0f )
			{
				float fDistanceT;

				// If visibility intersects outer edge... 
				if( Uni2DMathUtils.Raycast2DSegment( oInnerVertexVisibilityRay, f2OuterEdgeStart, f2OuterEdgeEnd, out fDistanceT ) == true )
				{
					// Is it the closest intersection we found?
					if( fClosestDistance > fDistanceT )
					{
						fClosestDistance = fDistanceT;
						rOuterContourVertexEdgeStart = rOuterContourVertexNode;

						f2ClosestOuterEdgeStart = f2OuterEdgeStart;
						f2ClosestOuterEdgeEnd = f2OuterEdgeEnd;
					}
				}
			}

			// Go to next edge
			rOuterContourVertexNode = rOuterContourVertexNode.Next;
		}
		while( rOuterContourVertexNode != rOuterCutContourVertexList.First );

		// Take the vertex of maximum x-value from the closest intersected edge
		Vector2 f2ClosestVisibleOuterContourVertex;
		CircularLinkedListNode<Vector2> rMutualVisibleOuterContourVertexNode;
		if( f2ClosestOuterEdgeStart.x < f2ClosestOuterEdgeEnd.x )
		{
			f2ClosestVisibleOuterContourVertex = f2ClosestOuterEdgeEnd;
			rMutualVisibleOuterContourVertexNode = rOuterContourVertexEdgeStart.Next;
		}
		else
		{
			f2ClosestVisibleOuterContourVertex = f2ClosestOuterEdgeStart;
			rMutualVisibleOuterContourVertexNode = rOuterContourVertexEdgeStart;
		}

		// Looking for points inside the triangle defined by inner vertex, intersection point an closest outer vertex
		// If a point is inside this triangle, at least one is a reflex vertex
		// The closest reflex vertex which minimises the angle this-vertex/inner vertex/intersection vertex
		// would be choosen as the mutual visible vertex
		Vector3 f3IntersectionPoint = oInnerVertexVisibilityRay.GetPoint( fClosestDistance );
		Vector2 f2InnerContourVertexToIntersectionPoint = new Vector2( f3IntersectionPoint.x, f3IntersectionPoint.y ) - f2InnerContourVertexMax;
		Vector2 f2NormalizedInnerContourVertexToIntersectionPoint = f2InnerContourVertexToIntersectionPoint.normalized;

		float fMaxDotAngle = float.MinValue;
		float fMinDistance = float.MaxValue;
		rOuterContourVertexNode = rOuterCutContourVertexList.First;
		do
		{
			Vector2 f2OuterContourVertex = rOuterContourVertexNode.Value;

			// if vertex not part of triangle
			if( f2OuterContourVertex != f2ClosestVisibleOuterContourVertex )
			{
				// if vertex is inside triangle...
				if( Uni2DMathUtils.IsPointInsideTriangle( f2InnerContourVertexMax, f3IntersectionPoint, f2ClosestVisibleOuterContourVertex, f2OuterContourVertex ) == true )
				{
					// if vertex is reflex
					Vector2 f2PreviousOuterContourVertex = rOuterContourVertexNode.Previous.Value;
					Vector2 f2NextOuterContourVertex = rOuterContourVertexNode.Next.Value;
	
					if( IsReflexVertex( f2OuterContourVertex, f2PreviousOuterContourVertex, f2NextOuterContourVertex ) == true )
					{
						// Use dot product as distance
						Vector2 f2InnerContourVertexToReflexVertex = f2OuterContourVertex - f2InnerContourVertexMax;

						// INFO: f2NormalizedInnerContourVertexToIntersectionPoint == Vector3.right (if everything is right)
						float fDistance = Vector2.Dot( f2NormalizedInnerContourVertexToIntersectionPoint, f2InnerContourVertexToReflexVertex );
						float fDotAngle = Vector2.Dot( f2NormalizedInnerContourVertexToIntersectionPoint, f2InnerContourVertexToReflexVertex.normalized );

						// New mutual visible vertex if angle smaller (e.g. dot angle larger) than min or equal and closer
						if( fDotAngle > fMaxDotAngle || ( fDotAngle == fMaxDotAngle && fDistance < fMinDistance ) )
						{
							fMaxDotAngle = fDotAngle;
							fMinDistance = fDistance;
							rMutualVisibleOuterContourVertexNode = rOuterContourVertexNode;
						}
					}
				}
			}

			// Go to next vertex
			rOuterContourVertexNode = rOuterContourVertexNode.Next;
		}
		while( rOuterContourVertexNode != rOuterCutContourVertexList.First );

		// Insert now the cut into the polygon
		// The cut starts from the outer contour mutual visible vertex to the inner vertex
		CircularLinkedListNode<Vector2> rOuterContourVertexNodeToInsertBefore = rMutualVisibleOuterContourVertexNode.Next;

		// Loop over the inner contour starting from the inner contour vertex...
		rInnerContourVertexNode = rMutualVisibleInnerContourVertexNode;
		do
		{
			// ... add the inner contour vertex before the outer contour vertex after the cut
			rOuterCutContourVertexList.AddBefore( rOuterContourVertexNodeToInsertBefore, rInnerContourVertexNode.Value );
			rInnerContourVertexNode = rInnerContourVertexNode.Next;
		}
		while( rInnerContourVertexNode != rMutualVisibleInnerContourVertexNode );

		// Close the cut by doubling the inner and outer contour vertices
		rOuterCutContourVertexList.AddBefore( rOuterContourVertexNodeToInsertBefore, rMutualVisibleInnerContourVertexNode.Value );
		rOuterCutContourVertexList.AddBefore( rOuterContourVertexNodeToInsertBefore, rMutualVisibleOuterContourVertexNode.Value );

		return rOuterCutContour;
	}
コード例 #6
0
	public static List<Contour> SubdivideContours( List<Contour> a_rOuterContours, float a_fStep )
	{
		List<Contour> oIteratedContoursList = new List<Contour>( a_rOuterContours.Count );

		foreach( Contour rOuterContour in a_rOuterContours )
		{
			// Simplify the new outer contour
			List<Vector2> oOuterContourVertices = new List<Vector2>( rOuterContour.Vertices );
			
			List<Vector2> oIteratedContourVertices = new List<Vector2>();
			for(int i = 0; i < oOuterContourVertices.Count; ++i)
			{
				Vector2 f2SegmentBegin = oOuterContourVertices[i];
				Vector2 f2SegmentEnd = oOuterContourVertices[(i+1)%oOuterContourVertices.Count];
				
				Vector2 f2SegmentDirection = f2SegmentEnd - f2SegmentBegin;
				float fSegmentLength = f2SegmentDirection.magnitude;
				
				int iSubdivisionCount = Mathf.RoundToInt(fSegmentLength / a_fStep);
				//iSubdivisionCount = 2;
				oIteratedContourVertices.Add(f2SegmentBegin);
				if(iSubdivisionCount > 1)
				{
					f2SegmentDirection /= fSegmentLength;
					float fSubdivisionStep = fSegmentLength/(float)(iSubdivisionCount);
					for(int iSubdivision = 1; iSubdivision < iSubdivisionCount; ++iSubdivision)
					{
						oIteratedContourVertices.Add(f2SegmentBegin + f2SegmentDirection * fSubdivisionStep * iSubdivision);
					}
				}
			}

			if( oIteratedContourVertices.Count > 2 )
			{	
				// Create the contour
				Contour oIteratedContour = new Contour( rOuterContour.Region );
				oIteratedContour.AddLast( oIteratedContourVertices );
	
				// Add the contour to the list
				oIteratedContoursList.Add( oIteratedContour );
			}
		}

		return oIteratedContoursList;
	}