예제 #1
0
        /// <summary>
        /// Creates the pair for the face
        /// Reverse the edge list and replace all edges with their pair
        /// Reverse vertex list.
        /// Add pair face to the edges and to the vertexes
        /// </summary>
        public void CreatePair()
        {
            PFFace pair = new PFFace(-Id)
            {
                Vertices = this.Vertices.Reverse().ToList()
            };

            foreach (var vert in pair.Vertices)
            {
                vert.Faces.Add(pair);
            }
            pair.Edges = this.Edges.Select(x => x.Pair).Reverse().ToList();
            //foreach (var edge in pair.Edges) edge.Faces.Add(pair); // this needs to be done separately after
            if (Normal != Vector3d.Unset)
            {
                pair.Normal = -Normal;
            }
            if (Centroid != Point3d.Unset)
            {
                pair.Centroid = Centroid;
            }
            //pair.FMesh = this.FMesh.DuplicateMesh();

            //pair.FMesh?.Flip(true, true, true);
            pair.Pair = this;

            Pair = pair;
        }
예제 #2
0
        /// <summary>
        /// Intersects an offset edge with another edge from the same face
        /// The second edge is at the end of the point
        /// </summary>
        /// <param name="topoLink"></param>
        /// <param name="position"></param>
        /// <param name="inFace"></param>
        /// <returns></returns>
        internal Point3d OffsetIntersection(PFVertex topoLink, PfoamRef coresp, PFFace inFace, out PFVertex otherVert, out PFEdge capEdge)
        {
            // test if position is in the inFace
            // intersect an edge with another edge - edges are part of the same face plane
            //-----------------------------------------------------------
            // for each edge test to see if coresp object contains an updated line for the edge
            //-----------------------------------------------------------
            // there will be an line/line intersection
            // if other point has more than 4 connections some connections will require type 1 calculations
            Point3d position = coresp.Vertices[topoLink].Position;

            otherVert = Vertices.Single(x => x != topoLink);
            var edgeDirection = otherVert.Point - topoLink.Point;
            var offsetLine    = new Line(position, position + edgeDirection);

            capEdge = otherVert.Edges.Single(x => inFace.Edges.Contains(x));
            var otherLine    = coresp.Edges[capEdge].Line;
            var intersection = Rhino.Geometry.Intersect.Intersection.LineLine(offsetLine, otherLine, out double a, out double b);

            return(offsetLine.PointAt(a));
        }
