/// <summary> /// Translate integeres to CornerStyle /// </summary> /// <param name="cornerStyleInInt"></param> /// <param name="cornerStyle"></param> private static void GetCornerStyleFromInt(ref int cornerStyleInInt, ref CurveOffsetCornerStyle cornerStyle) { if (cornerStyleInInt < 0) { cornerStyleInInt = 0; } if (cornerStyleInInt > 4) { cornerStyleInInt = 4; } switch (cornerStyleInInt) { case (0): cornerStyle = CurveOffsetCornerStyle.None; break; case (1): cornerStyle = CurveOffsetCornerStyle.Sharp; break; case (2): cornerStyle = CurveOffsetCornerStyle.Round; break; case (3): cornerStyle = CurveOffsetCornerStyle.Smooth; break; case (4): cornerStyle = CurveOffsetCornerStyle.Chamfer; break; } }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object can be used to retrieve data from input parameters and /// to store data in output parameters.</param> protected override void SolveInstance(IGH_DataAccess DA) { List <Curve> curveList = new List <Curve>(); DA.GetDataList(0, curveList); //GH_Structure<GH_Activ> in_IDtree = new GH_Structure<Curve>(); double width = new double(); if (!DA.GetData(1, ref width)) { width = .1; } double halfwidth = width / 2.0; CurveOffsetCornerStyle cornerstyle = new CurveOffsetCornerStyle(); List <PolylineCurve> plines = new List <PolylineCurve>(); Vector3d normal = new Vector3d(0.0, 0.0, 1.0); Point3d origin = new Point3d(0.0, 0.0, 0.0); Plane plane = new Plane(origin, normal); foreach (Curve c in curveList) { Polyline pl = new Polyline(); if (c.TryGetPolyline(out pl)) { int segCount = pl.SegmentCount; Line[] segments = pl.GetSegments(); foreach (Line l in segments) { l.Extend(halfwidth, halfwidth); Curve crv = l.ToNurbsCurve(); Curve[] offset1 = crv.Offset(plane, halfwidth, 0.0, cornerstyle); Curve[] offset2 = crv.Offset(plane, -halfwidth, 0.0, cornerstyle); Point3d[] rect = new Point3d[5] { offset1[0].PointAtStart, offset1[0].PointAtEnd, offset2[0].PointAtEnd, offset2[0].PointAtStart, offset1[0].PointAtStart }; PolylineCurve plc = new PolylineCurve(rect); plines.Add(plc); } } } // 2. Boolean Union Curve[] final = PolylineCurve.CreateBooleanUnion(plines); // 3. Set data back DA.SetDataList(0, final); }
/// <summary> /// Offsets this curve. If you have a nice offset, then there will be one entry in /// the array. If the original curve had kinks or the offset curve had self /// intersections, you will get multiple segments in the offset_curves[] array. /// </summary> /// <param name="directionPoint">A point that indicates the direction of the offset.</param> /// <param name="normal">The normal to the offset plane.</param> /// <param name="distance">The positive or negative distance to offset.</param> /// <param name="tolerance">The offset or fitting tolerance.</param> /// <param name="cornerStyle">Corner style for offset kinks.</param> /// <returns>Offset curves on success, null on failure.</returns> public Curve[] Offset(Point3d directionPoint, Vector3d normal, double distance, double tolerance, CurveOffsetCornerStyle cornerStyle) { IntPtr ptr = ConstPointer(); SimpleArrayCurvePointer offsetCurves = new SimpleArrayCurvePointer(); IntPtr pCurveArray = offsetCurves.NonConstPointer(); bool rc = UnsafeNativeMethods.RHC_RhinoOffsetCurve2(ptr, distance, directionPoint, normal, (int)cornerStyle, tolerance, pCurveArray); Curve[] curves = offsetCurves.ToNonConstArray(); offsetCurves.Dispose(); if (!rc) return null; return curves; }
/// <summary> /// Offsets this curve. If you have a nice offset, then there will be one entry in /// the array. If the original curve had kinks or the offset curve had self /// intersections, you will get multiple segments in the offset_curves[] array. /// </summary> /// <param name="plane">Offset solution plane.</param> /// <param name="distance">The positive or negative distance to offset.</param> /// <param name="tolerance">The offset or fitting tolerance.</param> /// <param name="cornerStyle">Corner style for offset kinks.</param> /// <returns>Offset curves on success, null on failure.</returns> public Curve[] Offset(Plane plane, double distance, double tolerance, CurveOffsetCornerStyle cornerStyle) { // Create a bogus dir point Point3d direction_point = plane.Origin + plane.XAxis; Random rnd = new Random(1); // Try a hundred times to find a smooth place on the curve where the tangent // is not (anti)parallel to the offset plane z-axis. // This is unbelievably foul, but the most consistent offset result I // can come up with on short notice. for (int i = 0; i < 100; i++) { double t = Domain.ParameterAt(rnd.NextDouble()); if (IsContinuous(Continuity.G1_continuous, t)) { Point3d p = PointAt(t); Vector3d v = TangentAt(t); if (v.IsParallelTo(plane.ZAxis, RhinoMath.ToRadians(0.1)) == 0) { Vector3d perp = Vector3d.CrossProduct(v, plane.ZAxis); perp.Unitize(); direction_point = p + 1e-3 * perp; break; } } } return Offset(direction_point, plane.Normal, distance, tolerance, cornerStyle); //IntPtr ptr = ConstPointer(); //SimpleArrayCurvePointer offsetCurves = new SimpleArrayCurvePointer(); //IntPtr pCurveArray = offsetCurves.NonConstPointer(); //bool rc = UnsafeNativeMethods.RHC_RhinoOffsetCurve(ptr, plane.ZAxis, plane.Origin, distance, pCurveArray, tolerance, 0.015, (int)cornerStyle); //Curve[] curves = offsetCurves.ToNonConstArray(); //offsetCurves.Dispose(); //if (!rc) // return null; //return curves; }
public Curve[] AfterOffset(Curve destination, double naN, Plane unset, int num2) { if (!RhinoMath.IsValidDouble(naN)) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "不是有效的数字"); return(new Curve[] {}); } else if (!unset.IsValid) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "不是有效的平面"); return(new Curve[] { }); } else { double num3 = Math.Abs(naN); double tolerance = Math.Min(GH_Component.DocumentTolerance(), 0.1 * num3); GH_Component.DocumentAngleTolerance(); num2 = Math.Max(Math.Min(num2, 4), 0); if (naN == 0.0) { return(new Curve[] { destination }); } else { CurveOffsetCornerStyle none = CurveOffsetCornerStyle.None; switch (num2) { case 0: none = CurveOffsetCornerStyle.None; break; case 1: none = CurveOffsetCornerStyle.Sharp; break; case 2: none = CurveOffsetCornerStyle.Round; break; case 3: none = CurveOffsetCornerStyle.Smooth; break; case 4: none = CurveOffsetCornerStyle.Chamfer; break; } Curve[] inputCurves = null; inputCurves = destination.Offset(unset, naN, tolerance, none); if (inputCurves == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "不能偏移该曲线"); return(new Curve[] { }); } else { Curve[] data = Curve.JoinCurves(inputCurves); if (data == null) { return(inputCurves); } else { return(data); } } } } }
/// <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) { InputChecker inputChecker = new InputChecker(this); #region get Input From GH Canvas GH_Structure <GH_Curve> inCurves = new GH_Structure <GH_Curve>(); bool areCurvesOK = DA.GetDataTree(0, out inCurves); inputChecker.StopIfConversionIsFailed(areCurvesOK); GH_Structure <GH_Curve> ghCurves = new GH_Structure <GH_Curve>(); ghCurves = inCurves.Duplicate(); ghCurves.Graft(GH_GraftMode.GraftAll); ghCurves.Simplify(GH_SimplificationMode.CollapseAllOverlaps); GH_Structure <GH_Number> inDistances = new GH_Structure <GH_Number>(); bool areDistancesOk = DA.GetDataTree(1, out inDistances); inputChecker.StopIfConversionIsFailed(areDistancesOk); GH_Structure <GH_Number> ghDistances = new GH_Structure <GH_Number>(); ghDistances = ValuesAllocator.NumsDSFromCurves(ghCurves, inDistances, ghDistances); GH_Structure <GH_Plane> inPlanes = new GH_Structure <GH_Plane>(); bool arePlanesOk = DA.GetDataTree(2, out inPlanes); inputChecker.StopIfConversionIsFailed(arePlanesOk); GH_Structure <GH_Plane> ghPlanes = new GH_Structure <GH_Plane>(); ghPlanes = ValuesAllocator.PlanesDSFromCurves(ghCurves, inPlanes, ghPlanes); GH_Structure <GH_Integer> inCorners = new GH_Structure <GH_Integer>(); bool areCornerssOk = DA.GetDataTree(3, out inCorners); inputChecker.StopIfConversionIsFailed(areCornerssOk); GH_Structure <GH_Integer> ghCorners = new GH_Structure <GH_Integer>(); ghCorners = ValuesAllocator.IntegerDSFromCurves(ghCurves, inCorners, ghCorners); #endregion GH_Structure <GH_Curve> ghCurveOffset = new GH_Structure <GH_Curve>(); double docTollerance = DocumentTolerance(); int pathIndex = 0; foreach (GH_Path ghPath in ghCurves.Paths) { for (int i = 0; i < ghCurves.get_Branch(ghPath).Count; i++) { CurveOffsetCornerStyle cornerStyle = CurveOffsetCornerStyle.None; int cornerStyleInInt = ghCorners.get_DataItem(ghPath, i).Value; GetCornerStyleFromInt(ref cornerStyleInInt, ref cornerStyle); Curve crv = ghCurves.get_DataItem(ghPath, i).Value; Plane plane = ghPlanes.get_DataItem(ghPath, i).Value; double dist = ghDistances.get_DataItem(ghPath, i).Value; List <Curve> resultingCurves = new List <Curve>(); resultingCurves.AddRange(crv.Offset(plane, dist, docTollerance, cornerStyle)); resultingCurves.AddRange(crv.Offset(plane, dist *= -1, docTollerance, cornerStyle)); foreach (Curve resultingCrv in resultingCurves) { GH_Curve ghResultingCrv = null; if (GH_Convert.ToGHCurve(resultingCrv, GH_Conversion.Both, ref ghResultingCrv)) { ghCurveOffset.Append(ghResultingCrv, ghPath); } } } pathIndex++; } DA.SetDataTree(0, ghCurveOffset); }
public static Curve OffsetOut(this Curve curve, double distance, Plane plane, CurveOffsetCornerStyle cornerStyle = CurveOffsetCornerStyle.Sharp) { if (distance == 0) { return(curve); } double original_area = AreaMassProperties.Compute(curve).Area; Curve[] offset_1 = curve.Offset(plane, distance, ObjectModel.Tolerance.Distance, cornerStyle); if (offset_1 != null) { double area_1 = AreaMassProperties.Compute(offset_1[0]).Area; if (area_1 > original_area) { return(offset_1[0]); } else { return(curve.Offset(plane, -distance, ObjectModel.Tolerance.Distance, cornerStyle)[0]); } } else { return(curve.Offset(plane, -distance, ObjectModel.Tolerance.Distance, cornerStyle)[0]); } }
//====================================================================// public static NotImplementedException OffsetIn(this Curve curve, double distance, Plane plane, CurveOffsetCornerStyle cornerStyle = CurveOffsetCornerStyle.Sharp) { return(new NotImplementedException()); }