/// <summary> /// Finds the cell a point is in relative to an edge /// The cell is part of the list of cells the edge is connected to. /// </summary> /// <param name="position">new vertex position</param> /// <returns>the cell the point is in</returns> public PFCell PointInCell(Point3d position) { // get all faces containing the edge // create dictionary with face normals pairs for each cell // see if vector from vert to point has the same direction as all the normals of those faces // if yes break var cellDihedrals = new Dictionary <PFCell, HashSet <Vector3d> >(); //new Dictionary<PFCell, HashSet<Vector3d>>(); foreach (var face in Faces) { if (cellDihedrals.TryGetValue(face.Cell, out HashSet <Vector3d> dihedral)) { dihedral.Add(face.Normal); } else { cellDihedrals[face.Cell] = new HashSet <Vector3d> { face.Normal }; } } PFCell result = new PFCell(); foreach (var keyValue in cellDihedrals) { if (Util.InsideHedra(Vertices[0].Point, position, keyValue.Value.ToList())) { result = keyValue.Key; break; } } return(result); }
/// <summary> /// Finds the cell some vertex moved into. /// The cell is part of the list of cells the vertex is connected to. /// </summary> /// <param name="position">new vertex position</param> /// <returns>the cell the vertex moves into</returns> public PFCell PointInCell(Point3d position) { // get all cells containing the vert // get all faces from cell containing the vert // see if vector from vert to point has the same direction as all the normals of those faces // if yes break if (Cells.Count == 0) { PopulateVertexCells(); } var cellTrihedrals = Cells.ToDictionary(cell => cell, cell => new HashSet <Vector3d>()); //new Dictionary<PFCell, HashSet<Vector3d>>(); foreach (var face in Faces) { cellTrihedrals[face.Cell].Add(face.Normal); } PFCell result = new PFCell(); foreach (var keyValue in cellTrihedrals) { if (!keyValue.Key.Exterior) { if (Util.InsideHedra(Point, position, keyValue.Value.ToList())) { result = keyValue.Key; break; } } } return(result); }
/// <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); }