Beispiel #1
0
        internal DrawPFoamConduit(PFoam foam)
        {
            this.conduit_foam = foam;
            var vPC = new PointCloud(foam.Vertices.Select(x => x.Point));

            bbox = vPC.GetBoundingBox(false);
        }
Beispiel #2
0
        /// <summary>
        /// Getter method to load primal/dual from a geometry container from the Rhino Document

        /// </summary>
        /// <param name="primal">provided primal - need to check if it has data after the method ends</param>
        /// <param name="dual">provided primal - just like primal check if it has cells </param>
        public static IList <Guid> LoadPrimalDual(out PFoam primal, out PFoam dual, out ContainerType container, bool connect = true)
        {
            primal = new PFoam();
            dual   = new PFoam();

            container = ContainerType.Edge;

            GetObject getObj              = new GetObject();
            var       togGeoUpdate        = new OptionToggle(true, "no", "yes");
            var       togClearConstraints = new OptionToggle(false, "no", "yes");

            //var togOptionReplace = new OptionToggle(true, "Keep", "Replace");

            getObj.SetCommandPrompt("Pick the geometry container (group of lines, surfaces, polysurfaces or meshes)");


            getObj.AddOptionToggle("UpdateGeo", ref togGeoUpdate);
            getObj.AddOptionToggle("ClearConstraints", ref togClearConstraints);
            //getObj.AddOptionToggle("ReplaceGeo", ref togOptionReplace);
            getObj.GroupSelect    = true;
            getObj.GeometryFilter = Rhino.DocObjects.ObjectType.Brep | Rhino.DocObjects.ObjectType.Curve | Rhino.DocObjects.ObjectType.Mesh;

            while (true)
            {
                var r = getObj.GetMultiple(1, 0);
                if (r == GetResult.Cancel)
                {
                    return(new List <Guid>());
                }
                else if (r == GetResult.Object)
                {
                    break;
                }
            }

            var guids = getObj.Objects().Select(x => x.ObjectId).ToList();

            var geoObj = getObj.Objects().Select(x => x.Geometry());

            if (geoObj.All(x => x.ObjectType == Rhino.DocObjects.ObjectType.Brep))
            {
                var brepInput = geoObj.Cast <Brep>().ToList();

                if (brepInput.Any(x => x.Faces.Count > 1))
                {
                    container = ContainerType.CellBrep;
                }
                else
                {
                    container = ContainerType.FaceBrep;
                }

                primal = LoadData.LoadFromFaces(brepInput, out dual, togGeoUpdate.CurrentValue);
            }
            else if (geoObj.All(x => x.ObjectType == Rhino.DocObjects.ObjectType.Curve))
            {
                container = ContainerType.Edge;
                var curveGeos = geoObj.Cast <Curve>().ToList();
                primal = LoadData.LoadFromEdges(curveGeos, out dual, togGeoUpdate.CurrentValue);
            }

            else if (geoObj.All(x => x.ObjectType == Rhino.DocObjects.ObjectType.Mesh))
            {
                var meshGeos = geoObj.Cast <Mesh>().ToList();
                if (meshGeos.Any(x => x.Ngons.Count > 1 ||
                                 (x.Ngons.Count == 0 && x.Faces.Count > 1) ||
                                 (x.Ngons.Count == 1 && x.Faces.Count > x.Ngons[0].FaceCount)))
                {
                    container = ContainerType.CellMesh;
                }
                else
                {
                    container = ContainerType.FaceMesh;
                }



                primal = LoadData.LoadFromMeshes(meshGeos, out dual, togGeoUpdate.CurrentValue);
            }
            else
            {
                Rhino.RhinoApp.WriteLine("Mixed data detected!");
                return(new List <Guid>());
            }


            if (primal.Cells.Count < 1)
            {
                Rhino.RhinoApp.WriteLine("Error creating primal from provided data!");
                return(new List <Guid>());
            }

            if (connect && dual.Cells.Count > 1 && primal.Dual.Id == dual.Id)
            {
                Util.ConnectDuals(ref primal, ref dual);
            }


            if (togClearConstraints.CurrentValue)
            {
                foreach (var vert in primal.Vertices)
                {
                    vert.RestrictPosition = null;
                    vert.RestrictSupport  = null;
                    vert.SupportGuid      = Guid.Empty;
                }
                foreach (var edge in primal.Edges)
                {
                    edge.TargetLength = double.NaN;
                    edge.MaxLength    = double.MaxValue;
                    edge.MinLength    = double.Epsilon;
                }
                foreach (var face in primal.Faces)
                {
                    face.TargetArea = double.NaN;
                }
            }


            Rhino.RhinoDoc.ActiveDoc.Objects.UnselectAll();
            Rhino.RhinoDoc.ActiveDoc.Views.Redraw();
            return(guids);
        }
