コード例 #1
0
ファイル: Point.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 /// Initializes a new instance of the <see cref="Point"/> class.
 /// </summary>
 /// <param name="vertex">The vertex.</param>
 /// <param name="x">The x.</param>
 /// <param name="y">The y.</param>
 /// <param name="z">The z.</param>
 public Point(Vertex vertex, double x, double y, double z)
 {
     References = new List<Vertex> { vertex };
     X = x;
     Y = y;
     Z = z;
 }
コード例 #2
0
ファイル: Edge.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 ///     Initializes a new instance of the <see cref="Edge" /> class.
 /// </summary>
 /// <param name="fromVertex">From vertex.</param>
 /// <param name="toVertex">To vertex.</param>
 /// <param name="ownedFace">The face.</param>
 /// <param name="otherFace">The other face.</param>
 /// <param name="doublyLinkedFaces"></param>
 /// <param name="doublyLinkedVertices"></param>
 public Edge(Vertex fromVertex, Vertex toVertex, PolygonalFace ownedFace, PolygonalFace otherFace,
     Boolean doublyLinkedFaces = false, Boolean doublyLinkedVertices = false)
 {
     From = fromVertex;
     To = toVertex;
     _ownedFace = ownedFace;
     _otherFace = otherFace;
     if (doublyLinkedVertices)
     {
         fromVertex.Edges.Add(this);
         toVertex.Edges.Add(this);
     }
     if (doublyLinkedFaces)
     {
         if (_ownedFace != null) _ownedFace.Edges.Add(this);
         if (_otherFace != null) _otherFace.Edges.Add(this);
     }
     Vector = new[]
     {
         (To.Position[0] - From.Position[0]),
         (To.Position[1] - From.Position[1]),
         (To.Position[2] - From.Position[2])
     };
     Length =
         Math.Sqrt(Vector[0] * Vector[0] + Vector[1] * Vector[1] + Vector[2] * Vector[2]);
     DefineInternalEdgeAngle();
 }
コード例 #3
0
ファイル: 3DLineFunctions.cs プロジェクト: mvelayati/TVGL
 internal static Vertex PointOnPlaneFromIntersectingLine(double[] normalOfPlane, double distOfPlane, Vertex point1, Vertex point2)
 {
     var d1 = normalOfPlane.dotProduct(point1.Position);
     var d2 = normalOfPlane.dotProduct(point2.Position);
     var fraction = (d1 - distOfPlane) / (d1 - d2);
     var position = new double[3];
     for (var i = 0; i < 3; i++)
         position[i] = point2.Position[i] * fraction + point1.Position[i] * (1 - fraction);
     return new Vertex(position);
 }
コード例 #4
0
ファイル: Slice.cs プロジェクト: mvelayati/TVGL
 private static int FindPrevContactElement(List<ContactElement> contacts, ContactElement current,
     out Vertex connectingVertex)
 {
     // this is the same as "FindNextContactElement" except it works backwards. Some subtle differences
     // in the queries between the two functions
     if (current is ThroughVertexContactElement)
     {
         for (int i = 0; i < contacts.Count; i++)
         {
             var ce = contacts[i];
             if (ce is ThroughFaceContactElement && ce.SplitFacePositive == current.SplitFaceNegative)
             {
                 connectingVertex = ce.StartVertex;
                 return i;
             }
         }
         connectingVertex = null;
         return -1;
     }
     else if (current is CoincidentEdgeContactElement)
     {
         for (int i = 0; i < contacts.Count; i++)
         {
             var ce = contacts[i];
             if (ce is CoincidentEdgeContactElement &&
                 ((CoincidentEdgeContactElement)ce).EndVertex ==
                 ((CoincidentEdgeContactElement)current).StartVertex)
             {
                 connectingVertex = ((CoincidentEdgeContactElement)ce).EndVertex;
                 return i;
             }
             else if (ce is ThroughFaceContactElement
                      &&
                      ((ThroughFaceContactElement)ce).SplitFacePositive.OtherVertex(
                          ((ThroughFaceContactElement)ce).SplitEdge) ==
                      ((CoincidentEdgeContactElement)current).EndVertex)
             {
                 connectingVertex = ce.StartVertex;
                 return i;
             }
         }
         connectingVertex = null;
         return -1;
     }
     for (int i = 0; i < contacts.Count; i++)
     {
         var ce = contacts[i];
         if ((ce is CoincidentEdgeContactElement &&
             current.SplitFacePositive.OtherVertex(((ThroughFaceContactElement)current).SplitEdge) ==
             ((CoincidentEdgeContactElement)ce).EndVertex)
         ||
         (!(ce is CoincidentEdgeContactElement) && ce.SplitFacePositive == current.SplitFaceNegative))
         {
             connectingVertex = ce.StartVertex;
             return i;
         }
     }
     connectingVertex = null;
     return -1;
 }
