/// <summary> /// Calculates the boolean difference between a closed planar curve, and a list of closed planar curves. /// Note, curves must be co-planar. /// </summary> /// <param name="curveA">The first closed, planar curve.</param> /// <param name="subtractors">curves to subtract from the first closed curve.</param> /// <returns>Result curves on success, empty array if no difference could be calculated.</returns> public static Curve[] CreateBooleanDifference(Curve curveA, IEnumerable<Curve> subtractors) { if (null == curveA || null == subtractors) throw new ArgumentNullException(null == curveA ? "curveA" : "subtractors"); List<Curve> curves = new List<Curve> { curveA }; curves.AddRange(subtractors); SimpleArrayCurvePointer input = new SimpleArrayCurvePointer(curves); IntPtr inputPtr = input.ConstPointer(); SimpleArrayCurvePointer output = new SimpleArrayCurvePointer(); IntPtr outputPtr = output.NonConstPointer(); int rc = UnsafeNativeMethods.ON_Curve_BooleanOperation(inputPtr, outputPtr, idxBooleanDifference); return rc < 1 ? new Curve[0] : output.ToNonConstArray(); }
/// <summary> /// Projects a curve to a set of meshes using a direction and tolerance. /// </summary> /// <param name="curves">A list, an array or any enumerable of curves.</param> /// <param name="meshes">A list, an array or any enumerable of meshes.</param> /// <param name="direction">A direction vector.</param> /// <param name="tolerance">A tolerance value.</param> /// <returns>A curve array.</returns> public static Curve[] ProjectToMesh(IEnumerable<Curve> curves, IEnumerable<Mesh> meshes, Vector3d direction, double tolerance) { foreach (Curve crv in curves) { if (crv == null) throw new ArgumentNullException("curves"); } List<GeometryBase> g = new List<GeometryBase>(); foreach (Mesh msh in meshes) { if (msh == null) throw new ArgumentNullException("meshes"); g.Add(msh); } using (SimpleArrayCurvePointer crv_array = new SimpleArrayCurvePointer(curves)) using (Runtime.InteropWrappers.SimpleArrayGeometryPointer mesh_array = new Runtime.InteropWrappers.SimpleArrayGeometryPointer(g)) using (SimpleArrayCurvePointer curves_out = new SimpleArrayCurvePointer()) { IntPtr pCurvesIn = crv_array.ConstPointer(); IntPtr pMeshes = mesh_array.ConstPointer(); IntPtr pCurvesOut = curves_out.NonConstPointer(); Curve[] rc = new Curve[0]; if (UnsafeNativeMethods.RHC_RhinoProjectCurveToMesh(pMeshes, pCurvesIn, direction, tolerance, pCurvesOut)) rc = curves_out.ToNonConstArray(); return rc; } }
/// <summary> /// Calculates the boolean union of two or more closed, planar curves. /// Note, curves must be co-planar. /// </summary> /// <param name="curves">The co-planar curves to union.</param> /// <returns>Result curves on success, empty array if no union could be calculated.</returns> public static Curve[] CreateBooleanUnion(IEnumerable<Curve> curves) { if (null == curves) throw new ArgumentNullException("curves"); SimpleArrayCurvePointer input = new SimpleArrayCurvePointer(curves); IntPtr inputPtr = input.ConstPointer(); SimpleArrayCurvePointer output = new SimpleArrayCurvePointer(); IntPtr outputPtr = output.NonConstPointer(); int rc = UnsafeNativeMethods.ON_Curve_BooleanOperation(inputPtr, outputPtr, idxBooleanUnion); return rc < 1 ? new Curve[0] : output.ToNonConstArray(); }
/// <summary> /// Calculates the boolean intersection of two closed, planar curves. /// Note, curves must be co-planar. /// </summary> /// <param name="curveA">The first closed, planar curve.</param> /// <param name="curveB">The second closed, planar curve.</param> /// <returns>Result curves on success, empty array if no intersection could be calculated.</returns> public static Curve[] CreateBooleanIntersection(Curve curveA, Curve curveB) { if (null == curveA || null == curveB) throw new ArgumentNullException(null == curveA ? "curveA" : "curveB"); SimpleArrayCurvePointer input = new SimpleArrayCurvePointer(new Curve[] { curveA, curveB }); IntPtr inputPtr = input.ConstPointer(); SimpleArrayCurvePointer output = new SimpleArrayCurvePointer(); IntPtr outputPtr = output.NonConstPointer(); int rc = UnsafeNativeMethods.ON_Curve_BooleanOperation(inputPtr, outputPtr, idxBooleanIntersection); return rc < 1 ? new Curve[0] : output.ToNonConstArray(); }
/// <summary> /// Creates curves between two open or closed input curves. Use sample points method to make curves compatible. /// This is how the algorithm workd: Divides the two curves into an equal number of points, finds the midpoint between the /// corresponding points on the curves and interpolates the tween curve through those points. There is no matching of curves /// direction. Caller must match input curves direction before calling the function. /// </summary> /// <param name="curve0">The first, or starting, curve.</param> /// <param name="curve1">The second, or ending, curve.</param> /// <param name="numCurves">Number of tween curves to create.</param> /// <param name="numSamples">Number of sample points along input curves.</param> /// <returns>>An array of joint curves. This array can be empty.</returns> public static Curve[] CreateTweenCurvesWithSampling(Curve curve0, Curve curve1, int numCurves, int numSamples) { IntPtr pConstCurve0 = curve0.ConstPointer(); IntPtr pConstCurve1 = curve1.ConstPointer(); SimpleArrayCurvePointer output = new SimpleArrayCurvePointer(); IntPtr outputPtr = output.NonConstPointer(); bool rc = UnsafeNativeMethods.RHC_RhinoTweenCurveWithSampling(pConstCurve0, pConstCurve1, numCurves, numSamples, outputPtr); return rc ? output.ToNonConstArray() : new Curve[0]; }
/// <summary> /// Joins a collection of curve segments together. /// </summary> /// <param name="inputCurves">An array, a list or any enumerable set of curve segments to join.</param> /// <param name="joinTolerance">Joining tolerance, /// i.e. the distance between segment end-points that is allowed.</param> /// <param name="preserveDirection"> /// <para>If true, curve endpoints will be compared to curve startpoints.</para> /// <para>If false, all start and endpoints will be compared and copies of input curves may be reversed in output.</para> /// </param> /// <returns>An array of joint curves. This array can be empty.</returns> /// <exception cref="ArgumentNullException">If inputCurves is null.</exception> public static Curve[] JoinCurves(IEnumerable<Curve> inputCurves, double joinTolerance, bool preserveDirection) { // 1 March 2010 S. Baer // JoinCurves calls the unmanaged RhinoMergeCurves function which appears to be a "better" // implementation of ON_JoinCurves. We removed the wrapper for ON_JoinCurves for this reason. if (null == inputCurves) throw new ArgumentNullException("inputCurves"); SimpleArrayCurvePointer input = new SimpleArrayCurvePointer(inputCurves); IntPtr inputPtr = input.ConstPointer(); SimpleArrayCurvePointer output = new SimpleArrayCurvePointer(); IntPtr outputPtr = output.NonConstPointer(); bool rc = UnsafeNativeMethods.RHC_RhinoMergeCurves(inputPtr, outputPtr, joinTolerance, preserveDirection); return rc ? output.ToNonConstArray() : new Curve[0]; }
/// <summary> /// Offset a curve on a brep face surface. This curve must lie on the surface. /// <para>This overload allows to specify different offsets for different curve parameters.</para> /// </summary> /// <param name="face">The brep face on which to offset.</param> /// <param name="curveParameters">Curve parameters corresponding to the offset distances.</param> /// <param name="offsetDistances">distances to offset (+)left, (-)right.</param> /// <param name="fittingTolerance">A fitting tolerance.</param> /// <returns>Offset curves on success, or null on failure.</returns> /// <exception cref="ArgumentNullException">If face, curveParameters or offsetDistances are null.</exception> public Curve[] OffsetOnSurface(BrepFace face, double[] curveParameters, double[] offsetDistances, double fittingTolerance) { if (face == null) throw new ArgumentNullException("face"); if (curveParameters == null) throw new ArgumentNullException("curveParameters"); if (offsetDistances == null) throw new ArgumentNullException("offsetDistances"); int array_count = curveParameters.Length; if (offsetDistances.Length != array_count) throw new ArgumentException("curveParameters and offsetDistances must be the same length"); int fid = face.m_index; IntPtr pConstBrep = face.m_brep.ConstPointer(); SimpleArrayCurvePointer offsetCurves = new SimpleArrayCurvePointer(); IntPtr pCurveArray = offsetCurves.NonConstPointer(); IntPtr pConstCurve = ConstPointer(); int count = UnsafeNativeMethods.RHC_RhinoOffsetCurveOnSrf3(pConstCurve, pConstBrep, fid, array_count, curveParameters, offsetDistances, fittingTolerance, pCurveArray); Curve[] curves = offsetCurves.ToNonConstArray(); offsetCurves.Dispose(); if (count < 1) return null; return curves; }
/// <summary> /// Pull a curve to a BrepFace using closest point projection. /// </summary> /// <param name="curve">Curve to pull.</param> /// <param name="face">Brepface that pulls.</param> /// <param name="tolerance">Tolerance to use for pulling.</param> /// <returns>An array of pulled curves, or an empty array on failure.</returns> public static Curve[] PullToBrepFace(Curve curve, BrepFace face, double tolerance) { IntPtr brep_ptr = face.m_brep.ConstPointer(); IntPtr curve_ptr = curve.ConstPointer(); using (SimpleArrayCurvePointer rc = new SimpleArrayCurvePointer()) { IntPtr rc_ptr = rc.NonConstPointer(); if (UnsafeNativeMethods.RHC_RhinoPullCurveToBrep(brep_ptr, face.FaceIndex, curve_ptr, tolerance, rc_ptr)) { return rc.ToNonConstArray(); } return new Curve[0]; } }
/// <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> /// Offset a curve on a brep face surface. This curve must lie on the surface. /// <para>This overload allows to specify a surface point at which the offset will pass.</para> /// </summary> /// <param name="face">The brep face on which to offset.</param> /// <param name="throughPoint">2d point on the brep face to offset through.</param> /// <param name="fittingTolerance">A fitting tolerance.</param> /// <returns>Offset curves on success, or null on failure.</returns> /// <exception cref="ArgumentNullException">If face is null.</exception> public Curve[] OffsetOnSurface(BrepFace face, Point2d throughPoint, double fittingTolerance) { if (face == null) throw new ArgumentNullException("face"); int fid = face.m_index; IntPtr pConstBrep = face.m_brep.ConstPointer(); SimpleArrayCurvePointer offsetCurves = new SimpleArrayCurvePointer(); IntPtr pCurveArray = offsetCurves.NonConstPointer(); IntPtr pConstCurve = ConstPointer(); int count = UnsafeNativeMethods.RHC_RhinoOffsetCurveOnSrf2(pConstCurve, pConstBrep, fid, throughPoint, fittingTolerance, pCurveArray); Curve[] curves = offsetCurves.ToNonConstArray(); offsetCurves.Dispose(); if (count < 1) return null; return curves; }
/// <summary> /// Splits a curve into pieces using a surface. /// </summary> /// <param name="cutter">A cutting surface or polysurface.</param> /// <param name="tolerance">A tolerance for computing intersections.</param> /// <returns>An array of curves. This array can be empty.</returns> public Curve[] Split(Surface cutter, double tolerance) { IntPtr pConstThis = ConstPointer(); IntPtr pConstSurface = cutter.ConstPointer(); using (Rhino.Runtime.InteropWrappers.SimpleArrayCurvePointer pieces = new SimpleArrayCurvePointer()) { IntPtr pPieces = pieces.NonConstPointer(); UnsafeNativeMethods.RHC_RhinoCurveSplit(pConstThis, pConstSurface, tolerance, pPieces); return pieces.ToNonConstArray(); } }
/// <summary> /// Splits a curve into pieces using a polysurface. /// </summary> /// <param name="cutter">A cutting surface or polysurface.</param> /// <param name="tolerance">A tolerance for computing intersections.</param> /// <returns>An array of curves. This array can be empty.</returns> public Curve[] Split(Brep cutter, double tolerance) { if (cutter == null) throw new ArgumentNullException("cutter"); IntPtr pConstThis = ConstPointer(); IntPtr pConstBrep = cutter.ConstPointer(); using (Rhino.Runtime.InteropWrappers.SimpleArrayCurvePointer pieces = new SimpleArrayCurvePointer()) { IntPtr pPieces = pieces.NonConstPointer(); UnsafeNativeMethods.RHC_RhinoCurveSplit(pConstThis, pConstBrep, tolerance, pPieces); return pieces.ToNonConstArray(); } }
/// <summary> /// Polylines will be exploded into line segments. ExplodeCurves will /// return the curves in topological order. /// </summary> /// <returns> /// An array of all the segments that make up this curve. /// </returns> public Curve[] DuplicateSegments() { IntPtr ptr = ConstPointer(); SimpleArrayCurvePointer output = new SimpleArrayCurvePointer(); IntPtr outputPtr = output.NonConstPointer(); int rc = UnsafeNativeMethods.RHC_RhinoDuplicateCurveSegments(ptr, outputPtr); return rc < 1 ? new Curve[0] : output.ToNonConstArray(); }
/// <summary> /// Projects a Curve onto a Brep along a given direction. /// </summary> /// <param name="curve">Curve to project.</param> /// <param name="brep">Brep to project onto.</param> /// <param name="direction">Direction of projection.</param> /// <param name="tolerance">Tolerance to use for projection.</param> /// <returns>An array of projected curves or empty array if the projection set is empty.</returns> public static Curve[] ProjectToBrep(Curve curve, Brep brep, Vector3d direction, double tolerance) { IntPtr brep_ptr = brep.ConstPointer(); IntPtr curve_ptr = curve.ConstPointer(); using (SimpleArrayCurvePointer rc = new SimpleArrayCurvePointer()) { IntPtr rc_ptr = rc.NonConstPointer(); return UnsafeNativeMethods.RHC_RhinoProjectCurveToBrep(brep_ptr, curve_ptr, direction, tolerance, rc_ptr) ? rc.ToNonConstArray() : new Curve[0]; } }
/// <summary> /// Pulls this curve to a brep face and returns the result of that operation. /// </summary> /// <param name="face">A brep face.</param> /// <param name="tolerance">A tolerance value.</param> /// <returns>An array containing the resulting curves after pulling. This array could be empty.</returns> /// <exception cref="ArgumentNullException">If face is null.</exception> public Curve[] PullToBrepFace(BrepFace face, double tolerance) { if (face == null) throw new ArgumentNullException("face"); IntPtr pConstCurve = ConstPointer(); IntPtr pConstBrepFace = face.ConstPointer(); using (Runtime.InteropWrappers.SimpleArrayCurvePointer curves = new SimpleArrayCurvePointer()) { IntPtr pCurves = curves.NonConstPointer(); UnsafeNativeMethods.RHC_RhinoPullCurveToFace(pConstCurve, pConstBrepFace, pCurves, tolerance); return curves.ToNonConstArray(); } }
/// <summary> /// Projects a collection of Curves onto a collection of Breps along a given direction. /// </summary> /// <param name="curves">Curves to project.</param> /// <param name="breps">Breps to project onto.</param> /// <param name="direction">Direction of projection.</param> /// <param name="tolerance">Tolerance to use for projection.</param> /// <param name="curveIndices">Index of which curve in the input list was the source for a curve in the return array.</param> /// <param name="brepIndices">Index of which brep was used to generate a curve in the return array.</param> /// <returns>An array of projected curves. Array is empty if the projection set is empty.</returns> public static Curve[] ProjectToBrep(IEnumerable<Curve> curves, IEnumerable<Brep> breps, Vector3d direction, double tolerance, out int[] curveIndices, out int[] brepIndices) { curveIndices = null; brepIndices = null; foreach (Curve crv in curves) { if (crv == null) { throw new ArgumentNullException("curves"); } } foreach (Brep brp in breps) { if (brp == null) { throw new ArgumentNullException("breps"); } } SimpleArrayCurvePointer crv_array = new SimpleArrayCurvePointer(curves); Runtime.InteropWrappers.SimpleArrayBrepPointer brp_array = new Runtime.InteropWrappers.SimpleArrayBrepPointer(); foreach (Brep brp in breps) { brp_array.Add(brp, true); } IntPtr ptr_crv_array = crv_array.ConstPointer(); IntPtr ptr_brp_array = brp_array.ConstPointer(); SimpleArrayInt brp_top = new SimpleArrayInt(); SimpleArrayInt crv_top = new SimpleArrayInt(); SimpleArrayCurvePointer rc = new SimpleArrayCurvePointer(); IntPtr ptr_rc = rc.NonConstPointer(); if (UnsafeNativeMethods.RHC_RhinoProjectCurveToBrepEx(ptr_brp_array, ptr_crv_array, direction, tolerance, ptr_rc, brp_top.m_ptr, crv_top.m_ptr)) { brepIndices = brp_top.ToArray(); curveIndices = crv_top.ToArray(); return rc.ToNonConstArray(); } return new Curve[0]; }
/// <summary> /// Creates a tangent arc between two curves and trims or extends the curves to the arc. /// </summary> /// <param name="curve0">The first curve to fillet.</param> /// <param name="point0"> /// A point on the first curve that is near the end where the fillet will /// be created. /// </param> /// <param name="curve1">The second curve to fillet.</param> /// <param name="point1"> /// A point on the second curve that is near the end where the fillet will /// be created. /// </param> /// <param name="radius">The radius of the fillet.</param> /// <param name="join">Join the output curves.</param> /// <param name="trim"> /// Trim copies of the input curves to the output fillet curve. /// </param> /// <param name="arcExtension"> /// Applies when arcs are filleted but need to be extended to meet the /// fillet curve or chamfer line. If true, then the arc is extended /// maintaining its validity. If false, then the arc is extended with a /// line segment, which is joined to the arc converting it to a polycurve. /// </param> /// <param name="tolerance"> /// The tolerance, generally the document's absolute tolerance. /// </param> /// <param name="angleTolerance"></param> /// <returns> /// The results of the fillet operation. The number of output curves depends /// on the input curves and the values of the parameters that were used /// during the fillet operation. In most cases, the output array will contain /// either one or three curves, although two curves can be returned if the /// radius is zero and join = false. /// For example, if both join and trim = true, then the output curve /// will be a polycurve containing the fillet curve joined with trimmed copies /// of the input curves. If join = false and trim = true, then three curves, /// the fillet curve and trimmed copies of the input curves, will be returned. /// If both join and trim = false, then just the fillet curve is returned. /// </returns> /// <example> /// <code source='examples\vbnet\ex_filletcurves.vb' lang='vbnet'/> /// <code source='examples\cs\ex_filletcurves.cs' lang='cs'/> /// <code source='examples\py\ex_filletcurves.py' lang='py'/> /// </example> public static Curve[] CreateFilletCurves( Curve curve0, Point3d point0, Curve curve1, Point3d point1, double radius, bool join, bool trim, bool arcExtension, double tolerance, double angleTolerance) { IntPtr const_ptr_curve0 = curve0.ConstPointer(); IntPtr const_ptr_curve1 = curve1.ConstPointer(); using (var output_array = new SimpleArrayCurvePointer()) { IntPtr ptr_output_array = output_array.NonConstPointer(); UnsafeNativeMethods.RHC_RhFilletCurve(const_ptr_curve0, point0, const_ptr_curve1, point1, radius, join, trim, arcExtension, tolerance, angleTolerance, ptr_output_array); return output_array.ToNonConstArray(); } }