Beispiel #3
0
        /// <summary>
        /// Loads a structure from a set of breps and the attached serial string (JSON)
        /// If there is a dual present it links the dual and outputs it too
        /// </summary>
        /// <param name="edgeLines">The set of line curves with extra data in .UserDictionary</param>
        /// <param name="dual">The dual. If empty structure then no dual was found</param>
        /// <returns></returns>
        public static PFoam LoadFromCells(IList <Brep> cellBreps, out PFoam dual, bool updateGeometry = false)
        {
            dual = new PFoam();
            var primal = new PFoam();

            var vertLocations = new Dictionary <int, List <PFVertex> >();


            foreach (var cellBrep in cellBreps)
            {
                if (cellBrep.Faces.Count < 2)
                {
                    throw new PolyFrameworkException("LoadFromCells only works with PolySurfaces!");
                }

                foreach (var bVert in cellBrep.Vertices)
                {
                    if (bVert.UserDictionary.TryGetInteger("Id", out int vertId))
                    {
                        if (vertLocations.TryGetValue(vertId, out List <PFVertex> vertList))
                        {
                            vertList.Add(new PFVertex(vertId, bVert.Location));
                        }
                        else
                        {
                            vertLocations[vertId] = new List <PFVertex> {
                                new PFVertex(vertId, bVert.Location)
                            };
                        }
                    }
                }

                if (cellBrep.UserDictionary.TryGetString("Primal", out string primalString))
                {
                    primal = Util.DeserializeFoam(primalString);
                }
                if (cellBrep.UserDictionary.TryGetString("Dual", out string dualString))
                {
                    dual = Util.DeserializeFoam(dualString);
                }
            }

            if (primal.Cells.Count < 1)
            {
                throw new PolyFrameworkException("No serial data stored in the geometry or data has problems!");
            }

            if (updateGeometry)
            {
                foreach (var vertex in primal.Vertices)
                {
                    if (vertLocations.TryGetValue(vertex.Id, out List <PFVertex> vertPostions))
                    {
                        vertex.Point = PFVertex.AverageVertexes(vertPostions);
                    }
                }
            }

            foreach (var face in primal.Faces)
            {
                face.FaceMesh();
                face.ComputeCentroid();
                face.ComputeFaceNormal();
            }
            foreach (var cell in primal.Cells)
            {
                cell.ComputeCentroid();
            }
            primal.Centroid = PFVertex.AverageVertexes(primal.Vertices);


            if (dual.Cells.Count > 1)
            {
                //Util.ConnectDuals(ref primal, ref dual);

                foreach (var face in dual.Faces)
                {
                    face.FaceMesh();
                    face.ComputeCentroid();
                    face.ComputeFaceNormal();
                }
                foreach (var cell in dual.Cells)
                {
                    cell.ComputeCentroid();
                }
                dual.Centroid = PFVertex.AverageVertexes(dual.Vertices);
            }



            return(primal);
        }