コード例 #5
0
ファイル: Slice.cs プロジェクト: mvelayati/TVGL
 private static List<TessellatedSolid> convertFaceListsToSolids(TessellatedSolid ts, List<List<PolygonalFace>> facesLists,
     List<Loop> loops, Boolean onPositiveSide, Flat plane)
 {
     List<TessellatedSolid> solids = new List<TessellatedSolid>();
     foreach (var facesList in facesLists)
     {
         // get a list of the vertex indices from the original solid
         var vertIndices = facesList.SelectMany(f => f.Vertices.Select(v => v.IndexInList))
             .Distinct().OrderBy(index => index).ToArray();
         var numVertices = vertIndices.Count();
         // get the set of connected loops for this list of faces. it could be one or it could be all
         var connectedLoops = loops.Where(loop =>
             (onPositiveSide && loop.Any(ce => facesList.Contains(ce.SplitFacePositive)))
             || (!onPositiveSide && loop.Any(ce => facesList.Contains(ce.SplitFaceNegative))))
             .ToList();
         // put the vertices from vertIndices in subSolidVertices, except those that are on the loop.
         // you'll need to copy those.
         var subSolidVertices = new Vertex[numVertices];
         var indicesToCopy = connectedLoops.SelectMany(loop => loop.Select(ce => ce.StartVertex.IndexInList))
             .OrderBy(index => index).ToArray();
         var numIndicesToCopy = indicesToCopy.GetLength(0);
         var newEdgeVertices = new Vertex[connectedLoops.Count][];
         for (int i = 0; i < connectedLoops.Count; i++)
             newEdgeVertices[i] = new Vertex[connectedLoops[i].Count];
         var copyIndex = 0;
         for (int i = 0; i < numVertices; i++)
         {
             Vertex vertexCopy;
             if (copyIndex < numIndicesToCopy && vertIndices[i] == indicesToCopy[copyIndex])
             {
                 var oldVertex = ts.Vertices[vertIndices[i]];
                 vertexCopy = oldVertex.Copy();
                 for (int j = 0; j < connectedLoops.Count; j++)
                 {
                     var k = connectedLoops[j].FindIndex(ce => ce.StartVertex == oldVertex);
                     newEdgeVertices[j][k] = vertexCopy;
                 }
                 foreach (var face in oldVertex.Faces.Where(face => facesList.Contains(face)))
                 {
                     face.Vertices.Remove(oldVertex);
                     face.Vertices.Add(vertexCopy);
                     vertexCopy.Faces.Add(face);
                 }
                 while (copyIndex < numIndicesToCopy && vertIndices[i] >= indicesToCopy[copyIndex])
                     copyIndex++;
             }
             else vertexCopy = ts.Vertices[vertIndices[i]];
             vertexCopy.IndexInList = i;
             subSolidVertices[i] = vertexCopy;
         }
         solids.Add(new TessellatedSolid(facesList, subSolidVertices, newEdgeVertices, onPositiveSide ? plane.Normal.multiply(-1) : plane.Normal,
             connectedLoops.Select(loop => loop.IsPositive).ToArray()));
     }
     return solids;
 }
