//weighted random populate point with attractors //reference Junichiro Horikawa on Github Point3dList Populate(Brep brep, double n, int ite, List <Point3d> attractors, double attractor_r, double attractor_strength) { var points = new Point3dList(); int num = Convert.ToInt32(n); if (brep != null) { var attracts = new Point3dList(attractors); var rnd = new Random(); var bbox = brep.GetBoundingBox(true); attractor_strength = (-1) * attractor_strength; for (int i = 0; i < num; i++) { if (points.Count == 0) { var rndpt = CreateRandomPoint(rnd, brep, bbox); points.Add(rndpt); } else { double fdist = -1; Point3d fpt = new Point3d(); for (int t = 0; t < Math.Max(Math.Min(ite, i), 10); t++) { var nrndpt = CreateRandomPoint(rnd, brep, bbox); var nindex = points.ClosestIndex(nrndpt); var npts = points[nindex]; var ndist = npts.DistanceTo(nrndpt); if (attractor_strength != 0) { var nattractid = attracts.ClosestIndex(nrndpt); var nattarctpts = attracts[nattractid]; var mindist = attractor_r; var pow = attractor_strength; var nattractdist = Math.Pow(Remap(Math.Min(nattarctpts.DistanceTo(nrndpt), mindist), 0, mindist, 0, 1.0), pow); ndist *= nattractdist; } if (fdist < ndist) { fdist = ndist; fpt = nrndpt; } } points.Add(fpt); } } } return(points); }
public static void TestPolygonSelect() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; //声明一个Point3d类列表对象,用于存储多段线的顶点 Point3dList pts = new Point3dList(); //提示用户选择多段线 PromptEntityResult per = ed.GetEntity("请选择多段线"); if (per.Status != PromptStatus.OK) { return; //选择错误,返回 } using (Transaction trans = doc.TransactionManager.StartTransaction()) { //转换为Polyline对象 Polyline pline = trans.GetObject(per.ObjectId, OpenMode.ForRead) as Polyline; if (pline != null) { //遍历所选多段线的顶点并添加到Point3d类列表 for (int i = 0; i < pline.NumberOfVertices; i++) { Point3d point = pline.GetPoint3dAt(i); pts.Add(point); } //窗口选择,仅选择完全位于多边形区域中的对象 PromptSelectionResult psr = ed.SelectWindowPolygon(pts); if (psr.Status == PromptStatus.OK) { Application.ShowAlertDialog("选择集中实体的数量:" + psr.Value.Count.ToString()); } } trans.Commit(); } }
/// <summary> /// This function selects points /// </summary> /// <param name="message"></param> /// <param name="pointer"></param> public static void XSelectPoints(string message, out Point3dList pointer) { // variables are: // string message // out Point3dList points - the out won't be recognized unless you have Rhino.Collections and the 'out parameters // have to be filled in the function. // don't need a doc because we won't write anything to the document table, only reading. pointer = new Point3dList(); var go = new GetObject(); go.GeometryFilter = Rhino.DocObjects.ObjectType.Point; go.SetCommandPrompt(message); go.GetMultiple(1, 0); if (go.CommandResult() != Result.Success) { return; } for (var i = 0; i < go.ObjectCount; i++) { var point = go.Object(i).Point(); if (null != point) { pointer.Add(point.Location); } } }
public froGHRTree(List <Point3d> points) { Points = new Point3dList(); Source = EnumRTreeType.Points; Tree = new RTree(); for (int i = 0; i < points.Count; i++) { Points.Add(points[i]); Tree.Insert(points[i], i); } }
protected Polyline generateFingerJoint(Line jointLine, double thickness) { Point3d currPoint = new Point3d(jointLine.FromX, jointLine.FromY, 0); Point3dList points = new Point3dList(); points.Add(currPoint); double xIncr, yIncr; yIncr = thickness; xIncr = thickness / 2; // An even finger count means the finger will be drawn right of the // center line int fingerCount = 0; int fingerDirection = -1; // Loop invariant: incrementing and placing current point will always // result in a point before the stoppingY while (currPoint.Y + yIncr <= jointLine.ToY) { // Multiplier for right finger on even, vice versa for odd fingerDirection = fingerCount % 2 == 0 ? 1 : -1; currPoint += new Vector3d(xIncr * fingerDirection, 0, 0); points.Add(currPoint); currPoint += new Vector3d(0, yIncr, 0); points.Add(currPoint); currPoint += new Vector3d(-xIncr * fingerDirection, 0, 0); points.Add(currPoint); fingerCount += 1; } // Finish the last truncated finger if necessary if (currPoint.Y < jointLine.ToY) { fingerDirection = fingerCount % 2 == 0 ? 1 : -1; currPoint += new Vector3d(xIncr * fingerDirection, 0, 0); points.Add(currPoint); currPoint += new Vector3d(0, jointLine.ToY - currPoint.Y, 0); points.Add(currPoint); currPoint += new Vector3d(-xIncr * fingerDirection, 0, 0); points.Add(currPoint); } return(new Polyline(points)); }
/// <summary> /// Gets all Greville (Edit) points for this curve. /// </summary> public Point3dList GrevillePoints() { double[] gr_ab = GrevilleParameters(); if (gr_ab == null) { return(null); } Point3dList gr_pts = new Point3dList(gr_ab.Length); foreach (double t in gr_ab) { gr_pts.Add(PointAt(t)); } return(gr_pts); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { Random r = new Random(13); var plcnt = 1000000; var edge = 10; GetNumber gn = new GetNumber(); gn.SetCommandPrompt("How many pointsies"); gn.SetDefaultInteger(plcnt); gn.SetUpperLimit(500000001, true); gn.SetLowerLimit(1, true); gn.AcceptNothing(true); var gnrc = gn.Get(); if (gnrc == GetResult.Nothing || gnrc == GetResult.Number) { var nr = (int)gn.Number(); if (nr > 500000000) { RhinoApp.WriteLine("More than 500.000.000 points"); return(Result.Cancel); } pc = new PointCloud(); Point3dList p3dlist = new Point3dList(nr); List <System.Drawing.Color> collist = new List <System.Drawing.Color>(nr); for (int i = 0; i < nr; i++) { var d = (double)i; p3dlist.Add(new Point3d(r.NextDouble() * edge, r.NextDouble() * edge, r.NextDouble() * edge)); collist.Add(System.Drawing.Color.FromArgb(r.Next(0, 255), r.Next(0, 255), r.Next(0, 255))); } pc.AddRange(p3dlist, collist); cnd.ThePc = pc; cnd.Enabled = true; } doc.Views.Redraw(); return(Result.Success); }
/// <summary> /// Solves the instance. /// </summary> /// <param name="DA">Da.</param> protected override void SolveInstance(IGH_DataAccess DA) { // Properties Mesh mesh = null; Curve initialCurve = null; double specifiedDistance = 0.0; int maxCount = 0; double threshold = 0.0; double perpStepSize = 0.0; bool bothDir = false; double minThreshold = 0.0; // Set the input data if (!DA.GetData(0, ref mesh)) { return; } if (!DA.GetData(1, ref initialCurve)) { return; } if (!DA.GetData(2, ref bothDir)) { return; } if (!DA.GetData(3, ref maxCount)) { return; } if (!DA.GetData(4, ref threshold)) { return; } if (!DA.GetData(5, ref specifiedDistance)) { return; } if (!DA.GetData(6, ref perpStepSize)) { return; } if (!DA.GetData(7, ref minThreshold)) { return; } // Data validation if (maxCount == 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Count cannot be 0"); } if (!mesh.IsValid) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh is invalid"); } // Placeholder properties DataTree <Curve> pattern = new DataTree <Curve>(); Curve previousCurve = initialCurve; List <Curve> perpGeods = new List <Curve>(); List <double> perpParams = new List <double>(); // Start piecewise evolution process for (int i = 0; i < maxCount; i++) { Debug.WriteLine("Iter " + i); // Create placeholder lists perpGeods = new List <Curve>(); perpParams = new List <double>(); // Divide curve double[] geodParams = previousCurve.DivideByLength(perpStepSize, true); if (geodParams == null) { AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "No points found on iter" + i); break; } if (geodParams.Length <= 2) { AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not enough points found on iter" + i); break; } // Generate perp geodesics for measurement foreach (double t in geodParams) { // Get curve tangent vector and mesh normal Point3d point = previousCurve.PointAt(t); Vector3d tangent = previousCurve.TangentAt(t); Vector3d normal = mesh.NormalAt(mesh.ClosestMeshPoint(point, 0.0)); // Rotate vector against normals 90 degrees tangent.Rotate(0.5 * Math.PI, normal); // Generate perp geodesic Curve perpGeodesic = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, point, tangent, 100).ToNurbsCurve(); // Check for success if (perpGeodesic != null && perpGeodesic.GetLength() > specifiedDistance) { // Divide by specified length double perpT = 0.0; perpGeodesic.LengthParameter(specifiedDistance, out perpT); // Add data to lists perpGeods.Add(perpGeodesic); perpParams.Add(perpT); } } // Clean perp geods of intersections ocurring BEFORE the specified distance var result = CleanPerpGeodesics(perpGeods, perpParams, specifiedDistance); // Assign clean lists perpGeods = result.perpGeodesics; perpParams = result.perpParams; // Break if not enough perpGeods remain if (perpGeods.Count < 6) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Not enough perp geodesics where found for iter " + i); break; } //Generate the next piecewise geodesic List <Curve> iterCurves = GeneratePiecewiseGeodesicCurve(mesh, perpParams, perpGeods, 1000, bothDir, 0, threshold, Vector3d.Unset); // Add it to the pattern pattern.AddRange(iterCurves, new GH_Path(i)); // Assign as previous for the next round Curve[] joinedResult = Curve.JoinCurves(iterCurves); // Error check if (joinedResult.Length > 1) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "More than 1 curve after Join in iter " + i); break; } //Create points and bisectrix vectors for next round of perp geodesics Point3dList ptList = new Point3dList(); foreach (Curve c in iterCurves) { if (!ptList.Contains(c.PointAtStart)) { ptList.Add(c.PointAtStart); } if (!ptList.Contains(c.PointAtEnd)) { ptList.Add(c.PointAtEnd); } } Debug.WriteLine("ptList Count: " + ptList.Count); // Assign new curve to previous curve Curve joinedCurve = joinedResult[0]; previousCurve = joinedCurve; } // Assign data to output DA.SetDataTree(0, pattern); DA.SetDataList(2, perpGeods); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { Point3dList points = new Point3dList(); // Point3dList is from the Collections class, we add a new variable points then initialize it and add // empty array Result commandres; //calls class Point3dList and initializes a new empty array with the name 'points' while (true) //make an infinite loop. every time we click on screen we will create a point which will // be added to the document and the screen will be refreshed. it happens fast!! { var gp = new GetPoint(); //prompt user string prompt; prompt = "set point(s) by click"; gp.SetCommandPrompt(prompt); //set up what to do with the result var res = gp.Get(); //get function returns a really cool type of enumeration // https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Input_GetResult.htm if (res == GetResult.Point) //using Rhino.Input, double equal sign is necessary... { doc.Objects.AddPoint(gp.Point()); //adds a point object to the document to object table doc.Views.Redraw(); //refreshes the views points.Add(gp.Point()); // add the point to our points array declared above commandres = Result.Success; } else if (res == GetResult.Nothing) { commandres = Result.Failure; break; } else { commandres = Result.Cancel; break; } } RhinoApp.WriteLine("The user drew {0} point(s) successfully", points.Count.ToString()); // access the points array and cast it to a string, outside the function so that it will only // show how many ponints you've drawn when the function is complete. return(Result.Success); }
DataTree<Object> GetStepTree(Mesh terrainMesh, List<double> contourZList, DataTree<Curve> contourTree, List<Brep> brepList) { DataTree<Object> stepTree = new DataTree<Object>(); Plane basePlane = Plane.WorldXY; basePlane.OriginZ = terrainMesh.GetBoundingBox(true).Min.Z; // For each contour-plane for (int i = 0; i < contourTree.BranchCount; i++) { // create higher-Z pt list Point3dList winPtList = new Point3dList(); foreach (Curve contourCrv in contourTree.Branches[i]) { Plane frm; double t; contourCrv.NormalizedLengthParameter(0.5, out t); contourCrv.FrameAt(t, out frm); frm.Transform(Rhino.Geometry.Transform.PlanarProjection(basePlane)); Point3d samplePt0, samplePt1; samplePt0 = frm.Origin; samplePt1 = frm.Origin; samplePt0 += doc.ModelAbsoluteTolerance * frm.YAxis; samplePt1 -= doc.ModelAbsoluteTolerance * frm.YAxis; Ray3d ray0 = new Ray3d(samplePt0, Vector3d.ZAxis); Ray3d ray1 = new Ray3d(samplePt1, Vector3d.ZAxis); double rayParam0 = Rhino.Geometry.Intersect.Intersection.MeshRay(terrainMesh, ray0); double rayParam1 = Rhino.Geometry.Intersect.Intersection.MeshRay(terrainMesh, ray1); winPtList.Add(((rayParam0 > rayParam1) ? samplePt0 : samplePt1)); } // For each splitted region in contour-plane foreach (BrepFace brepFace in brepList[i].Faces) { Brep testBrep = brepFace.DuplicateFace(false); foreach (Point3d pt in winPtList) { LineCurve testRay = new LineCurve(new Line(pt, Vector3d.ZAxis, 1000)); Point3d[] outPts; Curve[] outCrvs; bool ix = Rhino.Geometry.Intersect.Intersection.CurveBrep(testRay, testBrep, doc.ModelAbsoluteTolerance, out outCrvs, out outPts); if (outPts.Length != 0) { stepTree.Add(testBrep, new GH_Path(i)); break; } } } } return stepTree; }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { IGH_GeometricGoo shape = null; int num = -1; int ite = -1; List <Point3d> attractors = new List <Point3d>(); List <double> radiuses = new List <double>(); List <double> weights = new List <double>(); if (!DA.GetData <IGH_GeometricGoo>(0, ref shape)) { return; } if (!DA.GetData(1, ref num)) { return; } if (!DA.GetData(2, ref ite)) { return; } DA.GetDataList(3, attractors); DA.GetDataList(4, radiuses); DA.GetDataList(5, weights); GeometryBase geo = GH_Convert.ToGeometryBase(shape); var points = new Point3dList(); var attracts = new Point3dList(attractors); var rnd = new Random(); var bbox = geo.GetBoundingBox(true); for (int i = 0; i < num; i++) { if (points.Count == 0) { var rndpt = CreateRandomPoint(rnd, geo, bbox); points.Add(rndpt); } else { double fdist = -1; Point3d fpos = new Point3d(); for (int t = 0; t < Math.Max(Math.Min(ite, i), 10); t++) { var nrndpt = CreateRandomPoint(rnd, geo, bbox); double nattractdist = 1; for (int n = 0; n < attracts.Count; n++) { var nattract = attracts[n]; var rad = radiuses[Math.Min(n, radiuses.Count - 1)]; var pow = weights[Math.Min(n, radiuses.Count - 1)]; var ntdist = Math.Pow(JellyUtility.Remap(Math.Min(nattract.DistanceTo(nrndpt), rad), 0, rad, 0, 1.0), pow); nattractdist *= ntdist; } var nindex = points.ClosestIndex(nrndpt); var npos = points[nindex]; var ndist = npos.DistanceTo(nrndpt) * nattractdist; if (fdist < ndist) { fdist = ndist; fpos = nrndpt; } } points.Add(fpos); } } DA.SetDataList(0, points); }
/// <summary> /// Removes duplicate/invalid/tiny curves and outputs the cleaned list, a list of unique nodes and a list of node pairs. /// </summary> public static List<Curve> CleanNetwork(List<Curve> inputStruts, double tol, out Point3dList nodes, out List<IndexPair> nodePairs) { nodes = new Point3dList(); nodePairs = new List<IndexPair>(); var struts = new List<Curve>(); // Loop over list of struts for (int i = 0; i < inputStruts.Count; i++) { Curve strut = inputStruts[i]; // Unitize domain strut.Domain = new Interval(0, 1); // Minimum strut length (if user defined very small tolerance, use 100*rhinotolerance) double minLength = Math.Max(tol, 100*RhinoDoc.ActiveDoc.ModelAbsoluteTolerance); // If strut is invalid, ignore it if (strut == null || !strut.IsValid || strut.IsShort(minLength)) { continue; } Point3d[] pts = new Point3d[2] { strut.PointAtStart, strut.PointAtEnd }; List<int> nodeIndices = new List<int>(); // Loop over end points of strut // Check if node is already in nodes list, if so, we find its index instead of creating a new node for (int j = 0; j < 2; j++) { Point3d pt = pts[j]; // Find closest node to current pt int closestIndex = nodes.ClosestIndex(pt); // If node already exists (within tolerance), set the index if (nodes.Count != 0 && pt.EpsilonEquals(nodes[closestIndex], tol)) { nodeIndices.Add(closestIndex); } // If node doesn't exist else { // Update lookup list nodes.Add(pt); nodeIndices.Add(nodes.Count - 1); } } // We must ignore duplicate struts bool isDuplicate = false; IndexPair nodePair = new IndexPair(nodeIndices[0], nodeIndices[1]); int dupIndex = nodePairs.IndexOf(nodePair); // dupIndex equals -1 if nodePair not found, i.e. if it doesn't equal -1, a match was found if (nodePairs.Count != 0 && dupIndex != -1) { // Check the curve midpoint to make sure it's a duplicate Curve testStrut = struts[dupIndex]; Point3d ptA = strut.PointAt(0.5); Point3d ptB = testStrut.PointAt(0.5); if (ptA.EpsilonEquals(ptB, tol)) isDuplicate = true; } // So we only create the strut if it doesn't exist yet (check nodePairLookup list) if (!isDuplicate) { // Update the lookup list nodePairs.Add(nodePair); strut.Domain = new Interval(0, 1); struts.Add(strut); } } return struts; }
public static DataTree<Polyline> makeTiles(Mesh mesh) { DataTree < Polyline> Tree = new DataTree<Polyline>(); for(int i = 0;i < mesh.Faces.Count;i++) { Vector3d ab = new Vector3d (mesh.Vertices[mesh.Faces[i].B] - mesh.Vertices[mesh.Faces[i].A]); Vector3d ac = new Vector3d (mesh.Vertices[mesh.Faces[i].C] - mesh.Vertices[mesh.Faces[i].A]); Point3dList pts = new Point3dList(); pts.Add(mesh.Vertices[mesh.Faces[i].A]); pts.Add(mesh.Vertices[mesh.Faces[i].C]); pts.Add(mesh.Vertices[mesh.Faces[i].B]); Polyline edge = new Polyline(pts); Tree.Add(edge); } return Tree; }
/// <summary> /// Removes duplicate/invalid/tiny curves and outputs the cleaned list, a list of unique nodes and a list of node pairs. /// </summary> public static List <Curve> CleanNetwork(List <Curve> inputStruts, double tol, out Point3dList nodes, out List <IndexPair> nodePairs) { nodes = new Point3dList(); nodePairs = new List <IndexPair>(); var struts = new List <Curve>(); // Loop over list of struts for (int i = 0; i < inputStruts.Count; i++) { Curve strut = inputStruts[i]; // Unitize domain strut.Domain = new Interval(0, 1); // Minimum strut length (if user defined very small tolerance, use 100*rhinotolerance) double minLength = Math.Max(tol, 100 * RhinoDoc.ActiveDoc.ModelAbsoluteTolerance); // If strut is invalid, ignore it if (strut == null || !strut.IsValid || strut.IsShort(minLength)) { continue; } Point3d[] pts = new Point3d[2] { strut.PointAtStart, strut.PointAtEnd }; List <int> nodeIndices = new List <int>(); // Loop over end points of strut // Check if node is already in nodes list, if so, we find its index instead of creating a new node for (int j = 0; j < 2; j++) { Point3d pt = pts[j]; // Find closest node to current pt int closestIndex = nodes.ClosestIndex(pt); // If node already exists (within tolerance), set the index if (nodes.Count != 0 && pt.EpsilonEquals(nodes[closestIndex], tol)) { nodeIndices.Add(closestIndex); } // If node doesn't exist else { // Update lookup list nodes.Add(pt); nodeIndices.Add(nodes.Count - 1); } } // We must ignore duplicate struts bool isDuplicate = false; IndexPair nodePair = new IndexPair(nodeIndices[0], nodeIndices[1]); int dupIndex = nodePairs.IndexOf(nodePair); // dupIndex equals -1 if nodePair not found, i.e. if it doesn't equal -1, a match was found if (nodePairs.Count != 0 && dupIndex != -1) { // Check the curve midpoint to make sure it's a duplicate Curve testStrut = struts[dupIndex]; Point3d ptA = strut.PointAt(0.5); Point3d ptB = testStrut.PointAt(0.5); if (ptA.EpsilonEquals(ptB, tol)) { isDuplicate = true; } } // So we only create the strut if it doesn't exist yet (check nodePairLookup list) if (!isDuplicate) { // Update the lookup list nodePairs.Add(nodePair); strut.Domain = new Interval(0, 1); struts.Add(strut); } } return(struts); }