public static List <Circle> SortCircles(List <Circle> x) { if (x.Count == 1) { return(x); } List <Circle> sortedCircles = new List <Circle>() { x[0] }; for (int i = 1; i < x.Count; i++) { Plane plane = PlaneUtil.ProjectPlaneXPlaneToYPlane(sortedCircles[sortedCircles.Count - 1].Plane, x[i].Plane); Circle circle = new Circle(plane, x[i].Radius); sortedCircles.Add(circle); } return(sortedCircles); }
public static List <List <Polyline> > Miter(Mesh M, double D, double JointStep, double scale, GH_Structure <GH_Curve> additionalPlines) { if (additionalPlines.Branches.Count != 2) { return(null); } if (additionalPlines[0].Count != M.Ngons.Count || additionalPlines[1].Count != M.Ngons.Count) { return(null); } List <List <Polyline> > zzAll = new List <List <Polyline> >(); List <List <Line> > zzLinesAll = new List <List <Line> >(); List <List <Plane> > zzPlanesAll = new List <List <Plane> >(); Polyline[] plines = M.GetPolylines(); //Plane[] planes = M.GetNgonPlanes(); int[][] tv = M.GetNGonsTopoBoundaries(); int[][] fe = M.GetNGonFacesEdges(tv); HashSet <int> allE = M.GetAllNGonEdges(tv); int[][] ef = M.GetNgonsConnectedToNGonsEdges(allE, false); uint[][] finf = M.GetFacesInNGons(); int[] allEArray = allE.ToArray(); Dictionary <int, int> meNgonE = new Dictionary <int, int>(); for (int i = 0; i < allEArray.Length; i++) { meNgonE.Add(allEArray[i], i); } //Get planes Plane[] planes = new Plane[M.Ngons.Count]; for (int i = 0; i < additionalPlines[0].Count; i++) { Curve curve = additionalPlines[0][i].Value; curve.TryGetPolyline(out Polyline pline); planes[i] = pline.GetPlane(); } Line[] allEArrayLines = new Line[allEArray.Length]; Plane[] allEArrayBisector = new Plane[allEArray.Length]; for (int i = 0; i < M.Ngons.Count; i++) { zzAll.Add(new List <Polyline>()); zzPlanesAll.Add(new List <Plane>()); } //Get line segments and edge planes for (int i = 0; i < allEArray.Length; i++) { int me = allEArray[i]; int ne = meNgonE[me]; int[] edgeFaces = ef[ne]; if (edgeFaces.Length == 2) { //Rhino.RhinoApp.WriteLine(edgeFaces[0].ToString() + " " + edgeFaces[1].ToString()); int[] fe0 = fe[edgeFaces[0]]; int[] fe1 = fe[edgeFaces[1]]; int localID0 = Array.IndexOf(fe0, me); int localID1 = Array.IndexOf(fe1, me); //Get segments Curve curve = additionalPlines[0][edgeFaces[0]].Value; curve.TryGetPolyline(out Polyline pline0); curve = additionalPlines[1][edgeFaces[0]].Value; curve.TryGetPolyline(out Polyline pline1); Line l0 = PolylineUtil.tweenLine(pline0.SegmentAt(localID0), pline1.SegmentAt(localID0)); curve = additionalPlines[0][edgeFaces[1]].Value; curve.TryGetPolyline(out Polyline pline2); curve = additionalPlines[1][edgeFaces[1]].Value; curve.TryGetPolyline(out Polyline pline3); Line l1 = PolylineUtil.tweenLine(pline2.SegmentAt(localID1), pline3.SegmentAt(localID1)); //l0.Bake(); //l1.Bake(); l1.Flip(); allEArrayLines[ne] = PolylineUtil.tweenLine(l0, l1); Vector3d XAxis = allEArrayLines[ne].Direction; var pointsFit = new List <Point3d>(); pointsFit.AddRange(pline0.SegmentAt(localID0).ToP()); pointsFit.AddRange(pline1.SegmentAt(localID0).ToP()); pointsFit.AddRange(pline2.SegmentAt(localID1).ToP()); pointsFit.AddRange(pline3.SegmentAt(localID1).ToP()); Plane.FitPlaneToPoints(pointsFit, out Plane fitPlane); fitPlane.Rotate(Vector3d.VectorAngle(fitPlane.XAxis, XAxis, fitPlane), fitPlane.ZAxis); Point3d p0 = pline0.SegmentAt(localID0).PointAt(0.5); Point3d p1 = pline1.SegmentAt(localID0).PointAt(0.5); //Vector3d YAxis = (pline0.SegmentAt(localID0).PointAt(0.5) - pline1.SegmentAt(localID0).PointAt(0.5)) + (pline0.SegmentAt(localID1).PointAt(0.5) - pline1.SegmentAt(localID1).PointAt(0.5)); Plane plane = new Plane(allEArrayLines[ne].PointAt(0.5), XAxis, fitPlane.YAxis); allEArrayBisector[ne] = plane; //plane.Bake(1); //Create ZigZag Vector3d sideVec = Vector3d.CrossProduct(XAxis, plane.ZAxis); Rectangle3d rect = new Rectangle3d(new Plane(plane.Origin, plane.ZAxis, XAxis), new Interval(-D * 0.5, D * 0.5), new Interval(-allEArrayLines[ne].Length * 0.5, allEArrayLines[ne].Length * 0.5)); Polyline zigzag0 = ZigZagFromRectangle(rect, JointStep, scale); zzAll[edgeFaces[0]].Add(zigzag0); zzPlanesAll[edgeFaces[0]].Add(new Plane(rect.Plane)); //zigzag0.Bake(); //plane.Rotate(Math.PI,plane.ZAxis); rect = new Rectangle3d(new Plane(plane.Origin, -plane.ZAxis, -XAxis), new Interval(-D * 0.5, D * 0.5), new Interval(-allEArrayLines[ne].Length * 0.5, allEArrayLines[ne].Length * 0.5)); //rect.ToPolyline().Bake(); Polyline zigzag1 = ZigZagFromRectangle(rect, JointStep, scale); zzAll[edgeFaces[1]].Add(zigzag1); zzPlanesAll[edgeFaces[1]].Add(new Plane(rect.Plane)); //zzAll.Add(); //zigzag1.Bake(); } else { //int[] fe0 = fe[edgeFaces[0]]; //int localID0 = Array.IndexOf(fe0, me); ////Get segments //Curve curve = additionalPlines[0][edgeFaces[0]].Value; //curve.TryGetPolyline(out Polyline pline0); //curve = additionalPlines[1][edgeFaces[0]].Value; //curve.TryGetPolyline(out Polyline pline1); //Line l0 = PolylineUtil.tweenLine(pline0.SegmentAt(localID0), pline1.SegmentAt(localID0)); //allEArrayLines[ne] = l0; //Vector3d XAxis = allEArrayLines[ne].Direction; //Vector3d YAxis = (pline0.SegmentAt(localID0).PointAt(0.5) - pline1.SegmentAt(localID0).PointAt(0.5)) ; //Plane plane = new Plane(allEArrayLines[ne].PointAt(0.5), XAxis, YAxis); //allEArrayBisector[ne] = plane; ////plane.Bake(1); //Vector3d sideVec = Vector3d.CrossProduct(XAxis, plane.ZAxis); //Rectangle3d rect = new Rectangle3d(new Plane(plane.Origin, plane.ZAxis, XAxis ), new Interval(-D * 0.5, D * 0.5), new Interval(-allEArrayLines[ne].Length * 0.5, allEArrayLines[ne].Length * 0.5)); //Polyline zigzag = ZigZagFromRectangle(rect, JointStep, scale); ////zigzag.Bake(); } } ////Plane[][] bisePlanes; ////Plane[][] edgePlanes;//"ZY" ////M.GetEdgeAndBisectorPlanes(out bisePlanes, out edgePlanes); // for (int i = 0; i < plines.Length; i++) { // var zz = new List<Polyline>(); // var zzLines = new List<Line>(); // var zzPlanes = new List<Plane>(); // if (D != 0) { // Point3d center = M._Plane(i).Origin; // for (int j = 0; j < plines[i].Count - 1; j++) { // int e = fe[i][j]; // int[] faces = M.TopologyEdges.GetConnectedFaces(e); // int neiFace = faces[0]; // Vector3d normalDir = Vector3d.Zero; // if (faces.Length == 2) { // bool flag = false; // foreach (var ff in finf[i]) { // if (faces[0] == (int)ff) { // flag = true; // break; // } // } // neiFace = flag ? faces[1] : faces[0]; // normalDir = (M.FaceNormals[faces[1]] + M.FaceNormals[faces[0]]); // normalDir.Unitize(); // } else { // continue; // normalDir = (M.FaceNormals[faces[0]]); // normalDir.Unitize(); // } // Line l = plines[i].SegmentAt(j); // Vector3d dir = Vector3d.CrossProduct(M.FaceNormals[neiFace], l.Direction); // dir.Unitize(); // Point3d p0 = l.PointAt(0.5); // dir = -normalDir; // Vector3d sideVec = Vector3d.CrossProduct(l.Direction, normalDir); // Rectangle3d rect = new Rectangle3d(new Plane(l.Center(), sideVec, l.Direction), new Interval(-D * 0.5, D * 0.5), new Interval(-l.Length * 0.5, l.Length * 0.5)); // Polyline zigzag = ZigZagFromRectangle(rect, JointStep, scale); // //Project zigzag points to plane by direction of plane normal // for (int k = 0; k < zigzag.Count; k++) { // Line zzLine = new Line(zigzag[k], zigzag[k] + rect.Plane.ZAxis); // zigzag[k] = PlaneUtil.LinePlane(zzLine, planes[i]); // } // zzPlanes.Add(rect.Plane); // zz.Add(zigzag); // int sign = faces.Length == 2 ? -1 : -1; // //if (F) // // sign *= -1; // double distance = D * sign; // Polyline polyline = new Polyline() { l.From, l.To, l.To + dir * distance, l.From + dir * distance, l.From }; // }//for j // zzAll.Add(zz); // zzPlanesAll.Add(zzPlanes); // } //} //Add zigzag to panels //for (int i = 0; i < plines.Length; i++) { // plines[i].InsertPolyline(zzAll[i]); //} List <List <Polyline> > zzAllNew = new List <List <Polyline> >(); zzAllNew.Add(new List <Polyline>()); zzAllNew.Add(new List <Polyline>()); if (additionalPlines != null) { for (int i = 0; i < additionalPlines.Branches.Count; i++) { if (additionalPlines[i].Count != plines.Length) { continue; } for (int j = 0; j < additionalPlines[i].Count; j++) { //Cast to Polyline Curve curve = additionalPlines[i][j].Value; bool good = curve.TryGetPolyline(out Polyline aPline); if (good) { Plane plane = aPline.GetPlane(); for (int k = 0; k < zzAll[j].Count; k++) { Polyline zzPolyline = new Polyline(); for (int m = 0; m < zzAll[j][k].Count; m++) { Line zzLine = new Line(zzAll[j][k][m], zzAll[j][k][m] + zzPlanesAll[j][k].ZAxis); Point3d zzPoint = PlaneUtil.LinePlane(zzLine, plane); //zzPoint.Bake(); zzPolyline.Add(zzPoint); // } //zzPolyline.Bake(); aPline.InsertPolyline(zzPolyline); } //aPline.Bake(); //break; //additionalPlines[i][j] = new GH_Curve(new Polyline(aPline).ToNurbsCurve()); zzAllNew[i].Add(aPline); //zzAllNew[1].Add(aPline); } // } } //iterate of n-th layer of mesh. } //not null //zzAll.Clear(); return(zzAllNew); //return new List<List<Polyline>>() { additionalPlines[0], }; }
public static List <List <Polyline> > Miter(Mesh M, double D, double JointStep, double scale, ref GH_Structure <GH_Curve> additionalPlines) { List <List <Polyline> > zzAll = new List <List <Polyline> >(); List <List <Line> > zzLinesAll = new List <List <Line> >(); List <List <Plane> > zzPlanesAll = new List <List <Plane> >(); Polyline[] plines = M.GetPolylines(); Plane[] planes = M.GetNgonPlanes(); int[][] tv = M.GetNGonsTopoBoundaries(); int[][] fe = M.GetNGonFacesEdges(tv); HashSet <int> allE = M.GetAllNGonEdges(tv); int[][] ef = M.GetNgonsConnectedToNGonsEdges(allE, true); uint[][] finf = M.GetFacesInNGons(); int[] allEArray = allE.ToArray(); Dictionary <int, int> meNgonE = new Dictionary <int, int>(); for (int i = 0; i < allEArray.Length; i++) { meNgonE.Add(allEArray[i], i); } Plane[][] bisePlanes; Plane[][] edgePlanes;//"ZY" M.GetEdgeAndBisectorPlanes(out bisePlanes, out edgePlanes); for (int i = 0; i < plines.Length; i++) { var zz = new List <Polyline>(); var zzLines = new List <Line>(); var zzPlanes = new List <Plane>(); if (D != 0) { Point3d center = M._Plane(i).Origin; for (int j = 0; j < plines[i].Count - 1; j++) { int e = fe[i][j]; int[] faces = M.TopologyEdges.GetConnectedFaces(e); int neiFace = faces[0]; Vector3d normalDir = Vector3d.Zero; if (faces.Length == 2) { bool flag = false; foreach (var ff in finf[i]) { if (faces[0] == (int)ff) { flag = true; break; } } neiFace = flag ? faces[1] : faces[0]; normalDir = (M.FaceNormals[faces[1]] + M.FaceNormals[faces[0]]); normalDir.Unitize(); } else { continue; normalDir = (M.FaceNormals[faces[0]]); normalDir.Unitize(); } Line l = plines[i].SegmentAt(j); Vector3d dir = Vector3d.CrossProduct(M.FaceNormals[neiFace], l.Direction); dir.Unitize(); Point3d p0 = l.PointAt(0.5); dir = -normalDir; Vector3d sideVec = Vector3d.CrossProduct(l.Direction, normalDir); Rectangle3d rect = new Rectangle3d(new Plane(l.Center(), sideVec, l.Direction), new Interval(-D * 0.5, D * 0.5), new Interval(-l.Length * 0.5, l.Length * 0.5)); Polyline zigzag = ZigZagFromRectangle(rect, JointStep, scale); //Project zigzag points to plane by direction of plane normal for (int k = 0; k < zigzag.Count; k++) { Line zzLine = new Line(zigzag[k], zigzag[k] + rect.Plane.ZAxis); zigzag[k] = PlaneUtil.LinePlane(zzLine, planes[i]); } zzPlanes.Add(rect.Plane); zz.Add(zigzag); int sign = faces.Length == 2 ? -1 : -1; //if (F) // sign *= -1; double distance = D * sign; Polyline polyline = new Polyline() { l.From, l.To, l.To + dir * distance, l.From + dir * distance, l.From }; }//for j zzAll.Add(zz); zzPlanesAll.Add(zzPlanes); } } //Add zigzag to panels for (int i = 0; i < plines.Length; i++) { plines[i].InsertPolyline(zzAll[i]); } if (additionalPlines != null) { for (int i = 0; i < additionalPlines.Branches.Count; i++) { if (additionalPlines[i].Count != plines.Length) { continue; } for (int j = 0; j < additionalPlines[i].Count; j++) { //Cast to Polyline Curve curve = additionalPlines[i][j].Value; bool good = curve.TryGetPolyline(out Polyline aPline); if (good) { Plane plane = aPline.GetPlane(); for (int k = 0; k < zzAll[j].Count; k++) { Polyline zzPolyline = new Polyline(); for (int m = 0; m < zzAll[j][k].Count; m++) { Line zzLine = new Line(zzAll[j][k][m], zzAll[j][k][m] + zzPlanesAll[j][k].ZAxis); Point3d zzPoint = PlaneUtil.LinePlane(zzLine, plane); zzPolyline.Add(zzPoint); // } //zzPolyline.Bake(); aPline.InsertPolyline(zzPolyline); } //aPline.Bake(); //break; additionalPlines[i][j] = new GH_Curve(new Polyline(aPline).ToNurbsCurve()); } // } } //iterate of n-th layer of mesh. } //not null //zzAll.Clear(); //return zzAll; return(new List <List <Polyline> >() { plines.ToList() }); }
//Get ngon planes public static Plane[][] EPlanes(Mesh mesh, HashSet <int> allE, Dictionary <int, int> allEDict, Plane[] planesO, Plane[] planesOffset, int[][] eNgons, double jointWidth, double rotation, Line[] innerLines, int[][] ngonEdges, int[][] jointTypes, int[][] vertexNGons, int[] allV, double maxLength) { Line[] eLine = mesh.GetAllNGonEdgesLines(allE);//Plane origin points will be on those lines Plane[][] mp; //EDGE PLANES Plane[] edgePlanes = new Plane[allEDict.Count]; //Loop through all bisector edge faces and check if that edge belongs to one of edge faces //Dictionary<int, Plane> bisectors = GetBisectors(allE, planesO, eNgons); Dictionary <int, Plane> bisectors = GetCustomAveragePlanes(allE, planesO, eNgons, allV, mesh, ngonEdges, allEDict); for (int i = 0; i < allEDict.Count; i++) { Plane planeForXAxisRotation = (jointTypes[i][0] == 3) ? planesO[eNgons[i][0]] : planesO[eNgons[i][1]]; // Check which edges are connected with bisectors edgePlanes[i] = PlaneUtil.PlaneFromLinePlane(innerLines[i], planeForXAxisRotation); //Take edge vector and rotate it by male plane and in this way get edgePlane foreach (KeyValuePair <int, Plane> pair in bisectors) { //Test if edge is connected to bisector edge //Get connected ngons of bisector edge //Insertion direction: //1. Bisector plane 2Dof insertion freedom //To insert all edges correctly - insertion direction is limited to 1 Dof //2. It is a bisector of mesh faces connected to edge vertices, excluding faces connected to edges int[] bisectorNgons = eNgons[pair.Key]; bool flag1 = eNgons[i].Contains(bisectorNgons[0]); bool flag2 = eNgons[i].Contains(bisectorNgons[1]); if (flag1 || flag2) { Plane modifiedBisectorPlane = new Plane(edgePlanes[i].Origin, pair.Value.XAxis, pair.Value.YAxis); //Move bisector plane to the middle of edge Rhino.IndexPair ip = mesh.TopologyEdges.GetTopologyVertices(allE.ElementAt(i)); Rhino.IndexPair bip = mesh.TopologyEdges.GetTopologyVertices(allE.ElementAt(pair.Key)); //If edge is connected to bisector edge if ((ip.I == bip.I || ip.I == bip.J || ip.J == bip.I || ip.J == bip.J) && (i != pair.Key)) { edgePlanes[i] = PlaneUtil.AlignPlane(edgePlanes[i], modifiedBisectorPlane); //edgePlanes[i] = modifiedBisectorPlane; } else { planeForXAxisRotation = (jointTypes[i][0] == 3) ? planesO[eNgons[i][1]] : planesO[eNgons[i][0]]; // Check which edges are connected with bisectors edgePlanes[i] = PlaneUtil.PlaneFromLinePlane(innerLines[i], planeForXAxisRotation); //Take edge vector and rotate it by male plane and in this way get edgePlane //Get vertex ngons int[] CurrentEdgeVertexNgons_I = vertexNGons[Array.IndexOf(allV, ip.I)]; int[] CurrentEdgeVertexNgons_J = vertexNGons[Array.IndexOf(allV, ip.J)]; //Boolean difference between two int faceI = CurrentEdgeVertexNgons_I.Except(CurrentEdgeVertexNgons_J).First(); // int faceJ = CurrentEdgeVertexNgons_J.Except(CurrentEdgeVertexNgons_I).First(); Plane bi = planesO[faceI]; Plane mPlane = new Plane(edgePlanes[i].Origin, bi.XAxis, bi.YAxis); //edgePlanes[i].Rotate(Math.PI*0.5, edgePlanes[i].ZAxis); //edgePlanes[i] = new Plane(edgePlanes[i].Origin, edgePlanes[i].YAxis, edgePlanes[i].XAxis); edgePlanes[i] = PlaneUtil.AlignPlane(edgePlanes[i], mPlane); //edgePlanes[i].Rotate(Math.PI * 0.5, edgePlanes[i].ZAxis); //edgePlanes[i].Rotate(Math.PI * 0.5, edgePlanes[i].ZAxis); } break; } } } //OFFSET PLANES mp = new Plane[allEDict.Count][]; HashSet <int> edges = new HashSet <int>(); int[] e1 = ngonEdges[6]; int[] e2 = ngonEdges[7]; for (int i = 0; i < e1.Length; i++) { edges.Add(allEDict[e1[i]]); } for (int i = 0; i < e2.Length; i++) { edges.Add(allEDict[e2[i]]); } Rhino.RhinoApp.ClearCommandHistoryWindow(); foreach (var edge in edges) { GrasshopperUtil.Debug(edge); } for (int i = 0; i < allEDict.Count; i++) { mp[i] = new Plane[0]; if (jointTypes[i][0] != -1 && jointTypes[i][1] != -1) { //Direction Vector3d vec = Vector3d.Subtract((Vector3d)innerLines[i].From, (Vector3d)innerLines[i].To); vec.Unitize(); vec *= jointWidth; //Distance double dist = innerLines[i].Length - jointWidth; //Draw at least one joint int n = (int)(innerLines[i].Length * 0.5 / jointWidth) - 1; if (innerLines[i].Length > maxLength) { vec.Unitize(); double jointWidth2 = innerLines[i].Length / 10; vec *= jointWidth2; dist = innerLines[i].Length - jointWidth2; //Draw at least one joint n = (int)((innerLines[i].Length * 0.5 / jointWidth2) - 1); } n = (n <= 0) ? 0 : n; //Planes //Define center planes mp[i] = new Plane[n * 2 + 2]; if (dist > 0) { mp[i][n] = new Plane(edgePlanes[i]); mp[i][n].Translate(vec * 0.5); mp[i][n + 1] = new Plane(edgePlanes[i]); mp[i][n + 1].Translate(-vec * 0.5); } //Define rest of the planes for (int j = 1; j < n + 1; j++) { int t = n - j; mp[i][t] = new Plane(edgePlanes[i]); mp[i][t].Translate((j * vec) + (vec * 0.5)); mp[i][j + n + 1] = new Plane(edgePlanes[i]); mp[i][j + n + 1].Translate((j * -vec) - (vec * 0.5)); } if (dist < 0) { mp[i] = new Plane[0]; } //if (edges.Contains(i)) // mp[i] = new Plane[0]; } } //ROTATE PLANES RotatePlaneArray(mp, rotation); //OUTPUT return(mp); }
public static Dictionary <int, Plane> GetCustomAveragePlanes(HashSet <int> allE, Plane[] planesO, int[][] eNgons, int[] allV, Mesh mesh, int[][] ngonEdges, Dictionary <int, int> allEDict) { Dictionary <int, Plane> bisectors = new Dictionary <int, Plane>(); double minAngle = Math.PI / 18 * 3; double maxAngle = Math.PI / 18 * 15; for (int i = 0; i < allE.Count; i++) { int[] ngons = eNgons[i]; double angle = Vector3d.VectorAngle(planesO[ngons[0]].ZAxis, planesO[ngons[1]].ZAxis); if (angle < minAngle || angle > maxAngle) { //Get connected edges to current edges int[] edgesA = ngonEdges[ngons[0]]; int[] ngonPairA = new int[0]; int[] edgesB = ngonEdges[ngons[1]]; int[] ngonPairB = new int[0]; Rhino.IndexPair ip = mesh.TopologyEdges.GetTopologyVertices(allE.ElementAt(i)); for (int j = 0; j < edgesA.Length; j++) { Rhino.IndexPair tempIp = mesh.TopologyEdges.GetTopologyVertices(edgesA[j]); if (ip.I != tempIp.I && ip.J != tempIp.J && ip.J != tempIp.I && ip.I != tempIp.J) { ngonPairA = eNgons[allEDict[edgesA[j]]]; //GrasshopperUtil.Debug(ngonPairA[0]); //GrasshopperUtil.Debug(ngonPairA[1]); break; } } for (int j = 0; j < edgesB.Length; j++) { Rhino.IndexPair tempIp = mesh.TopologyEdges.GetTopologyVertices(edgesB[j]); if (ip.I != tempIp.I && ip.J != tempIp.J && ip.J != tempIp.I && ip.I != tempIp.J) { ngonPairB = eNgons[allEDict[edgesB[j]]]; //GrasshopperUtil.Debug(ngonPairB[0]); //GrasshopperUtil.Debug(ngonPairB[1]); break; } } int faceA = ngonPairB.Except(ngons).First(); int faceB = ngonPairA.Except(ngons).First(); Plane ptemp = planesO[faceA]; ptemp.Flip(); Plane bisector = PlaneUtil.AveragePlane(new Plane[] { ptemp, planesO[faceB] });; bisectors.Add(i, bisector); } } return(bisectors); }