internal DrawPFoamConduit(PFoam foam) { this.conduit_foam = foam; var vPC = new PointCloud(foam.Vertices.Select(x => x.Point)); bbox = vPC.GetBoundingBox(false); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
/// <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); }