コード例 #6
0
ファイル: Slice.cs プロジェクト: mvelayati/TVGL
 private static int FindNextContactElement(List<ContactElement> contacts, ContactElement current,
     out Vertex connectingVertex)
 {
     // there are six cases to handle: A=ThroughFace (abbreviated as face below), ThroughVertex (vertex), CoincidentEdge (edge)
     // current contact element --> next contact element
     // 1. vertex --> face
     // 2. edge --> edge
     // 3. edge --> face
     // 4. face --> face
     // 5. face --> vertex
     // 6. face --> edge
     if (current is ThroughVertexContactElement)
     {
         // from a ThroughVertex, it only make sense that you could go to ThroughFace
         for (int i = 0; i < contacts.Count; i++)
         {
             var ce = contacts[i];
             if (ce is ThroughFaceContactElement && ce.SplitFaceNegative == current.SplitFacePositive)
             {
                 connectingVertex = ce.StartVertex;
                 return i;
             }
         }
         connectingVertex = null;
         return -1;
     }
     else if (current is CoincidentEdgeContactElement)
     {
         // from a Coincident Edge, the valid options are another CoincidentEdge or ThroughFace.
         // It doesn't make sense that you could go to a ThroughVertex (redundant with this)
         for (int i = 0; i < contacts.Count; i++)
         {
             var ce = contacts[i];
             if ((ce is CoincidentEdgeContactElement &&
                  ((CoincidentEdgeContactElement)ce).StartVertex ==
                  ((CoincidentEdgeContactElement)current).EndVertex)
                 || (ce is ThroughFaceContactElement
                     &&
                     ((ThroughFaceContactElement)ce).SplitFaceNegative.OtherVertex(
                         ((ThroughFaceContactElement)ce).SplitEdge) ==
                     ((CoincidentEdgeContactElement)current).EndVertex))
             {
                 connectingVertex = ce.StartVertex;
                 return i;
             }
         }
         connectingVertex = null;
         return -1;
     }
     // finally from ThroughFace, you can go to any of the other three.
     for (int i = 0; i < contacts.Count; i++)
     {
         var ce = contacts[i];
         if ((ce is CoincidentEdgeContactElement &&
             current.SplitFacePositive.OtherVertex(((ThroughFaceContactElement)current).SplitEdge) ==
             ((CoincidentEdgeContactElement)ce).StartVertex)
         ||
         (!(ce is CoincidentEdgeContactElement) && ce.SplitFaceNegative == current.SplitFacePositive))
         {
             connectingVertex = ce.StartVertex;
             return i;
         }
     }
     connectingVertex = null;
     return -1;
 }
コード例 #7
0
ファイル: Point.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 /// Initializes a new instance of the <see cref="Point"/> class.
 /// </summary>
 /// <param name="vertex">The vertex.</param>
 /// <param name="x">The x.</param>
 /// <param name="y">The y.</param>
 public Point(Vertex vertex, double x, double y)
     : this(vertex, x, y, 0.0)
 {
 }
コード例 #8
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
        internal TessellatedSolid(List<PolygonalFace> facesList, Vertex[] subSolidVertices, Vertex[][] newEdgeVertices,
            double[] normal, Boolean[] loopIsPositive)
        {
            Faces = facesList.ToArray();
            Vertices = subSolidVertices;
            var numloops = newEdgeVertices.GetLength(0);
            var points2D = new Point[numloops][];
            for (int i = 0; i < numloops; i++)
                points2D[i] = MinimumEnclosure.Get2DProjectionPoints(newEdgeVertices[i], normal);
            List<PolygonalFace> patchFaces = TriangulatePolygon.Run(points2D.ToList<Point[]>(), loopIsPositive);

            //todo:
            //1. make faces from list of points
            //2. connect to existing.
            MakeEdges();
            CreateConvexHull();
            DefineBoundingBoxAndCenter();
            for (int i = 0; i < Faces.Length; i++)
            {
                var face = Faces[i];
                var centerX = face.Vertices.Average(v => v.X);
                var centerY = face.Vertices.Average(v => v.Y);
                var centerZ = face.Vertices.Average(v => v.Z);
                face.Center = new[] { centerX, centerY, centerZ };
            }
            ConnectConvexHullToObjects();
            DefineVolumeAndAreas();
            DefineFaceCurvature();
            DefineVertexCurvature();
        }
コード例 #9
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
 internal void AddVertex(Vertex newVertex)
 {
     var newVertices = new Vertex[NumberOfVertices + 1];
     for (int i = 0; i < NumberOfVertices; i++)
         newVertices[i] = Vertices[i];
     newVertices[NumberOfVertices] = newVertex;
     newVertex.IndexInList = NumberOfVertices;
     Vertices = newVertices;
     NumberOfVertices++;
 }
コード例 #10
0
ファイル: Point.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 /// Initializes a new instance of the <see cref="Point"/> class.
 /// </summary>
 /// <param name="v">The v.</param>
 public Point(Vertex v)
     : this(v, v.Position[0], v.Position[1], v.Position[2])
 {
 }