예제 #3
0
        /// <summary>
        /// This deserializes a whole foam object from a Json string.
        /// Since it only looks at a singular object the dual cannot be deserialized here.
        /// Instead placeholder object will be used in the properties for the dual.
        ///
        /// </summary>
        /// <param name="jsonFoam"></param>
        /// <returns></returns>
        public static PFoam DeserializeFoam(string jsonFoam)
        {
            if (jsonFoam == "")
            {
                return(new PFoam());
            }
            // get the foam dict
            JavaScriptSerializer json = new JavaScriptSerializer();

            json.MaxJsonLength = 2147483647;

            var foamPropDict = json.Deserialize <Dictionary <string, object> >(jsonFoam);
            // create the foam and add its ID
            PFoam foam = new PFoam()
            {
                Id = (string)foamPropDict["Id"]
            };


            // extract the vertices dictionary and partially extract the vertices into the foam
            // create dicts for all properties that cannot be deserialized directly into the object.
            // also a new dict (Id, vertex)
            var vertObjDict = foamPropDict["Vertices"] as Dictionary <string, object>;
            var vertDict    = new Dictionary <int, PFVertex>();
            var vertEdgesId = new Dictionary <PFVertex, List <int> >();
            var vertFacesId = new Dictionary <PFVertex, List <int> >();
            var vertCellsId = new Dictionary <PFVertex, List <int> >();

            // since there is no real object from another foam to deserialize as dual
            // a place holder object is to be replaced as soon as the dual is available
            // var vertDualId = new Dictionary<PFVertex, int>();
            foreach (var vertKeyVal in vertObjDict)
            {
                var vertPropDict = vertKeyVal.Value as Dictionary <string, object>;

                PFVertex vert = new PFVertex();
                vert.Id = (int)vertPropDict["Id"];
                //Dictionary<string, double> coordList = vertPropDict["Point"] as Dictionary<string, double>;
                vert.Point    = PointFromDict(vertPropDict["Point"] as Dictionary <string, object>);
                vert.External = (bool)vertPropDict["External"];

                // this will make new versions compatible with older data json strings
                if (vertPropDict.ContainsKey("SupportGuid"))
                {
                    vert.SupportGuid   = Guid.Parse(vertPropDict["SupportGuid"] as string); // this will throw an exception if there is no guid
                    vert.InfluenceCoef = Convert.ToDouble(vertPropDict["InfluenceCoef"]);   // idem
                    vert.Fixed         = (bool)vertPropDict["Fixed"];                       // idem
                    vert.OnGeo         = (bool)vertPropDict["OnGeo"];
                    if (vert.SupportGuid != Guid.Empty)                                     // now try and find the object in the document
                    {
                        var restrGeo = Rhino.RhinoDoc.ActiveDoc.Objects.FindId(vert.SupportGuid);
                        if (restrGeo != null)
                        {
                            foam.SetVertexConstraints(new List <PFVertex> {
                                vert
                            }, restrGeo, vert.InfluenceCoef, vert.OnGeo);
                        }
                    }
                    if (vert.Fixed)
                    {
                        foam.SetVertexConstraints(new List <PFVertex> {
                            vert
                        }, new Point(vert.Point), 100, vert.OnGeo);
                        // this needs to be update after the offset part... based on the geometry
                    }
                }



                vertEdgesId[vert] = (vertPropDict["Edges"] as ArrayList).Cast <int>().ToList();
                vertFacesId[vert] = (vertPropDict["Faces"] as ArrayList).Cast <int>().ToList();
                vertCellsId[vert] = (vertPropDict["Cells"] as ArrayList).Cast <int>().ToList();
                vert.Dual         = new PFCell((int)vertPropDict["Dual"]); // dummy cell for dual
                //vertDualId[vert] = (int)vertPropDict["Dual"];
                foam.Vertices.Add(vert);
                vertDict.Add(vert.Id, vert);
            }


            // extract the edges from the dictionary and put the vertices in the edges.
            // after also put the pairs in the edges
            // create dictionaries for all properties not immediately fillable
            var edgeObjDict   = foamPropDict["Edges"] as Dictionary <string, object>;
            var edgeDict      = new Dictionary <int, PFEdge>();
            var edgePair      = new Dictionary <PFEdge, int>();
            var edgeFaces     = new Dictionary <PFEdge, List <int> >();
            var edgeFaceAngle = new Dictionary <PFEdge, List <double> >();
            var edgeDual      = new Dictionary <PFEdge, int>();

            foreach (var edgeKeyVal in edgeObjDict)
            {
                var    edgePropDict = edgeKeyVal.Value as Dictionary <string, object>;
                PFEdge edge         = new PFEdge(Int32.Parse(edgeKeyVal.Key));
                var    edgeVertsIds = (edgePropDict["Vertices"] as ArrayList).Cast <int>();
                foreach (int vertId in edgeVertsIds)
                {
                    edge.Vertices.Add(vertDict[vertId]); // add the vertex in the edge
                }
                //edgeDict[edge.Id] = edge;
                edge.External  = (bool)edgePropDict["External"];
                edge.Deviation = Convert.ToDouble(edgePropDict["Deviation"]);

                // this will make new versions compatible with older data json strings
                if (edgePropDict.ContainsKey("TargetLength"))
                {
                    edge.TargetLength  = Convert.ToDouble(edgePropDict["TargetLength"]);
                    edge.MinLength     = Convert.ToDouble(edgePropDict["MinLength"]);
                    edge.MaxLength     = Convert.ToDouble(edgePropDict["MaxLength"]);
                    edge.InfluenceCoef = Convert.ToDouble(edgePropDict["InfluenceCoef"]);
                }


                // put all properties that can't be filled right now in their dictionaries
                edgePair[edge]      = (int)edgePropDict["Pair"]; // for keeping score of the pair easier
                edgeFaces[edge]     = (edgePropDict["Faces"] as ArrayList).Cast <int>().ToList();
                edgeFaceAngle[edge] = (edgePropDict["FaceAngle"] as ArrayList).ToArray().Select(x => Convert.ToDouble(x)).ToList();
                edge.Dual           = new PFFace((int)edgePropDict["Dual"]); // dummy face for dual just placeholder
                // add edge to foam and edgeDict;
                foam.Edges.Add(edge);
                edgeDict.Add(edge.Id, edge);
            }
            // now that all the edges have been extracted we can populate edge.Pair
            foreach (var edge in foam.Edges)
            {
                edge.Pair = edgeDict[edgePair[edge]];
            }

            // extract the faces from the dictionary

            var faceObjDict = foamPropDict["Faces"] as Dictionary <string, object>;
            var faceDict    = new Dictionary <int, PFFace>();
            var faceCell    = new Dictionary <PFFace, int>();
            var facePair    = new Dictionary <PFFace, int>();

            foreach (var faceKeyVal in faceObjDict)
            {
                var    facePropDict = faceKeyVal.Value as Dictionary <string, object>;
                PFFace face         = new PFFace(Int32.Parse(faceKeyVal.Key));
                var    faceVertsIds = (facePropDict["Vertices"] as ArrayList).Cast <int>().ToList();
                foreach (var vertId in faceVertsIds)
                {
                    face.Vertices.Add(vertDict[vertId]);
                }
                var faceEdgesIds = (facePropDict["Edges"] as ArrayList).Cast <int>().ToList();
                face.Edges     = faceEdgesIds.Select(x => edgeDict[x]).ToList();
                faceCell[face] = (int)facePropDict["Cell"];
                facePair[face] = (int)facePropDict["Pair"];
                face.Normal    = VectorFromDict(facePropDict["Normal"] as Dictionary <string, object>);
                face.Centroid  = PointFromDict(facePropDict["Centroid"] as Dictionary <string, object>);
                face.Dual      = new PFEdge((int)facePropDict["Dual"]); // create a dummy edge as dual - replace later
                face.External  = (bool)facePropDict["External"];
                face.Area      = Convert.ToDouble(facePropDict["Area"]);

                if (facePropDict.ContainsKey("TargetArea"))
                {
                    face.TargetArea    = Convert.ToDouble(facePropDict["TargetArea"]);
                    face.InfluenceCoef = Convert.ToDouble(facePropDict["InfluenceCoef"]);
                }


                // add face to foam.faces and faceDict
                foam.Faces.Add(face);
                faceDict.Add(face.Id, face);
            }
            foreach (var face in foam.Faces)
            {
                face.Pair = faceDict[facePair[face]];
            }

            // extract cells from the dictionary
            var cellObjDict = foamPropDict["Cells"] as Dictionary <string, object>;
            var cellDict    = new Dictionary <int, PFCell>();

            foreach (var cellKeyVal in cellObjDict)
            {
                var    cellPropDict = cellKeyVal.Value as Dictionary <string, object>;
                PFCell cell         = new PFCell(Int32.Parse(cellKeyVal.Key));
                var    cellVertsIds = (cellPropDict["Vertices"] as ArrayList).Cast <int>();
                cell.Vertices = cellVertsIds.Select(x => vertDict[x]).ToList();
                var cellEdgesIds = (cellPropDict["Edges"] as ArrayList).Cast <int>();
                cell.Edges = cellEdgesIds.Select(x => edgeDict[x]).ToList();
                var cellFacesIds = (cellPropDict["Faces"] as ArrayList).Cast <int>();
                cell.Faces    = cellFacesIds.Select(x => faceDict[x]).ToList();
                cell.Centroid = PointFromDict(cellPropDict["Centroid"] as Dictionary <string, object>);
                cell.Dual     = (cellPropDict["Dual"] as ArrayList).Cast <int>().Select(x => new PFVertex(x, Point3d.Unset)).ToList(); // list of dummy points to be changed later
                cell.Exterior = (bool)cellPropDict["Exterior"];
                // add cell to foam.cells and cellDict
                foam.Cells.Add(cell);
                cellDict.Add(cell.Id, cell);
            }

            //populate properties of vertices
            foreach (var vert in foam.Vertices)
            {
                vert.Edges = vertEdgesId[vert].Select(x => edgeDict[x]).ToList();
                vert.Faces = vertFacesId[vert].Select(x => faceDict[x]).ToList();
                vert.Cells = vertCellsId[vert].Select(x => cellDict[x]).ToList();
            }
            //populate properties of edges
            foreach (var edge in foam.Edges)
            {
                edge.Faces     = edgeFaces[edge].Select(x => faceDict[x]).ToList();
                edge.FaceAngle = edgeFaceAngle[edge];
            }
            // populate the properties of faces
            foreach (var face in foam.Faces)
            {
                face.Cell = cellDict[faceCell[face]];
            }

            // now deserialize all other properties
            foam.ExtVetices = (foamPropDict["ExtVertices"] as ArrayList).Cast <int>().Select(x => vertDict[x]).ToList();
            foam.ExtEdges   = (foamPropDict["ExtEdges"] as ArrayList).Cast <int>().Select(x => edgeDict[x]).ToList();
            foam.ExtFaces   = (foamPropDict["ExtFaces"] as ArrayList).Cast <int>().Select(x => faceDict[x]).ToList();
            foam.Centroid   = PointFromDict(foamPropDict["Centroid"] as Dictionary <string, object>);
            foam.Dual       = new PFoam() // this is a dummy dual just a placeholder with Id
            {
                Id = foamPropDict["Dual"] as string
            };
            foam.MaxDeviation = Convert.ToDouble(foamPropDict["MaxDeviation"]);

            // put also the edges in the vertices - use the vertObjDict for that


            // populate the edges and vertices in the faces


            return(foam);
        }