Beispiel #4
0
        /// <summary>
        /// Loads a structure from a set of breps and the attached serial string (JSON)
        /// If there is a dual present it links the dual and outputs it too
        /// </summary>
        /// <param name="edgeLines">The set of line curves with extra data in .UserDictionary</param>
        /// <param name="dual">The dual. If empty structure then no dual was found</param>
        /// <returns></returns>
        public static PFoam LoadFromMeshes(IList <Mesh> meshes, out PFoam dual, bool updateGeometry = false)
        {
            dual = new PFoam();
            var primal = new PFoam();

            var vertLocations = new Dictionary <int, List <PFVertex> >();


            foreach (var mesh in meshes)
            {
                //if (faceBrep.Faces.Count > 1) throw new PolyFrameworkException("LoadFromFaces only works with individual faces!");
                if (mesh.UserDictionary.TryGetDictionary("VertexIds", out Rhino.Collections.ArchivableDictionary vertDict))
                {
                    var sortedVerts = vertDict.ToList().OrderBy(x => int.Parse(x.Key)).Select(y => new Tuple <int, int>(int.Parse(y.Key), (int)y.Value));
                    foreach (var indexId in sortedVerts)
                    {
                        if (vertLocations.TryGetValue(indexId.Item2, out List <PFVertex> vertList))
                        {
                            vertList.Add(new PFVertex(indexId.Item2, new Point3d(mesh.Vertices[indexId.Item1])));
                        }
                        else
                        {
                            vertLocations[indexId.Item2] = new List <PFVertex> {
                                new PFVertex(indexId.Item2, new Point3d(mesh.Vertices[indexId.Item1]))
                            };
                        }
                    }
                }



                if (mesh.UserDictionary.TryGetString("Primal", out string primalString))
                {
                    primal = Util.DeserializeFoam(primalString);
                }
                if (mesh.UserDictionary.TryGetString("Dual", out string dualString))
                {
                    dual = Util.DeserializeFoam(dualString);
                }
            }

            if (primal.Cells.Count < 1)
            {
                throw new PolyFrameworkException("No serial data stored in the geometry or data has problems!");
            }

            if (updateGeometry)
            {
                foreach (var vertex in primal.Vertices)
                {
                    if (vertLocations.TryGetValue(vertex.Id, out List <PFVertex> vertPostions))
                    {
                        vertex.Point = PFVertex.AverageVertexes(vertPostions);
                    }
                }
            }

            foreach (var face in primal.Faces)
            {
                face.FaceMesh();
                face.ComputeCentroid();
                face.ComputeFaceNormal();
            }
            foreach (var cell in primal.Cells)
            {
                cell.ComputeCentroid();
            }
            primal.Centroid = PFVertex.AverageVertexes(primal.Vertices);


            if (dual.Cells.Count > 1)
            {
                //Util.ConnectDuals(ref primal, ref dual);

                foreach (var face in dual.Faces)
                {
                    face.FaceMesh();
                    face.ComputeCentroid();
                    face.ComputeFaceNormal();
                }
                foreach (var cell in dual.Cells)
                {
                    cell.ComputeCentroid();
                }
                dual.Centroid = PFVertex.AverageVertexes(dual.Vertices);
            }



            return(primal);
        }
Beispiel #5
0
        /// <summary>
        /// Loads a structure from a set of lines and the attached serial string (JSON)
        /// If there is a dual present it links the dual and outputs it too
        /// </summary>
        /// <param name="edgeLines">The set of line curves with extra data in .UserDictionary</param>
        /// <param name="dual">The dual. If empty structure then no dual was found</param>
        /// <returns></returns>
        public static PFoam LoadFromEdges(IList <Curve> edgeLines, out PFoam dual, bool updateGeometry = false)
        {
            dual = new PFoam();
            var primal = new PFoam();

            var vertLocations = new Dictionary <int, List <PFVertex> >();


            foreach (var edgeLine in edgeLines)
            {
                if (edgeLine.UserDictionary.TryGetInteger("V0", out int v0))
                {
                    if (vertLocations.TryGetValue(v0, out List <PFVertex> vertList))
                    {
                        vertList.Add(new PFVertex(v0, edgeLine.PointAtStart));
                    }
                    else
                    {
                        vertLocations[v0] = new List <PFVertex> {
                            new PFVertex(v0, edgeLine.PointAtStart)
                        };
                    }
                }
                if (edgeLine.UserDictionary.TryGetInteger("V1", out int v1))
                {
                    if (vertLocations.TryGetValue(v1, out List <PFVertex> vertList))
                    {
                        vertList.Add(new PFVertex(v1, edgeLine.PointAtEnd));
                    }
                    else
                    {
                        vertLocations[v1] = new List <PFVertex> {
                            new PFVertex(v1, edgeLine.PointAtEnd)
                        };
                    }
                }
                if (edgeLine.UserDictionary.TryGetString("Primal", out string primalString))
                {
                    primal = Util.DeserializeFoam(primalString);
                }
                if (edgeLine.UserDictionary.TryGetString("Dual", out string dualString))
                {
                    dual = Util.DeserializeFoam(dualString);
                }
            }

            if (primal.Cells.Count < 1)
            {
                throw new PolyFrameworkException("No serial data stored in the geometry or data has problems!");
            }

            if (updateGeometry)
            {
                foreach (var vertex in primal.Vertices)
                {
                    if (vertLocations.TryGetValue(vertex.Id, out List <PFVertex> vertPostions))
                    {
                        vertex.Point = PFVertex.AverageVertexes(vertPostions);
                    }
                    if (vertex.Fixed) // update the fixed position for the vertex based on new position
                    {
                        vertex.RestrictSupport = new Point(vertex.Point);
                        //vertex.RestrictPosition = vertex.ConstrainPoint;
                    }
                }
            }

            foreach (var face in primal.Faces)
            {
                face.FaceMesh();
                face.ComputeCentroid();
                face.ComputeFaceNormal();
            }
            foreach (var cell in primal.Cells)
            {
                cell.ComputeCentroid();
            }
            primal.Centroid = PFVertex.AverageVertexes(primal.Vertices);


            if (dual.Cells.Count > 1)
            {
                //Util.ConnectDuals(ref primal, ref dual);

                foreach (var face in dual.Faces)
                {
                    face.FaceMesh();
                    face.ComputeCentroid();
                    face.ComputeFaceNormal();
                }
                foreach (var cell in dual.Cells)
                {
                    cell.ComputeCentroid();
                }
                dual.Centroid = PFVertex.AverageVertexes(dual.Vertices);
            }



            return(primal);
        }