コード例 #11
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
 private void RemoveVertices(List<int> removeIndices)
 {
     var offset = 0;
     var numToRemove = removeIndices.Count;
     removeIndices.Sort();
     NumberOfVertices -= numToRemove;
     var newVertices = new Vertex[NumberOfVertices];
     for (int i = 0; i < NumberOfVertices; i++)
     {
         while (offset < numToRemove && (i + offset) == removeIndices[offset])
             offset++;
         var v = Vertices[i + offset];
         v.IndexInList = i;
         newVertices[i] = v;
     }
     Vertices = newVertices;
 }
コード例 #12
0
 internal ThroughVertexContactElement(Vertex onPlaneVertex, PolygonalFace negativeFace, PolygonalFace positiveFace)
 {
     StartVertex = onPlaneVertex;
     SplitFacePositive = positiveFace;
     SplitFaceNegative = negativeFace;
 }
コード例 #13
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
        private Edge[] MakeEdges(PolygonalFace[] localFaces, Vertex[] localVertices)
        {
            NumberOfEdges = 3 * NumberOfFaces / 2;
            var alreadyDefinedEdges = new Dictionary<int, Edge>();

            for (var i = 0; i < NumberOfFaces; i++)
            {
                var face = localFaces[i];
                var lastIndex = face.Vertices.Count - 1;
                for (var j = 0; j <= lastIndex; j++)
                {
                    var fromIndex = face.Vertices[j].IndexInList;
                    var toIndex = (j == lastIndex)
                        ? face.Vertices[0].IndexInList
                        : face.Vertices[j + 1].IndexInList;

                    if (fromIndex == toIndex) throw new Exception("edge to same vertices.");
                    var checksum = (fromIndex < toIndex)
                        ? fromIndex + (NumberOfVertices * toIndex)
                        : toIndex + (NumberOfVertices * fromIndex);
                    if (alreadyDefinedEdges.ContainsKey(checksum))
                    {
                        var edge = alreadyDefinedEdges[checksum];
                        edge.OtherFace = face;
                        face.Edges.Add(edge);
                    }
                    else
                    {
                        var edge = new Edge(localVertices[fromIndex], localVertices[toIndex], face, null, true, true);
                        alreadyDefinedEdges.Add(checksum, edge);
                    }
                }
            }
            var badEdges = new List<Edge>();
            foreach (var edge in alreadyDefinedEdges.Values)
                if (edge.OwnedFace == null || edge.OtherFace == null)
                {
                    badEdges.Add(edge);
                    edge.OwnedFace = edge.OtherFace = edge.OwnedFace ?? edge.OtherFace;
                    Debug.WriteLine("Edge found with only face (face normal = " +
                                    edge.OwnedFace.Normal.MakePrintString()
                                    + ", between vertices " + edge.From.Position.MakePrintString() + " & " +
                                    edge.To.Position.MakePrintString());
                }
            var localEdges = alreadyDefinedEdges.Values.ToArray();
            NumberOfEdges = localEdges.GetLength(0);
            return localEdges;
        }
コード例 #14
0
ファイル: MinimumEnclosure.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 /// Given a direction, dir, this function returns the maximum length along this direction
 /// for the provided vertices as well as the two vertices that represent the extremes.
 /// </summary>
 /// <param name="dir">The dir.</param>
 /// <param name="vertices">The vertices.</param>
 /// <param name="vLow">The v low.</param>
 /// <param name="vHigh">The v high.</param>
 /// <returns>System.Double.</returns>
 public static double GetLengthAndExtremeVertices(double[] dir, IList<Vertex> vertices, out Vertex vLow, out Vertex vHigh)
 {
     var dotProducts = new double[vertices.Count];
     var i = 0;
     foreach (var v in vertices)
         dotProducts[i++] = dir.dotProduct(v.Position);
     var min_d = dotProducts.Min();
     var max_d = dotProducts.Max();
     vLow = vertices[dotProducts.FindIndex(min_d)];
     vHigh = vertices[dotProducts.FindIndex(max_d)];
     return max_d - min_d;
 }
コード例 #15
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
 internal void RemoveVertex(int removeVIndex)
 {
     NumberOfVertices--;
     var newVertices = new Vertex[NumberOfVertices];
     for (int i = 0; i < removeVIndex; i++)
         newVertices[i] = Vertices[i];
     for (int i = removeVIndex; i < NumberOfVertices; i++)
     {
         var v = Vertices[i + 1];
         v.IndexInList--;
         newVertices[i] = v;
     }
     Vertices = newVertices;
 }
コード例 #16
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
 internal void RemoveVertex(Vertex removeVertex)
 {
     RemoveVertex(Vertices.FindIndex(removeVertex));
 }