예제 #4
0
        /// <summary>
        /// Finds the intersecting face and the resulting point for an offset edge
        /// Based on a point where the edge will be. Edge stays parallel to itself.
        /// </summary>
        /// <param name="topoLink">The moved vertex from the edge</param>
        /// <param name="position">New position for the moved edge</param>
        /// <param name="capFace">The face intersected with the offset. </param>
        /// <returns>The point of intersection</returns>
        internal Point3d OffsetIntersection(PFVertex topoLink, PfoamRef coresp, out PFVertex otherVert, out PFFace capFace)
        {
            Point3d position = coresp.Vertices[topoLink].Position;

            // for this I need to build overloads to see for special cases - when starting point is in face, or in edge
            otherVert = Vertices.Single(x => x != topoLink);
            var edgeDirection = otherVert.Point - topoLink.Point;

            edgeDirection.Unitize();
            // find all the unique faces of the other point to intersect with
            // get plane for face
            // find intersection closest to position -> get that face (use normal to find it and its cell)
            //-----------------------------------------------------------
            // for each face test to see if coresp object contains an updated plane for the face
            //-----------------------------------------------------------
            // this is the otherPosition - I should output also the point and the corresponding face (cell)
            // if some faces(or their pair) are part of open cells exclude those faces from the intersections
            var edgeFaces = new HashSet <PFFace>(Faces);

            edgeFaces.UnionWith(Pair.Faces);
            var otherVertFaces = new HashSet <PFFace>(otherVert.Faces);

            var edgeCapFaces = otherVertFaces.Except(edgeFaces);

            var facingCapFaces = edgeFaces.Where(x => !x.External && Dot(x.Normal, edgeDirection) > 0).ToList();

            if (edgeCapFaces.Count() < 1)
            {
                capFace = null;
                return(position + edgeDirection * GetLength());
            }
            var offsetLine = new Line(position, position + edgeDirection);

            // now intersect line with all face planes
            double minPara      = double.MaxValue;
            int    minParaIndex = 0;

            for (int i = 0; i < facingCapFaces.Count(); i++)
            {
                var facePlane = coresp.Faces[facingCapFaces[i]].Plane;
                if (Rhino.Geometry.Intersect.Intersection.LinePlane(offsetLine, facePlane, out double param))
                {
                    if (param < minPara)
                    {
                        minPara      = param;
                        minParaIndex = i;
                    }
                }
            }

            capFace = facingCapFaces[minParaIndex];

            return(offsetLine.PointAt(minPara));
        }