Beispiel #6
0
        /// <summary>
        /// goes through all members of both foam objects and replaces dummy objects with
        /// real dual references from the other foam
        /// works only if the foam objects have the dummy duals set
        /// will throw exception if the two are not dual of each other
        /// </summary>
        /// <param name="primal">primal foam</param>
        /// <param name="dual">dual foam</param>
        public static void ConnectDuals(ref PFoam primal, ref PFoam dual)
        {
            if (primal.Dual.Id != dual.Id && dual.Dual.Id != primal.Id)
            {
                throw new PolyFrameworkException("The two foam objects are not dual of each other!");
            }
            // first save all sub-objects in dictionaries
            var primalVerts = primal.Vertices.ToDictionary(vert => vert.Id, vert => vert);
            var primalEdges = primal.Edges.ToDictionary(edge => edge.Id, edge => edge);
            var primalFaces = primal.Faces.ToDictionary(face => face.Id, face => face);
            var primalCells = primal.Cells.ToDictionary(cell => cell.Id, cell => cell);

            var dualVerts = dual.Vertices.ToDictionary(vert => vert.Id, vert => vert);
            var dualEdges = dual.Edges.ToDictionary(edge => edge.Id, edge => edge);
            var dualFaces = dual.Faces.ToDictionary(face => face.Id, face => face);
            var dualCells = dual.Cells.ToDictionary(cell => cell.Id, cell => cell);

            // go through each sub-object and reference its dual from the other foam
            // test for nulls

            // primal vertices - dual cells
            foreach (var vert in primal.Vertices)
            {
                vert.Dual = vert.Dual.Id != -1 ? dualCells[vert.Dual.Id] : null;
            }
            // dual vertices - primal cells
            foreach (var vert in dual.Vertices)
            {
                vert.Dual = vert.Dual.Id != -1 ? primalCells[vert.Dual.Id] : null;
            }
            // primal edges - dual faces
            foreach (var edge in primal.Edges)
            {
                if (edge.Dual != null)
                {
                    edge.Dual = edge.Dual.Id != 0 ? dualFaces[edge.Dual.Id] : null;
                }
            }
            // dual edges - primal faces
            foreach (var edge in dual.Edges)
            {
                if (edge.Dual != null)
                {
                    edge.Dual = edge.Dual.Id != 0 ? primalFaces[edge.Dual.Id] : null;
                }
            }
            // primal faces - dual edges
            foreach (var face in primal.Faces)
            {
                if (face.Dual != null)
                {
                    face.Dual = face.Dual.Id != 0 ? dualEdges[face.Dual.Id] : null;
                }
            }
            // dual faces - primal edges
            foreach (var face in dual.Faces)
            {
                if (face.Dual != null)
                {
                    face.Dual = face.Dual.Id != 0 ? primalEdges[face.Dual.Id] : null;
                }
            }
            // primal cells - dual vertices
            foreach (var cell in primal.Cells)
            {
                List <PFVertex> realDuals = new List <PFVertex>();
                foreach (var dVert in cell.Dual)
                {
                    realDuals.Add(dualVerts[dVert.Id]);
                }
                cell.Dual = new List <PFVertex>(realDuals);
            }
            // dual cells - primal vertices
            foreach (var cell in dual.Cells)
            {
                List <PFVertex> realDuals = new List <PFVertex>();
                foreach (var dVert in cell.Dual)
                {
                    realDuals.Add(primalVerts[dVert.Id]);
                }
                cell.Dual = new List <PFVertex>(realDuals);
            }

            primal.Dual = dual;
            dual.Dual   = primal;
        }
Beispiel #7
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);
        }