コード例 #17
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
 internal void AddVertices(IList<Vertex> verticesToAdd)
 {
     var numToAdd = verticesToAdd.Count();
     var newVertices = new Vertex[NumberOfVertices + numToAdd];
     for (int i = 0; i < NumberOfVertices; i++)
         newVertices[i] = Vertices[i];
     for (int i = 0; i < numToAdd; i++)
     {
         var newVertex = verticesToAdd[i];
         newVertices[NumberOfVertices + i] = newVertex;
         newVertex.IndexInList = NumberOfVertices + i;
     }
     Vertices = newVertices;
     NumberOfVertices += numToAdd;
 }
コード例 #18
0
ファイル: Edge.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 ///     Others the vertex.
 /// </summary>
 /// <param name="v">The v.</param>
 /// <returns>Vertex.</returns>
 /// <exception cref="System.Exception">OtherVertex: Vertex thought to connect to edge, but it doesn't.</exception>
 public Vertex OtherVertex(Vertex v)
 {
     if (v == To) return From;
     if (v == From) return To;
     throw new Exception("OtherVertex: Vertex thought to connect to edge, but it doesn't.");
 }
コード例 #19
0
 internal static Boolean FindNegativeAndPositiveFaces(Flat plane, Vertex onPlaneVertex, double[] vertexDistancesToPlane, out PolygonalFace negativeFace, out PolygonalFace positiveFace)
 {
     negativeFace = null;
     positiveFace = null;
     foreach (var face in onPlaneVertex.Faces)
     {
         var otherEdge = face.OtherEdge(onPlaneVertex);
         var toDistance = vertexDistancesToPlane[otherEdge.To.IndexInList];
         var fromDistance = vertexDistancesToPlane[otherEdge.From.IndexInList];
         if ((toDistance > 0 && fromDistance < 0) || (toDistance < 0 && fromDistance > 0))
             if ((toDistance > 0) == (face == otherEdge.OwnedFace))
                 positiveFace = face;
             else negativeFace = face;
     }
     return (negativeFace != null && positiveFace != null);
 }
コード例 #20
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 ///     Makes the vertices.
 /// </summary>
 /// <param name="listOfVertices">The list of vertices.</param>
 private void MakeVertices(IList<double[]> listOfVertices)
 {
     NumberOfVertices = listOfVertices.Count;
     Vertices = new Vertex[NumberOfVertices];
     for (var i = 0; i < NumberOfVertices; i++)
         Vertices[i] = new Vertex(listOfVertices[i], i);
 }
コード例 #21
0
ファイル: TessellatedSolid.cs プロジェクト: mvelayati/TVGL
 /// <summary>
 ///     Copies this instance.
 /// </summary>
 /// <returns>TessellatedSolid.</returns>
 public TessellatedSolid Copy()
 {
     var copyOfFaces = new PolygonalFace[NumberOfFaces];
     for (var i = 0; i < NumberOfFaces; i++)
         copyOfFaces[i] = Faces[i].Copy();
     var copyOfVertices = new Vertex[NumberOfVertices];
     for (var i = 0; i < NumberOfVertices; i++)
         copyOfVertices[i] = Vertices[i].Copy();
     for (var fIndex = 0; fIndex < NumberOfFaces; fIndex++)
     {
         var thisFace = copyOfFaces[fIndex];
         var oldFace = Faces[fIndex];
         var vertexIndices = new List<int>();
         foreach (var oldVertex in oldFace.Vertices)
         {
             var vIndex = oldVertex.IndexInList;
             vertexIndices.Add(vIndex);
             var thisVertex = copyOfVertices[vIndex];
             thisFace.Vertices.Add(thisVertex);
             thisVertex.Faces.Add(thisFace);
         }
     }
     Edge[] copyOfEdges = MakeEdges(copyOfFaces, copyOfVertices);
     var copy = new TessellatedSolid
        {
        SurfaceArea = SurfaceArea,
        Center = (double[])Center.Clone(),
        Faces = copyOfFaces,
        Vertices = copyOfVertices,
        Edges = copyOfEdges,
        Name = Name,
        NumberOfFaces = NumberOfFaces,
        NumberOfVertices = NumberOfVertices,
        Volume = Volume,
        XMax = XMax,
        XMin = XMin,
        YMax = YMax,
        YMin = YMin,
        ZMax = ZMax,
        ZMin = ZMin
        };
     copy.CreateConvexHull();
     return copy;
 }