This is page 8 of 8. Use http://codebase.md/jingcheng-chen/rhinomcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .github
│ └── workflows
│ ├── mcp-server-publish.yml
│ └── rhino-plugin-publish.yml
├── .gitignore
├── assets
│ ├── claude_enable_instruction.jpg
│ ├── cursor_enable_instruction.jpg
│ ├── cursor_usage_instruction.jpg
│ ├── demo1.jpg
│ ├── demo2.jpg
│ ├── rhino_plugin_instruction.jpg
│ └── rhinomcp_logo.svg
├── demo_chats
│ ├── create_6x6x6_boxes.txt
│ └── create_rhinoceros_lego_blocks.txt
├── LICENSE
├── README.md
├── rhino_mcp_plugin
│ ├── .gitignore
│ ├── Commands
│ │ ├── MCPStartCommand.cs
│ │ ├── MCPStopCommand.cs
│ │ └── MCPVersionCommand.cs
│ ├── EmbeddedResources
│ │ └── plugin-utility.ico
│ ├── Functions
│ │ ├── _utils.cs
│ │ ├── CreateLayer.cs
│ │ ├── CreateObject.cs
│ │ ├── CreateObjects.cs
│ │ ├── DeleteLayer.cs
│ │ ├── DeleteObject.cs
│ │ ├── ExecuteRhinoscript.cs
│ │ ├── GetDocumentInfo.cs
│ │ ├── GetObjectInfo.cs
│ │ ├── GetOrSetCurrentLayer.cs
│ │ ├── GetSelectedObjectsInfo.cs
│ │ ├── ModifyObject.cs
│ │ ├── ModifyObjects.cs
│ │ └── SelectObjects.cs
│ ├── manifest.yml
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── launchSettings.json
│ ├── rhinomcp.csproj
│ ├── rhinomcp.sln
│ ├── RhinoMCPPlugin.cs
│ ├── RhinoMCPServer.cs
│ ├── RhinoMCPServerController.cs
│ └── Serializers
│ └── Serializer.cs
└── rhino_mcp_server
├── .gitignore
├── dev.sh
├── main.py
├── pyproject.toml
├── README.md
├── src
│ └── rhinomcp
│ ├── __init__.py
│ ├── prompts
│ │ └── assert_general_strategy.py
│ ├── server.py
│ ├── static
│ │ └── rhinoscriptsyntax.py
│ └── tools
│ ├── create_layer.py
│ ├── create_object.py
│ ├── create_objects.py
│ ├── delete_layer.py
│ ├── delete_object.py
│ ├── execute_rhinoscript_python_code.py
│ ├── get_document_info.py
│ ├── get_object_info.py
│ ├── get_or_set_current_layer.py
│ ├── get_rhinoscript_python_code_guide.py
│ ├── get_rhinoscript_python_function_names.py
│ ├── get_selected_objects_info.py
│ ├── modify_object.py
│ ├── modify_objects.py
│ └── select_objects.py
├── static
│ ├── application.py
│ ├── block.py
│ ├── compat.py
│ ├── curve.py
│ ├── dimension.py
│ ├── document.py
│ ├── geometry.py
│ ├── grips.py
│ ├── group.py
│ ├── hatch.py
│ ├── layer.py
│ ├── light.py
│ ├── line.py
│ ├── linetype.py
│ ├── material.py
│ ├── mesh.py
│ ├── object.py
│ ├── plane.py
│ ├── pointvector.py
│ ├── selection.py
│ ├── surface.py
│ ├── toolbar.py
│ ├── transformation.py
│ ├── userdata.py
│ ├── userinterface.py
│ ├── utility.py
│ └── view.py
└── uv.lock
```
# Files
--------------------------------------------------------------------------------
/rhino_mcp_server/static/curve.py:
--------------------------------------------------------------------------------
```python
1 | import math
2 |
3 | import System
4 |
5 | import Rhino
6 |
7 | import scriptcontext
8 |
9 | import rhinocompat as compat
10 | from rhinoscript import utility as rhutil
11 |
12 |
13 | def AddArc(plane, radius, angle_degrees):
14 | """Adds an arc curve to the document
15 | Parameters:
16 | plane (str): plane on which the arc will lie. The origin of the plane will be
17 | the center point of the arc. x-axis of the plane defines the 0 angle
18 | direction.
19 | radius(number): radius of the arc
20 | angle_degrees (number): interval of arc in degrees
21 | Returns:
22 | guid: id of the new curve object
23 | Example:
24 | import rhinoscriptsyntax as rs
25 | plane = rs.WorldXYPlane()
26 | plane = rs.RotatePlane(plane, 45.0, [0,0,1])
27 | rs.AddArc( plane, 5.0, 45.0 )
28 | See Also:
29 | AddArc3Pt
30 | ArcAngle
31 | ArcCenterPoint
32 | ArcMidPoint
33 | ArcRadius
34 | IsArc
35 | """
36 | plane = rhutil.coerceplane(plane, True)
37 | radians = math.radians(angle_degrees)
38 | arc = Rhino.Geometry.Arc(plane, radius, radians)
39 | rc = scriptcontext.doc.Objects.AddArc(arc)
40 | if rc==System.Guid.Empty: raise Exception("Unable to add arc to document")
41 | scriptcontext.doc.Views.Redraw()
42 | return rc
43 |
44 |
45 | def AddArc3Pt(start, end, point_on_arc):
46 | """Adds a 3-point arc curve to the document
47 | Parameters:
48 | start, end (point|guid): endpoints of the arc
49 | point_on_arc (point|guid): a point on the arc
50 | Returns:
51 | guid: id of the new curve object
52 | Example:
53 | import rhinoscriptsyntax as rs
54 | start = rs.GetPoint("Start of arc")
55 | if start is not None:
56 | end = rs.GetPoint("End of arc")
57 | if end is not None:
58 | pton = rs.GetPoint("Point on arc")
59 | if pton is not None:
60 | rs.AddArc3Pt(start, end, pton)
61 | See Also:
62 | AddArc
63 | ArcAngle
64 | ArcCenterPoint
65 | ArcMidPoint
66 | ArcRadius
67 | IsArc
68 | """
69 | start = rhutil.coerce3dpoint(start, True)
70 | end = rhutil.coerce3dpoint(end, True)
71 | pton = rhutil.coerce3dpoint(point_on_arc, True)
72 | arc = Rhino.Geometry.Arc(start, pton, end)
73 | rc = scriptcontext.doc.Objects.AddArc(arc)
74 | if rc==System.Guid.Empty: raise Exception("Unable to add arc to document")
75 | scriptcontext.doc.Views.Redraw()
76 | return rc
77 |
78 |
79 | def AddArcPtTanPt(start, direction, end):
80 | """Adds an arc curve, created from a start point, a start direction, and an
81 | end point, to the document
82 | Parameters:
83 | start (point): the starting point of the arc
84 | direction (vector): the arc direction at start
85 | end (point): the ending point of the arc
86 | Returns:
87 | guid: id of the new curve object
88 | Example:
89 | import rhinoscriptsyntax as rs
90 | pick = rs.GetCurveObject("Select curve to extend")
91 | point = rs.GetPoint("End of extension")
92 | domain = rs.CurveDomain(pick[0])
93 | if abs(pick[4]-domain[0]) < abs(pick[4]-domain[1]):
94 | origin = rs.CurveStartPoint(pick[0])
95 | tangent = rs.VectorReverse(rs.CurveTangent(pick[0], domain[0]))
96 | else:
97 | origin = rs.CurveEndPoint(pick[0])
98 | tangent = rs.CurveTangent(pick[0], domain[1])
99 | rs.AddArcPtTanPt(origin, tangent, point)
100 | See Also:
101 | AddArc
102 | AddArc3Pt
103 | IsArc
104 | """
105 | start = rhutil.coerce3dpoint(start, True)
106 | direction = rhutil.coerce3dvector(direction, True)
107 | end = rhutil.coerce3dpoint(end, True)
108 | arc = Rhino.Geometry.Arc(start, direction, end)
109 | rc = scriptcontext.doc.Objects.AddArc(arc)
110 | if rc==System.Guid.Empty: raise Exception("Unable to add arc to document")
111 | scriptcontext.doc.Views.Redraw()
112 | return rc
113 |
114 |
115 | def AddBlendCurve(curves, parameters, reverses, continuities):
116 | """Makes a curve blend between two curves
117 | Parameters:
118 | curves ([guid|curve, guid|curve]): list of two curves
119 | parameters ([number, number]): list of two curve parameters defining the blend end points
120 | reverses ([bool, bool]): list of two boolean values specifying to use the natural or opposite direction of the curve
121 | continuities ([number, number]): list of two numbers specifying continuity at end points
122 | 0 = position
123 | 1 = tangency
124 | 2 = curvature
125 | Returns:
126 | guid: identifier of new curve on success
127 | Example:
128 | import rhinoscriptsyntax as rs
129 | curve0 = rs.AddLine((0,0,0), (0,9,0))
130 | curve1 = rs.AddLine((1,10,0), (10,10,0))
131 | curves = curve0, curve1
132 | domain_crv0 = rs.CurveDomain(curve0)
133 | domain_crv1 = rs.CurveDomain(curve1)
134 | params = domain_crv0[1], domain_crv1[0]
135 | revs = False, True
136 | cont = 2,2
137 | rs.AddBlendCurve( curves, params, revs, cont )
138 | See Also:
139 | AddFilletCurve
140 | """
141 | crv0 = rhutil.coercecurve(curves[0], -1, True)
142 | crv1 = rhutil.coercecurve(curves[1], -1, True)
143 | c0 = System.Enum.ToObject(Rhino.Geometry.BlendContinuity, continuities[0])
144 | c1 = System.Enum.ToObject(Rhino.Geometry.BlendContinuity, continuities[1])
145 | curve = Rhino.Geometry.Curve.CreateBlendCurve(crv0, parameters[0], reverses[0], c0, crv1, parameters[1], reverses[1], c1)
146 | rc = scriptcontext.doc.Objects.AddCurve(curve)
147 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
148 | scriptcontext.doc.Views.Redraw()
149 | return rc
150 |
151 |
152 | def AddCircle(plane_or_center, radius):
153 | """Adds a circle curve to the document
154 | Parameters:
155 | plane_or_center (point|plane): plane on which the circle will lie. If a point is
156 | passed, this will be the center of the circle on the active
157 | construction plane
158 | radius (number): the radius of the circle
159 | Returns:
160 | guid: id of the new curve object
161 | Example:
162 | import rhinoscriptsyntax as rs
163 | plane = rs.WorldXYPlane()
164 | rs.AddCircle( plane, 5.0 )
165 | See Also:
166 | AddCircle3Pt
167 | CircleCenterPoint
168 | CircleCircumference
169 | CircleRadius
170 | IsCircle
171 | """
172 | rc = None
173 | plane = rhutil.coerceplane(plane_or_center, False)
174 | if plane:
175 | circle = Rhino.Geometry.Circle(plane, radius)
176 | rc = scriptcontext.doc.Objects.AddCircle(circle)
177 | else:
178 | center = rhutil.coerce3dpoint(plane_or_center, True)
179 | view = scriptcontext.doc.Views.ActiveView
180 | plane = view.ActiveViewport.ConstructionPlane()
181 | plane.Origin = center
182 | circle = Rhino.Geometry.Circle(plane, radius)
183 | rc = scriptcontext.doc.Objects.AddCircle(circle)
184 | if rc==System.Guid.Empty: raise Exception("Unable to add circle to document")
185 | scriptcontext.doc.Views.Redraw()
186 | return rc
187 |
188 |
189 | def AddCircle3Pt(first, second, third):
190 | """Adds a 3-point circle curve to the document
191 | Parameters:
192 | first, second, third (point|guid): points on the circle
193 | Returns:
194 | guid: id of the new curve object
195 | Example:
196 | import rhinoscriptsyntax as rs
197 | point1 = rs.GetPoint("First point on circle")
198 | if point1:
199 | point2 = rs.GetPoint("Second point on circle")
200 | if point2:
201 | point3 = rs.GetPoint("Third point on circle")
202 | if point3:
203 | rs.AddCircle3Pt(point1, point2, point3)
204 | See Also:
205 | AddCircle
206 | CircleCenterPoint
207 | CircleCircumference
208 | CircleRadius
209 | IsCircle
210 | """
211 | start = rhutil.coerce3dpoint(first, True)
212 | end = rhutil.coerce3dpoint(second, True)
213 | third = rhutil.coerce3dpoint(third, True)
214 | circle = Rhino.Geometry.Circle(start, end, third)
215 | rc = scriptcontext.doc.Objects.AddCircle(circle)
216 | if rc==System.Guid.Empty: raise Exception("Unable to add circle to document")
217 | scriptcontext.doc.Views.Redraw()
218 | return rc
219 |
220 |
221 | def AddCurve(points, degree=3):
222 | """Adds a control points curve object to the document
223 | Parameters:
224 | points ([point|guid, ...]) a list of points
225 | degree (number): degree of the curve
226 | Returns:
227 | guid: id of the new curve object
228 | Example:
229 | import rhinoscriptsyntax as rs
230 | points = rs.GetPoints(True, message1="Pick curve point")
231 | if points: rs.AddCurve(points)
232 | See Also:
233 | AddInterpCurve
234 | IsCurve
235 | """
236 | points = rhutil.coerce3dpointlist(points, True)
237 | curve = Rhino.Geometry.Curve.CreateControlPointCurve(points, degree)
238 | if not curve: raise Exception("unable to create control point curve from given points")
239 | rc = scriptcontext.doc.Objects.AddCurve(curve)
240 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
241 | scriptcontext.doc.Views.Redraw()
242 | return rc
243 |
244 |
245 | def AddEllipse(plane, radiusX, radiusY):
246 | """Adds an elliptical curve to the document
247 | Parameters:
248 | plane (plane) the plane on which the ellipse will lie. The origin of
249 | the plane will be the center of the ellipse
250 | radiusX, radiusY (number): radius in the X and Y axis directions
251 | Returns:
252 | guid: id of the new curve object if successful
253 | Example:
254 | import rhinoscriptsyntax as rs
255 | plane = rs.WorldXYPlane()
256 | rs.AddEllipse( plane, 5.0, 10.0 )
257 | See Also:
258 | AddEllipse3Pt
259 | IsEllipse
260 | EllipseCenterPoint
261 | EllipseQuadPoints
262 | """
263 | plane = rhutil.coerceplane(plane, True)
264 | ellipse = Rhino.Geometry.Ellipse(plane, radiusX, radiusY)
265 | rc = scriptcontext.doc.Objects.AddEllipse(ellipse)
266 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
267 | scriptcontext.doc.Views.Redraw()
268 | return rc
269 |
270 |
271 | def AddEllipse3Pt(center, second, third):
272 | """Adds a 3-point elliptical curve to the document
273 | Parameters:
274 | center (point|guid): center point of the ellipse
275 | second (point|guid): end point of the x axis
276 | third (point|guid): end point of the y axis
277 | Returns:
278 | guid: id of the new curve object if successful
279 | Example:
280 | import rhinoscriptsyntax as rs
281 | center = (0,0,0)
282 | second = (5,0,0)
283 | third = (0,10,0)
284 | rs.AddEllipse3Pt( center, second, third )
285 | See Also:
286 | AddEllipse
287 | IsEllipse
288 | EllipseCenterPoint
289 | EllipseQuadPoints
290 | """
291 | center = rhutil.coerce3dpoint(center, True)
292 | second = rhutil.coerce3dpoint(second, True)
293 | third = rhutil.coerce3dpoint(third, True)
294 | ellipse = Rhino.Geometry.Ellipse(center, second, third)
295 | rc = scriptcontext.doc.Objects.AddEllipse(ellipse)
296 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
297 | scriptcontext.doc.Views.Redraw()
298 | return rc
299 |
300 |
301 | def AddFilletCurve(curve0id, curve1id, radius=1.0, base_point0=None, base_point1=None):
302 | """Adds a fillet curve between two curve objects
303 | Parameters:
304 | curve0id (guid): identifier of the first curve object
305 | curve1id (guid): identifier of the second curve object
306 | radius (number, optional): fillet radius
307 | base_point0 (point|guid, optional): base point of the first curve. If omitted,
308 | starting point of the curve is used
309 | base_point1 (point|guid, optional): base point of the second curve. If omitted,
310 | starting point of the curve is used
311 | Returns:
312 | guid: id of the new curve object if successful
313 | Example:
314 | import rhinoscriptsyntax as rs
315 | curve0 = rs.AddLine([0,0,0], [5,1,0])
316 | curve1 = rs.AddLine([0,0,0], [1,5,0])
317 | rs.AddFilletCurve( curve0, curve1 )
318 | See Also:
319 | CurveFilletPoints
320 | """
321 | if base_point0: base_point0 = rhutil.coerce3dpoint(base_point0, True)
322 | else: base_point0 = Rhino.Geometry.Point3d.Unset
323 | if base_point1: base_point1 = rhutil.coerce3dpoint(base_point1, True)
324 | else: base_point1 = Rhino.Geometry.Point3d.Unset
325 | curve0 = rhutil.coercecurve(curve0id, -1, True)
326 | curve1 = rhutil.coercecurve(curve1id, -1, True)
327 | crv0_t = 0.0
328 | if base_point0==Rhino.Geometry.Point3d.Unset:
329 | crv0_t = curve0.Domain.Min
330 | else:
331 | rc, t = curve0.ClosestPoint(base_point0, 0.0)
332 | if not rc: raise Exception("ClosestPoint failed")
333 | crv0_t = t
334 | crv1_t = 0.0
335 | if base_point1==Rhino.Geometry.Point3d.Unset:
336 | crv1_t = curve1.Domain.Min
337 | else:
338 | rc, t = curve1.ClosestPoint(base_point1, 0.0)
339 | if not rc: raise Exception("ClosestPoint failed")
340 | crv1_t = t
341 | arc = Rhino.Geometry.Curve.CreateFillet(curve0, curve1, radius, crv0_t, crv1_t)
342 | rc = scriptcontext.doc.Objects.AddArc(arc)
343 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
344 | scriptcontext.doc.Views.Redraw()
345 | return rc
346 |
347 |
348 | def AddInterpCrvOnSrf(surface_id, points):
349 | """Adds an interpolated curve object that lies on a specified
350 | surface. Note, this function will not create periodic curves,
351 | but it will create closed curves.
352 | Parameters:
353 | surface_id (guid): identifier of the surface to create the curve on
354 | points ([point|guid, point|guid, ...])list of 3D points that lie on the specified surface.
355 | The list must contain at least 2 points
356 | Returns:
357 | guid: id of the new curve object if successful
358 | Example:
359 | import rhinoscriptsyntax as rs
360 | surface_id = rs.GetObject("Select surface to draw curve on", rs.filter.surface)
361 | if surface_id:
362 | point1 = rs.GetPointOnSurface( surface_id, "First point on surface")
363 | if point1:
364 | point2 = rs.GetPointOnSurface( surface_id, "Second point on surface")
365 | if point2:
366 | rs.AddInterpCrvOnSrf( surface_id, [point1, point2])
367 | See Also:
368 | AddCurve
369 | AddInterpCurve
370 | AddInterpCrvOnSrfUV
371 | """
372 | surface = rhutil.coercesurface(surface_id, True)
373 | points = rhutil.coerce3dpointlist(points, True)
374 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
375 | curve = surface.InterpolatedCurveOnSurface(points, tolerance)
376 | if not curve: raise Exception("unable to create InterpolatedCurveOnSurface")
377 | rc = scriptcontext.doc.Objects.AddCurve(curve)
378 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
379 | scriptcontext.doc.Views.Redraw()
380 | return rc
381 |
382 |
383 | def AddInterpCrvOnSrfUV(surface_id, points):
384 | """Adds an interpolated curve object based on surface parameters,
385 | that lies on a specified surface. Note, this function will not
386 | create periodic curves, but it will create closed curves.
387 | Parameters:
388 | surface_id (guid): identifier of the surface to create the curve on
389 | points ([[number, number}, [number,number], ...]): a list of 2D surface parameters. The list must contain
390 | at least 2 sets of parameters
391 | Returns:
392 | guid: id of the new curve object if successful
393 | Example:
394 | import rhinoscriptsyntax as rs
395 | surface_id = rs.GetObject("Select surface to draw curve on", rs.filter.surface)
396 | if surface_id:
397 | domainU = rs.SurfaceDomain( surface_id, 0)
398 | u0 = domainU[0]/2
399 | u1 = domainU[1]/2
400 | domainV = rs.SurfaceDomain( surface_id, 1)
401 | v0 = domainV[0]/2
402 | v1 = domainV[1]/2
403 | rs.AddInterpCrvOnSrfUV( surface_id, [[u0,v0],[u1,v1]])
404 | See Also:
405 | AddCurve
406 | AddInterpCurve
407 | AddInterpCrvOnSrf
408 | """
409 | surface = rhutil.coercesurface(surface_id, True)
410 | points = rhutil.coerce2dpointlist(points)
411 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
412 | curve = surface.InterpolatedCurveOnSurfaceUV(points, tolerance)
413 | if not curve: raise Exception("unable to create InterpolatedCurveOnSurfaceUV")
414 | rc = scriptcontext.doc.Objects.AddCurve(curve)
415 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
416 | scriptcontext.doc.Views.Redraw()
417 | return rc
418 |
419 |
420 | def AddInterpCurve(points, degree=3, knotstyle=0, start_tangent=None, end_tangent=None):
421 | """Adds an interpolated curve object to the document. Options exist to make
422 | a periodic curve or to specify the tangent at the endpoints. The resulting
423 | curve is a non-rational NURBS curve of the specified degree.
424 | Parameters:
425 | points (point|guid, point|guid, ...]): a list containing 3D points to interpolate. For periodic curves,
426 | if the final point is a duplicate of the initial point, it is
427 | ignored. The number of control points must be >= (degree+1).
428 | degree (number, optional): The degree of the curve (must be >=1).
429 | Periodic curves must have a degree >= 2. For knotstyle = 1 or 2,
430 | the degree must be 3. For knotstyle = 4 or 5, the degree must be odd
431 | knotstyle(opt):
432 | 0 Uniform knots. Parameter spacing between consecutive knots is 1.0.
433 | 1 Chord length spacing. Requires degree = 3 with arrCV1 and arrCVn1 specified.
434 | 2 Sqrt (chord length). Requires degree = 3 with arrCV1 and arrCVn1 specified.
435 | 3 Periodic with uniform spacing.
436 | 4 Periodic with chord length spacing. Requires an odd degree value.
437 | 5 Periodic with sqrt (chord length) spacing. Requires an odd degree value.
438 | start_tangent (vector, optional): a vector that specifies a tangency condition at the
439 | beginning of the curve. If the curve is periodic, this argument must be omitted.
440 | end_tangent (vector, optional): 3d vector that specifies a tangency condition at the
441 | end of the curve. If the curve is periodic, this argument must be omitted.
442 | Returns:
443 | guid: id of the new curve object if successful
444 | Example:
445 | import rhinoscriptsyntax as rs
446 | points = (0,0,0), (1,1,0), (2,0,0), (3,1,0), (4,0,0), (5,1,0)
447 | rs.AddInterpCurve(points)
448 | See Also:
449 | AddCurve
450 | CurvePointCount
451 | IsCurve
452 | """
453 | points = rhutil.coerce3dpointlist(points, True)
454 | if not start_tangent: start_tangent = Rhino.Geometry.Vector3d.Unset
455 | start_tangent = rhutil.coerce3dvector(start_tangent, True)
456 | if not end_tangent: end_tangent = Rhino.Geometry.Vector3d.Unset
457 | end_tangent = rhutil.coerce3dvector(end_tangent, True)
458 | knotstyle = System.Enum.ToObject(Rhino.Geometry.CurveKnotStyle, knotstyle)
459 | curve = Rhino.Geometry.Curve.CreateInterpolatedCurve(points, degree, knotstyle, start_tangent, end_tangent)
460 | if not curve: raise Exception("unable to CreateInterpolatedCurve")
461 | rc = scriptcontext.doc.Objects.AddCurve(curve)
462 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
463 | scriptcontext.doc.Views.Redraw()
464 | return rc
465 |
466 |
467 | def AddLine(start, end):
468 | """Adds a line curve to the current model.
469 | Parameters:
470 | start, end (point|guid) end points of the line
471 | Returns:
472 | guid: id of the new curve object
473 | Example:
474 | import rhinoscriptsyntax as rs
475 | start = rs.GetPoint("Start of line")
476 | if start:
477 | end = rs.GetPoint("End of line")
478 | if end: rs.AddLine(start, end)
479 | See Also:
480 | CurveEndPoint
481 | CurveStartPoint
482 | IsLine
483 | """
484 | start = rhutil.coerce3dpoint(start, True)
485 | end = rhutil.coerce3dpoint(end, True)
486 | rc = scriptcontext.doc.Objects.AddLine(start, end)
487 | if rc==System.Guid.Empty: raise Exception("Unable to add line to document")
488 | scriptcontext.doc.Views.Redraw()
489 | return rc
490 |
491 |
492 | def AddNurbsCurve(points, knots, degree, weights=None):
493 | """Adds a NURBS curve object to the document
494 | Parameters:
495 | points ([guid|point, guid|point, ...]): a list containing 3D control points
496 | knots ([number, number, ...]): Knot values for the curve. The number of elements in knots must
497 | equal the number of elements in points plus degree minus 1
498 | degree (number): degree of the curve. must be greater than of equal to 1
499 | weights([number, number, ...], optional) weight values for the curve. Number of elements should
500 | equal the number of elements in points. Values must be greater than 0
501 | Returns:
502 | guid: the identifier of the new object if successful, otherwise None
503 | Example:
504 | import rhinoscriptsyntax as rs
505 | curve_id = rs.GetObject("Pick a curve", rs.filter.curve)
506 | if curve_id:
507 | points = rs.CurvePoints(curve_id)
508 | knots = rs.CurveKnots(curve_id)
509 | degree = rs.CurveDegree(curve_id)
510 | newcurve = rs.AddNurbsCurve( points, knots, degree)
511 | if newcurve: rs.SelectObject(newcurve)
512 | See Also:
513 | CurveDegree
514 | CurveKnots
515 | CurvePoints
516 | """
517 | points = rhutil.coerce3dpointlist(points, True)
518 | cvcount = len(points)
519 | knotcount = cvcount + degree - 1
520 | if len(knots)!=knotcount:
521 | raise Exception("Number of elements in knots must equal the number of elements in points plus degree minus 1")
522 | if weights and len(weights)!=cvcount:
523 | raise Exception("Number of elements in weights should equal the number of elements in points")
524 | rational = (weights!=None)
525 |
526 | nc = Rhino.Geometry.NurbsCurve(3,rational,degree+1,cvcount)
527 | if rational:
528 | for i in compat.RANGE(cvcount):
529 | nc.Points.SetPoint(i, points[i], weights[i])
530 | else:
531 | for i in compat.RANGE(cvcount):
532 | nc.Points.SetPoint(i, points[i])
533 | for i in compat.RANGE(knotcount): nc.Knots[i] = knots[i]
534 | rc = scriptcontext.doc.Objects.AddCurve(nc)
535 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
536 | scriptcontext.doc.Views.Redraw()
537 | return rc
538 |
539 |
540 | def AddPolyline(points, replace_id=None):
541 | """Adds a polyline curve to the current model
542 | Parameters:
543 | points ([guid|point, guid|point, ...]): list of 3D points. Duplicate, consecutive points will be
544 | removed. The list must contain at least two points. If the
545 | list contains less than four points, then the first point and
546 | last point must be different.
547 | replace_id (guid, optional): If set to the id of an existing object, the object
548 | will be replaced by this polyline
549 | Returns:
550 | guid: id of the new curve object if successful
551 | Example:
552 | import rhinoscriptsyntax as rs
553 | points = rs.GetPoints(True)
554 | if points: rs.AddPolyline(points)
555 | See Also:
556 | IsPolyline
557 | """
558 | points = rhutil.coerce3dpointlist(points, True)
559 | if replace_id: replace_id = rhutil.coerceguid(replace_id, True)
560 | rc = System.Guid.Empty
561 | pl = Rhino.Geometry.Polyline(points)
562 | pl.DeleteShortSegments(scriptcontext.doc.ModelAbsoluteTolerance)
563 | if replace_id:
564 | if scriptcontext.doc.Objects.Replace(replace_id, pl):
565 | rc = replace_id
566 | else:
567 | rc = scriptcontext.doc.Objects.AddPolyline(pl)
568 | if rc==System.Guid.Empty: raise Exception("Unable to add polyline to document")
569 | scriptcontext.doc.Views.Redraw()
570 | return rc
571 |
572 |
573 | def AddRectangle(plane, width, height):
574 | """Add a rectangular curve to the document
575 | Parameters:
576 | plane (plane) plane on which the rectangle will lie
577 | width, height (number): width and height of rectangle as measured along the plane's
578 | x and y axes
579 | Returns:
580 | guid: id of new rectangle
581 | Example:
582 | import rhinoscriptsyntax as rs
583 | plane = rs.WorldXYPlane()
584 | plane = rs.RotatePlane(plane, 45.0, [0,0,1])
585 | rs.AddRectangle( plane, 5.0, 15.0 )
586 | See Also:
587 |
588 | """
589 | plane = rhutil.coerceplane(plane, True)
590 | rect = Rhino.Geometry.Rectangle3d(plane, width, height)
591 | poly = rect.ToPolyline()
592 | rc = scriptcontext.doc.Objects.AddPolyline(poly)
593 | if rc==System.Guid.Empty: raise Exception("Unable to add polyline to document")
594 | scriptcontext.doc.Views.Redraw()
595 | return rc
596 |
597 |
598 | def AddSpiral(point0, point1, pitch, turns, radius0, radius1=None):
599 | """Adds a spiral or helical curve to the document
600 | Parameters:
601 | point0 (point|guid): helix axis start point or center of spiral
602 | point1 (point|guid): helix axis end point or point normal on spiral plane
603 | pitch (number): distance between turns. If 0, then a spiral. If > 0 then the
604 | distance between helix "threads"
605 | turns (number): number of turns
606 | radius0 (number): starting radius of spiral
607 | radius1 (number, optional): ending radius of spiral. If omitted, the starting radius is used for the complete spiral.
608 | Returns:
609 | guid: id of new curve on success
610 | Example:
611 | import rhinoscriptsyntax as rs
612 | point0 = (0,0,0)
613 | point1 = (0,0,10)
614 | pitch = 1
615 | turns = 10
616 | radius0 = 5.0
617 | radius1 = 8.0
618 | rs.AddSpiral(point0, point1, pitch, turns, radius0, radius1)
619 | See Also:
620 |
621 | """
622 | if radius1 is None: radius1 = radius0
623 | point0 = rhutil.coerce3dpoint(point0, True)
624 | point1 = rhutil.coerce3dpoint(point1, True)
625 | dir = point1 - point0
626 | plane = Rhino.Geometry.Plane(point0, dir)
627 | point2 = point0 + plane.XAxis
628 | curve = Rhino.Geometry.NurbsCurve.CreateSpiral(point0, dir, point2, pitch, turns, radius0, radius1)
629 | rc = scriptcontext.doc.Objects.AddCurve(curve)
630 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
631 | scriptcontext.doc.Views.Redraw()
632 | return rc
633 |
634 |
635 | def AddSubCrv(curve_id, param0, param1):
636 | """Add a curve object based on a portion, or interval of an existing curve
637 | object. Similar in operation to Rhino's SubCrv command
638 | Parameters:
639 | curve_id (guid): identifier of a closed planar curve object
640 | param0, param1 (number): first and second parameters on the source curve
641 | Returns:
642 | guid: id of the new curve object if successful
643 | Example:
644 | import rhinoscriptsyntax as rs
645 | getresult = rs.GetCurveObject()
646 | if getresult:
647 | curve_id = getresult[0]
648 | point0 = rs.GetPointOnCurve( curve_id )
649 | if point0:
650 | point1 = rs.GetPointOnCurve( curve_id )
651 | if point1:
652 | t0 = rs.CurveClosestPoint( curve_id, point0)
653 | t1 = rs.CurveClosestPoint( curve_id, point1)
654 | rs.AddSubCrv( curve_id, t0, t1 )
655 | See Also:
656 | CurveClosestPoint
657 | GetCurveObject
658 | GetPointOnCurve
659 | """
660 | curve = rhutil.coercecurve(curve_id, -1, True)
661 | trimcurve = curve.Trim(param0, param1)
662 | if not trimcurve: raise Exception("unable to trim curve")
663 | rc = scriptcontext.doc.Objects.AddCurve(trimcurve)
664 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
665 | scriptcontext.doc.Views.Redraw()
666 | return rc
667 |
668 |
669 | def ArcAngle(curve_id, segment_index=-1):
670 | """Returns the angle of an arc curve object.
671 | Parameters:
672 | curve_id (guid): identifier of a curve object
673 | segment_index (number, optional): identifies the curve segment if
674 | curve_id (guid): identifies a polycurve
675 | Returns:
676 | number: The angle in degrees if successful.
677 | Example:
678 | import rhinoscriptsyntax as rs
679 | id = rs.GetObject("Select arc")
680 | if rs.IsArc(id):
681 | angle = rs.ArcAngle(id)
682 | print("Arc angle: {}".format(angle))
683 | See Also:
684 | AddArc3Pt
685 | ArcCenterPoint
686 | ArcMidPoint
687 | ArcRadius
688 | IsArc
689 | """
690 | curve = rhutil.coercecurve(curve_id, segment_index, True)
691 | rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
692 | if not rc: raise Exception("curve is not arc")
693 | return arc.AngleDegrees
694 |
695 |
696 | def ArcCenterPoint(curve_id, segment_index=-1):
697 | """Returns the center point of an arc curve object
698 | Parameters:
699 | curve_id (guid): identifier of a curve object
700 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
701 | Returns:
702 | point: The 3D center point of the arc if successful.
703 | Example:
704 | import rhinoscriptsyntax as rs
705 | id = rs.GetObject("Select arc")
706 | if rs.IsArc(id):
707 | point = rs.ArcCenterPoint(id)
708 | rs.AddPoint(point)
709 | See Also:
710 | AddArc3Pt
711 | ArcAngle
712 | ArcMidPoint
713 | ArcRadius
714 | IsArc
715 | """
716 | curve = rhutil.coercecurve(curve_id, segment_index, True)
717 | rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
718 | if not rc: raise Exception("curve is not arc")
719 | return arc.Center
720 |
721 |
722 | def ArcMidPoint(curve_id, segment_index=-1):
723 | """Returns the mid point of an arc curve object
724 | Parameters:
725 | curve_id (guid): identifier of a curve object
726 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
727 | Returns:
728 | point: The 3D mid point of the arc if successful.
729 | Example:
730 | import rhinoscriptsyntax as rs
731 | id = rs.GetObject("Select arc")
732 | if rs.IsArc(id):
733 | point = rs.ArcMidPoint(id)
734 | rs.AddPoint(point)
735 | See Also:
736 | AddArc3Pt
737 | ArcAngle
738 | ArcCenterPoint
739 | ArcRadius
740 | IsArc
741 | """
742 | curve = rhutil.coercecurve(curve_id, segment_index, True)
743 | rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
744 | if not rc: raise Exception("curve is not arc")
745 | return arc.MidPoint
746 |
747 |
748 | def ArcRadius(curve_id, segment_index=-1):
749 | """Returns the radius of an arc curve object
750 | Parameters:
751 | curve_id (guid): identifier of a curve object
752 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
753 | Returns:
754 | number: The radius of the arc if successful.
755 | Example:
756 | import rhinoscriptsyntax as rs
757 | id = rs.GetObject("Select arc")
758 | if rs.IsArc(id):
759 | radius = rs.ArcRadius(id)
760 | print("Arc radius: {}".format(radius))
761 | See Also:
762 | AddArc3Pt
763 | ArcAngle
764 | ArcCenterPoint
765 | ArcMidPoint
766 | IsArc
767 | """
768 | curve = rhutil.coercecurve(curve_id, segment_index, True)
769 | rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
770 | if not rc: raise Exception("curve is not arc")
771 | return arc.Radius
772 |
773 |
774 | def CircleCenterPoint(curve_id, segment_index=-1, return_plane=False):
775 | """Returns the center point of a circle curve object
776 | Parameters:
777 | curve_id (guid): identifier of a curve object
778 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
779 | return_plane (bool, optional): if True, the circle's plane is returned. If omitted the plane is not returned.
780 | Returns:
781 | point: The 3D center point of the circle if successful.
782 | plane: The plane of the circle if return_plane is True
783 | Example:
784 | import rhinoscriptsyntax as rs
785 | id = rs.GetObject("Select circle")
786 | if rs.IsCircle(id):
787 | point = rs.CircleCenterPoint(id)
788 | rs.AddPoint( point )
789 | See Also:
790 | AddCircle
791 | AddCircle3Pt
792 | CircleCircumference
793 | CircleRadius
794 | IsCircle
795 | """
796 | curve = rhutil.coercecurve(curve_id, segment_index, True)
797 | rc, circle = curve.TryGetCircle(Rhino.RhinoMath.ZeroTolerance)
798 | if not rc: raise Exception("curve is not circle")
799 | if return_plane: return circle.Plane
800 | return circle.Center
801 |
802 |
803 | def CircleCircumference(curve_id, segment_index=-1):
804 | """Returns the circumference of a circle curve object
805 | Parameters:
806 | curve_id (guid): identifier of a curve object
807 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
808 | Returns:
809 | number: The circumference of the circle if successful.
810 | Example:
811 | import rhinoscriptsyntax as rs
812 | id = rs.GetObject("Select circle")
813 | if rs.IsCircle(id):
814 | circumference = rs.CircleCircumference(id)
815 | print("Circle circumference: {}".format(circumference))
816 | See Also:
817 | AddCircle
818 | AddCircle3Pt
819 | CircleCenterPoint
820 | CircleRadius
821 | IsCircle
822 | """
823 | curve = rhutil.coercecurve(curve_id, segment_index, True)
824 | rc, circle = curve.TryGetCircle( Rhino.RhinoMath.ZeroTolerance )
825 | if not rc: raise Exception("curve is not circle")
826 | return circle.Circumference
827 |
828 |
829 | def CircleRadius(curve_id, segment_index=-1):
830 | """Returns the radius of a circle curve object
831 | Parameters:
832 | curve_id (guid): identifier of a curve object
833 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
834 | Returns:
835 | number: The radius of the circle if successful.
836 | Example:
837 | import rhinoscriptsyntax as rs
838 | id = rs.GetObject("Select circle")
839 | if rs.IsCircle(id):
840 | radius = rs.CircleRadius(id)
841 | print("Circle radius: {}".format(radius))
842 | See Also:
843 | AddCircle
844 | AddCircle3Pt
845 | CircleCenterPoint
846 | CircleCircumference
847 | IsCircle
848 | """
849 | curve = rhutil.coercecurve(curve_id, segment_index, True)
850 | rc, circle = curve.TryGetCircle( Rhino.RhinoMath.ZeroTolerance )
851 | if not rc: raise Exception("curve is not circle")
852 | return circle.Radius
853 |
854 |
855 | def CloseCurve(curve_id, tolerance=-1.0):
856 | """Closes an open curve object by making adjustments to the end points so
857 | they meet at a point
858 | Parameters:
859 | curve_id (guid): identifier of a curve object
860 | tolerance (number, optional): maximum allowable distance between start and end
861 | point. If omitted, the current absolute tolerance is used
862 | Returns:
863 | guid: id of the new curve object if successful
864 | Example:
865 | import rhinoscriptsyntax as rs
866 | obj = rs.GetObject("Select curve", rs.filter.curve)
867 | if not rs.IsCurveClosed(obj) and rs.IsCurveClosable(obj):
868 | rs.CloseCurve( obj )
869 | See Also:
870 | IsCurveClosable
871 | IsCurveClosed
872 | """
873 | curve = rhutil.coercecurve(curve_id, -1, True)
874 | if curve.IsClosed: return curve_id
875 | if tolerance<0.0: tolerance = Rhino.RhinoMath.ZeroTolerance
876 | if not curve.MakeClosed(tolerance): return scriptcontext.errorhandler()
877 | rc = scriptcontext.doc.Objects.AddCurve(curve)
878 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
879 | scriptcontext.doc.Views.Redraw()
880 | return rc
881 |
882 |
883 | def ClosedCurveOrientation(curve_id, direction=(0,0,1)):
884 | """Determine the orientation (counter-clockwise or clockwise) of a closed,
885 | planar curve
886 | Parameters:
887 | curve_id (guid): identifier of a curve object
888 | direction (vector, optional): 3d vector that identifies up, or Z axs, direction of
889 | the plane to test against
890 | Returns:
891 | number: 1 if the curve's orientation is counter-clockwise
892 | -1 if the curve's orientation is clockwise
893 | 0 if unable to compute the curve's orientation
894 | Example:
895 | See Also:
896 | """
897 | curve = rhutil.coercecurve(curve_id, -1 ,True)
898 | direction = rhutil.coerce3dvector(direction, True)
899 | if not curve.IsClosed: return 0
900 | orientation = curve.ClosedCurveOrientation(direction)
901 | return int(orientation)
902 |
903 |
904 | def ConvertCurveToPolyline(curve_id, angle_tolerance=5.0, tolerance=0.01, delete_input=False, min_edge_length=0, max_edge_length=0):
905 | """Convert curve to a polyline curve
906 | Parameters:
907 | curve_id (guid): identifier of a curve object
908 | angle_tolerance (number, optional): The maximum angle between curve tangents at line endpoints.
909 | If omitted, the angle tolerance is set to 5.0.
910 | tolerance(number, optional): The distance tolerance at segment midpoints. If omitted, the tolerance is set to 0.01.
911 | delete_input(bool, optional): Delete the curve object specified by curve_id. If omitted, curve_id will not be deleted.
912 | min_edge_length (number, optional): Minimum segment length
913 | max_edge_length (number, optonal): Maximum segment length
914 | Returns:
915 | guid: The new curve if successful.
916 | Example:
917 | import rhinoscriptsyntax as rs
918 | obj = rs.GetObject("Select a curve")
919 | if rs.IsCurve(obj):
920 | polyline = rs.ConvertCurveToPolyline(obj)
921 | if polyline: rs.SelectObject(polyline)
922 | See Also:
923 | IsCurve
924 | """
925 | curve = rhutil.coercecurve(curve_id, -1, True)
926 | if angle_tolerance<=0: angle_tolerance = 5.0
927 | angle_tolerance = Rhino.RhinoMath.ToRadians(angle_tolerance)
928 | if tolerance<=0.0: tolerance = 0.01;
929 | polyline_curve = curve.ToPolyline( 0, 0, angle_tolerance, 0.0, 0.0, tolerance, min_edge_length, max_edge_length, True)
930 | if not polyline_curve: return scriptcontext.errorhandler()
931 | id = System.Guid.Empty
932 | if delete_input:
933 | if scriptcontext.doc.Objects.Replace( curve_id, polyline_curve): id = curve_id
934 | else:
935 | id = scriptcontext.doc.Objects.AddCurve( polyline_curve )
936 | if System.Guid.Empty==id: return scriptcontext.errorhandler()
937 | return id
938 |
939 |
940 | def CurveArcLengthPoint(curve_id, length, from_start=True):
941 | """Returns the point on the curve that is a specified arc length
942 | from the start of the curve.
943 | Parameters:
944 | curve_id (guid): identifier of a curve object
945 | length (number): The arc length from the start of the curve to evaluate.
946 | from_start (bool, optional): If not specified or True, then the arc length point is
947 | calculated from the start of the curve. If False, the arc length
948 | point is calculated from the end of the curve.
949 | Returns:
950 | point: on curve if successful
951 | Example:
952 | import rhinoscriptsyntax as rs
953 | obj = rs.GetObject("Select a curve")
954 | if rs.IsCurve(obj):
955 | length = rs.CurveLength(obj)
956 | point = rs.CurveArcLengthPoint(obj, length/3.0)
957 | rs.AddPoint( point )
958 | See Also:
959 | CurveEndPoint
960 | CurveMidPoint
961 | CurveStartPoint
962 | """
963 | curve = rhutil.coercecurve(curve_id, -1, True)
964 | curve_length = curve.GetLength()
965 | if curve_length>=length:
966 | s = 0.0
967 | if length==0.0: s = 0.0
968 | elif length==curve_length: s = 1.0
969 | else: s = length / curve_length
970 | dupe = curve.Duplicate()
971 | if dupe:
972 | if from_start==False: dupe.Reverse()
973 | rc, t = dupe.NormalizedLengthParameter(s)
974 | if rc: return dupe.PointAt(t)
975 | dupe.Dispose()
976 |
977 |
978 | def CurveArea(curve_id):
979 | """Returns area of closed planar curves. The results are based on the
980 | current drawing units.
981 | Parameters:
982 | curve_id (guid): The identifier of a closed, planar curve object.
983 | Returns:
984 | list[number, number]: List of area information. The list will contain the following information:
985 | Element Description
986 | [0] The area. If more than one curve was specified, the
987 | value will be the cumulative area.
988 | [1] The absolute (+/-) error bound for the area.
989 | Example:
990 | import rhinoscriptsyntax as rs
991 | id = rs.GetObject("Select a curve", rs.filter.curve)
992 | if id:
993 | props = rs.CurveArea(id)
994 | if props:
995 | print("The curve area is: {}".format(props[0]))
996 | See Also:
997 | IsCurve
998 | IsCurveClosed
999 | IsCurvePlanar
1000 | """
1001 | curve = rhutil.coercecurve(curve_id, -1, True)
1002 | tol = scriptcontext.doc.ModelAbsoluteTolerance
1003 | mp = Rhino.Geometry.AreaMassProperties.Compute(curve, tol)
1004 | if mp == None: return None
1005 | return mp.Area, mp.AreaError
1006 |
1007 |
1008 | def CurveAreaCentroid(curve_id):
1009 | """Returns area centroid of closed, planar curves. The results are based
1010 | on the current drawing units.
1011 | Parameters:
1012 | curve_id (guid)The identifier of a closed, planar curve object.
1013 | Returns:
1014 | tuple(point, vector): of area centroid information containing the following information:
1015 | Element Description
1016 | [0] The 3d centroid point. If more than one curve was specified,
1017 | the value will be the cumulative area.
1018 | [1] A 3d vector with the absolute (+/-) error bound for the area
1019 | centroid.
1020 | Example:
1021 | import rhinoscriptsyntax as rs
1022 | id = rs.GetObject("Select a curve", rs.filter.curve)
1023 | if id:
1024 | props = rs.CurveAreaCentroid(id)
1025 | if props:
1026 | print("The curve area centroid is: {}".format(props[0]))
1027 | See Also:
1028 | IsCurve
1029 | IsCurveClosed
1030 | IsCurvePlanar
1031 | """
1032 | curve = rhutil.coercecurve(curve_id, -1, True)
1033 | tol = scriptcontext.doc.ModelAbsoluteTolerance
1034 | mp = Rhino.Geometry.AreaMassProperties.Compute(curve, tol)
1035 | if mp == None: return None
1036 | return mp.Centroid, mp.CentroidError
1037 |
1038 |
1039 | def CurveArrows(curve_id, arrow_style=None):
1040 | """Enables or disables a curve object's annotation arrows
1041 | Parameters:
1042 | curve_id (guid): identifier of a curve
1043 | arrow_style (number, optional): the style of annotation arrow to be displayed. If omitted the current type is returned.
1044 | 0 = no arrows
1045 | 1 = display arrow at start of curve
1046 | 2 = display arrow at end of curve
1047 | 3 = display arrow at both start and end of curve
1048 | Returns:
1049 | number: if arrow_style is not specified, the current annotation arrow style
1050 | number: if arrow_style is specified, the previous arrow style
1051 | Example:
1052 | import rhinoscriptsyntax as rs
1053 | obj = rs.GetObject("Select a curve", rs.filter.curve)
1054 | if rs.CurveArrows(obj)!=3: rs.CurveArrows(obj, 3)
1055 | See Also:
1056 | IsCurve
1057 | """
1058 | curve = rhutil.coercecurve(curve_id, -1, True)
1059 | rhobj = rhutil.coercerhinoobject(curve_id, True, True)
1060 | attr = rhobj.Attributes
1061 | rc = attr.ObjectDecoration
1062 | none_obj_decor = compat.ENUM_NONE(Rhino.DocObjects.ObjectDecoration)
1063 | if arrow_style is not None:
1064 | if arrow_style==0:
1065 | attr.ObjectDecoration = none_obj_decor
1066 | elif arrow_style==1:
1067 | attr.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.StartArrowhead
1068 | elif arrow_style==2:
1069 | attr.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.EndArrowhead
1070 | elif arrow_style==3:
1071 | attr.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.BothArrowhead
1072 | id = rhutil.coerceguid(curve_id, True)
1073 | scriptcontext.doc.Objects.ModifyAttributes(id, attr, True)
1074 | scriptcontext.doc.Views.Redraw()
1075 | if rc==none_obj_decor: return 0
1076 | if rc==Rhino.DocObjects.ObjectDecoration.StartArrowhead: return 1
1077 | if rc==Rhino.DocObjects.ObjectDecoration.EndArrowhead: return 2
1078 | if rc==Rhino.DocObjects.ObjectDecoration.BothArrowhead: return 3
1079 |
1080 |
1081 | def CurveBooleanDifference(curve_id_0, curve_id_1, tolerance=None):
1082 | """Calculates the difference between two closed, planar curves and
1083 | adds the results to the document. Note, curves must be coplanar.
1084 | Parameters:
1085 | curve_id_0 (guid): identifier of the first curve object.
1086 | curve_id_1 (guid): identifier of the second curve object.
1087 | tolerance (float, optional): a positive tolerance value, or None for the doc default.
1088 | Returns:
1089 | list(guid, ...): The identifiers of the new objects if successful, None on error.
1090 | Example:
1091 | import rhinoscriptsyntax as rs
1092 | curveA = rs.GetObject("Select first curve", rs.filter.curve)
1093 | curveB = rs.GetObject("Select second curve", rs.filter.curve)
1094 | arrResult = rs.CurveBooleanDifference(curveA, curveB)
1095 | if arrResult:
1096 | rs.DeleteObject( curveA )
1097 | rs.DeleteObject( curveB )
1098 | See Also:
1099 | CurveBooleanIntersection
1100 | CurveBooleanUnion
1101 | """
1102 | curve0 = rhutil.coercecurve(curve_id_0, -1, True)
1103 | curve1 = rhutil.coercecurve(curve_id_1, -1, True)
1104 | if tolerance is None or tolerance<0:
1105 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1106 | out_curves = Rhino.Geometry.Curve.CreateBooleanDifference(curve0, curve1, tolerance)
1107 | curves = []
1108 | if out_curves:
1109 | for curve in out_curves:
1110 | if curve and curve.IsValid:
1111 | rc = scriptcontext.doc.Objects.AddCurve(curve)
1112 | curve.Dispose()
1113 | if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
1114 | curves.append(rc)
1115 | scriptcontext.doc.Views.Redraw()
1116 | return curves
1117 |
1118 |
1119 | def CurveBooleanIntersection(curve_id_0, curve_id_1, tolerance=None):
1120 | """Calculates the intersection of two closed, planar curves and adds
1121 | the results to the document. Note, curves must be coplanar.
1122 | Parameters:
1123 | curve_id_0 (guid): identifier of the first curve object.
1124 | curve_id_1 (guid): identifier of the second curve object.
1125 | tolerance (float, optional): a positive tolerance value, or None for the doc default.
1126 | Returns:
1127 | list(guid, ...): The identifiers of the new objects.
1128 | Example:
1129 | import rhinoscriptsyntax as rs
1130 | curveA = rs.GetObject("Select first curve", rs.filter.curve)
1131 | curveB = rs.GetObject("Select second curve", rs.filter.curve)
1132 | result = rs.CurveBooleanIntersection(curveA, curveB)
1133 | if result:
1134 | rs.DeleteObject( curveA )
1135 | rs.DeleteObject( curveB )
1136 | See Also:
1137 | CurveBooleanDifference
1138 | CurveBooleanUnion
1139 | """
1140 | curve0 = rhutil.coercecurve(curve_id_0, -1, True)
1141 | curve1 = rhutil.coercecurve(curve_id_1, -1, True)
1142 | if tolerance is None or tolerance<0:
1143 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1144 | out_curves = Rhino.Geometry.Curve.CreateBooleanIntersection(curve0, curve1, tolerance)
1145 | curves = []
1146 | if out_curves:
1147 | for curve in out_curves:
1148 | if curve and curve.IsValid:
1149 | rc = scriptcontext.doc.Objects.AddCurve(curve)
1150 | curve.Dispose()
1151 | if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
1152 | curves.append(rc)
1153 | scriptcontext.doc.Views.Redraw()
1154 | return curves
1155 |
1156 |
1157 | def CurveBooleanUnion(curve_id, tolerance=None):
1158 | """Calculate the union of two or more closed, planar curves and
1159 | add the results to the document. Note, curves must be coplanar.
1160 | Parameters:
1161 | curve_id ([guid, guid, ...])list of two or more close planar curves identifiers
1162 | tolerance (float, optional): a positive tolerance value, or None for the doc default.
1163 | Returns:
1164 | list(guid, ...): The identifiers of the new objects.
1165 | Example:
1166 | import rhinoscriptsyntax as rs
1167 | curve_ids = rs.GetObjects("Select curves to union", rs.filter.curve)
1168 | if curve_ids and len(curve_ids)>1:
1169 | result = rs.CurveBooleanUnion(curve_ids)
1170 | if result: rs.DeleteObjects(curve_ids)
1171 | See Also:
1172 | CurveBooleanDifference
1173 | CurveBooleanIntersection
1174 | """
1175 | in_curves = [rhutil.coercecurve(id,-1,True) for id in curve_id]
1176 | if len(in_curves)<2: raise ValueException("curve_id must have at least 2 curves")
1177 | if tolerance is None or tolerance<0:
1178 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1179 | out_curves = Rhino.Geometry.Curve.CreateBooleanUnion(in_curves, tolerance)
1180 | curves = []
1181 | if out_curves:
1182 | for curve in out_curves:
1183 | if curve and curve.IsValid:
1184 | rc = scriptcontext.doc.Objects.AddCurve(curve)
1185 | curve.Dispose()
1186 | if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
1187 | curves.append(rc)
1188 | scriptcontext.doc.Views.Redraw()
1189 | return curves
1190 |
1191 |
1192 | def CurveBrepIntersect(curve_id, brep_id, tolerance=None):
1193 | """Intersects a curve object with a brep object. Note, unlike the
1194 | CurveSurfaceIntersection function, this function works on trimmed surfaces.
1195 | Parameters:
1196 | curve_id (guid): identifier of a curve object
1197 | brep_id (guid): identifier of a brep object
1198 | tolerance (number, optional): distance tolerance at segment midpoints.
1199 | If omitted, the current absolute tolerance is used.
1200 | Returns:
1201 | list(guid, ...): identifiers for the newly created intersection objects if successful.
1202 | None: on error.
1203 | Example:
1204 | import rhinoscriptsyntax as rs
1205 | curve = rs.GetObject("Select a curve", rs.filter.curve)
1206 | if curve:
1207 | brep = rs.GetObject("Select a brep", rs.filter.surface + rs.filter.polysurface)
1208 | if brep: rs.CurveBrepIntersect( curve, brep )
1209 | See Also:
1210 | CurveSurfaceIntersection
1211 | """
1212 | curve = rhutil.coercecurve(curve_id, -1, True)
1213 | brep = rhutil.coercebrep(brep_id, True)
1214 | if tolerance is None or tolerance<0:
1215 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1216 | rc, out_curves, out_points = Rhino.Geometry.Intersect.Intersection.CurveBrep(curve, brep, tolerance)
1217 | if not rc: return scriptcontext.errorhandler()
1218 |
1219 | curves = []
1220 | points = []
1221 | for curve in out_curves:
1222 | if curve and curve.IsValid:
1223 | rc = scriptcontext.doc.Objects.AddCurve(curve)
1224 | curve.Dispose()
1225 | if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
1226 | curves.append(rc)
1227 | for point in out_points:
1228 | if point and point.IsValid:
1229 | rc = scriptcontext.doc.Objects.AddPoint(point)
1230 | points.append(rc)
1231 | if not curves and not points: return None
1232 | scriptcontext.doc.Views.Redraw()
1233 | return curves, points
1234 |
1235 |
1236 | def CurveClosestObject(curve_id, object_ids):
1237 | """Returns the 3D point locations on two objects where they are closest to
1238 | each other. Note, this function provides similar functionality to that of
1239 | Rhino's ClosestPt command.
1240 | Parameters:
1241 | curve_id (guid):identifier of the curve object to test
1242 | object_ids ([guid, ...]) list of identifiers of point cloud, curve, surface, or
1243 | polysurface to test against
1244 | Returns:
1245 | tuple[guid, point, point]: containing the results of the closest point calculation.
1246 | The elements are as follows:
1247 | [0] The identifier of the closest object.
1248 | [1] The 3-D point that is closest to the closest object.
1249 | [2] The 3-D point that is closest to the test curve.
1250 | Example:
1251 | import rhinoscriptsyntax as rs
1252 | filter = rs.filter.curve | rs.filter.pointcloud | rs.filter.surface | rs.filter.polysurface
1253 | objects = rs.GetObjects("Select target objects for closest point", filter)
1254 | if objects:
1255 | curve = rs.GetObject("Select curve")
1256 | if curve:
1257 | results = rs.CurveClosestObject(curve, objects)
1258 | if results:
1259 | print("Curve id: {}".format(results[0]))
1260 | rs.AddPoint( results[1] )
1261 | rs.AddPoint( results[2] )
1262 | See Also:
1263 | CurveClosestPoint
1264 | EvaluateCurve
1265 | IsCurve
1266 | """
1267 | curve = rhutil.coercecurve(curve_id,-1,True)
1268 | geometry = []
1269 | id = rhutil.coerceguid(object_ids, False)
1270 | if id: object_ids = [id]
1271 | for object_id in object_ids:
1272 | rhobj = rhutil.coercerhinoobject(object_id, True, True)
1273 | geometry.append( rhobj.Geometry )
1274 | if not geometry: raise ValueError("object_ids must contain at least one item")
1275 | success, curve_point, geom_point, which_geom = curve.ClosestPoints(geometry, 0.0)
1276 | if success: return object_ids[which_geom], geom_point, curve_point
1277 |
1278 |
1279 | def CurveClosestPoint(curve_id, test_point, segment_index=-1 ):
1280 | """Returns parameter of the point on a curve that is closest to a test point.
1281 | Parameters:
1282 | curve_id (guid): identifier of a curve object
1283 | point (point): sampling point
1284 | segment_index (number, optional): curve segment index if `curve_id` identifies a polycurve
1285 | Returns:
1286 | number: The parameter of the closest point on the curve
1287 | Example:
1288 | import rhinoscriptsyntax as rs
1289 | id = rs.GetObject("Select a curve")
1290 | if id:
1291 | point = rs.GetPointOnCurve(id, "Pick a test point")
1292 | if point:
1293 | param = rs.CurveClosestPoint(id, point)
1294 | print("Curve parameter: {}".format(param))
1295 | See Also:
1296 | EvaluateCurve
1297 | IsCurve
1298 | """
1299 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1300 | point = rhutil.coerce3dpoint(test_point, True)
1301 | rc, t = curve.ClosestPoint(point, 0.0)
1302 | if not rc: raise Exception("ClosestPoint failed")
1303 | return t
1304 |
1305 |
1306 | def CurveContourPoints(curve_id, start_point, end_point, interval=None):
1307 | """Returns the 3D point locations calculated by contouring a curve object.
1308 | Parameters:
1309 | curve_id (guid): identifier of a curve object.
1310 | start_point (point): 3D starting point of a center line.
1311 | end_point (point): 3D ending point of a center line.
1312 | interval (number, optional): The distance between contour curves. If omitted,
1313 | the interval will be equal to the diagonal distance of the object's
1314 | bounding box divided by 50.
1315 | Returns:
1316 | list(point, ....): A list of 3D points, one for each contour
1317 | Example:
1318 | import rhinoscriptsyntax as rs
1319 | obj = rs.GetObject("Select curve", rs.filter.curve)
1320 | start_point = rs.GetPoint("Base point of center line")
1321 | end_point = rs.GetPoint("Endpoint of center line", start_point)
1322 | contour = rs.CurveContourPoints(obj, start_point, end_point)
1323 | if contour: rs.AddPoints(contour)
1324 | See Also:
1325 | AddSrfContourCrvs
1326 | """
1327 | curve = rhutil.coercecurve(curve_id, -1, True)
1328 | start_point = rhutil.coerce3dpoint(start_point, True)
1329 | end_point = rhutil.coerce3dpoint(end_point, True)
1330 | if start_point.DistanceTo(end_point)<Rhino.RhinoMath.ZeroTolerance:
1331 | raise Exception("start and end point are too close to define a line")
1332 | if not interval:
1333 | bbox = curve.GetBoundingBox(True)
1334 | diagonal = bbox.Max - bbox.Min
1335 | interval = diagonal.Length / 50.0
1336 | rc = curve.DivideAsContour( start_point, end_point, interval )
1337 | return list(rc)
1338 |
1339 |
1340 | def CurveCurvature(curve_id, parameter):
1341 | """Returns the curvature of a curve at a parameter. See the Rhino help for
1342 | details on curve curvature
1343 | Parameters:
1344 | curve_id (guid): identifier of the curve
1345 | parameter (number): parameter to evaluate
1346 | Returns:
1347 | tuple[point, vector, point, number, vector]: of curvature information on success
1348 | [0] = point at specified parameter
1349 | [1] = tangent vector
1350 | [2] = center of radius of curvature
1351 | [3] = radius of curvature
1352 | [4] = curvature vector
1353 | None: on failure
1354 | Example:
1355 | import rhinoscriptsyntax as rs
1356 | obj = rs.GetObject("Select a curve")
1357 | if rs.IsCurve(obj):
1358 | point = rs.GetPointOnCurve(obj, "Pick a test point")
1359 | if point:
1360 | param = rs.CurveClosestPoint(obj, point)
1361 | if param:
1362 | data = rs.CurveCurvature(obj, param)
1363 | if data:
1364 | print("Curve curvature evaluation at parameter {}".format(param, ":"))
1365 | print(" 3-D Point: {}".format(data[0]))
1366 | print(" 3-D Tangent: {}".format(data[1]))
1367 | print(" Center of radius of curvature: {}".format(data[2]))
1368 | print(" Radius of curvature: {}".format(data[3]))
1369 | print(" 3-D Curvature: {}".format(data[4]))
1370 | See Also:
1371 | SurfaceCurvature
1372 | """
1373 | curve = rhutil.coercecurve(curve_id, -1, True)
1374 | point = curve.PointAt(parameter)
1375 | tangent = curve.TangentAt(parameter)
1376 | if tangent.IsTiny(0): return scriptcontext.errorhandler()
1377 | cv = curve.CurvatureAt(parameter)
1378 | k = cv.Length
1379 | if k<Rhino.RhinoMath.SqrtEpsilon: return scriptcontext.errorhandler()
1380 | rv = cv / (k*k)
1381 | circle = Rhino.Geometry.Circle(point, tangent, point + 2.0*rv)
1382 | center = point + rv
1383 | radius = circle.Radius
1384 | return point, tangent, center, radius, cv
1385 |
1386 |
1387 | def CurveCurveIntersection(curveA, curveB=None, tolerance=-1):
1388 | """Calculates intersection of two curve objects.
1389 | Parameters:
1390 | curveA (guid): identifier of the first curve object.
1391 | curveB (guid, optional): identifier of the second curve object. If omitted, then a
1392 | self-intersection test will be performed on curveA.
1393 | tolerance (number, optional): absolute tolerance in drawing units. If omitted,
1394 | the document's current absolute tolerance is used.
1395 | Returns:
1396 | list of tuples: containing intersection information if successful.
1397 | The list will contain one or more of the following elements:
1398 | Element Type Description
1399 | [n][0] Number The intersection event type, either Point (1) or Overlap (2).
1400 | [n][1] Point3d If the event type is Point (1), then the intersection point
1401 | on the first curve. If the event type is Overlap (2), then
1402 | intersection start point on the first curve.
1403 | [n][2] Point3d If the event type is Point (1), then the intersection point
1404 | on the first curve. If the event type is Overlap (2), then
1405 | intersection end point on the first curve.
1406 | [n][3] Point3d If the event type is Point (1), then the intersection point
1407 | on the second curve. If the event type is Overlap (2), then
1408 | intersection start point on the second curve.
1409 | [n][4] Point3d If the event type is Point (1), then the intersection point
1410 | on the second curve. If the event type is Overlap (2), then
1411 | intersection end point on the second curve.
1412 | [n][5] Number If the event type is Point (1), then the first curve parameter.
1413 | If the event type is Overlap (2), then the start value of the
1414 | first curve parameter range.
1415 | [n][6] Number If the event type is Point (1), then the first curve parameter.
1416 | If the event type is Overlap (2), then the end value of the
1417 | first curve parameter range.
1418 | [n][7] Number If the event type is Point (1), then the second curve parameter.
1419 | If the event type is Overlap (2), then the start value of the
1420 | second curve parameter range.
1421 | [n][8] Number If the event type is Point (1), then the second curve parameter.
1422 | If the event type is Overlap (2), then the end value of the
1423 | second curve parameter range.
1424 | Example:
1425 | import rhinoscriptsyntax as rs
1426 | def ccx():
1427 | curve1 = rs.GetObject("Select first curve", rs.filter.curve)
1428 | if curve1 is None: return
1429 | curve2 = rs.GetObject("Select second curve", rs.filter.curve)
1430 | if curve2 is None: return
1431 | intersection_list = rs.CurveCurveIntersection(curve1, curve2)
1432 | if intersection_list is None:
1433 | print("Selected curves do not intersect.")
1434 | return
1435 | for intersection in intersection_list:
1436 | if intersection[0] == 1:
1437 | print("Point")
1438 | print("Intersection point on first curve: {}".format(intersection[1]))
1439 | print("Intersection point on second curve: {}".format(intersection[3]))
1440 | print("First curve parameter: {}".format(intersection[5]))
1441 | print("Second curve parameter: {}".format(intersection[7]))
1442 | else:
1443 | print("Overlap")
1444 | print("Intersection start point on first curve: {}".format(intersection[1]))
1445 | print("Intersection end point on first curve: {}".format(intersection[2]))
1446 | print("Intersection start point on second curve: {}".format(intersection[3]))
1447 | print("Intersection end point on second curve: {}".format(intersection[4]))
1448 | print("First curve parameter range: {} to {}".format(intersection[5], intersection[6]))
1449 | print("Second curve parameter range: {} to {}".format(intersection[7], intersection[8]))
1450 | ccx()
1451 | See Also:
1452 | CurveSurfaceIntersection
1453 | """
1454 | curveA = rhutil.coercecurve(curveA, -1, True)
1455 | if curveB: curveB = rhutil.coercecurve(curveB, -1, True)
1456 | if tolerance is None or tolerance<0.0:
1457 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1458 | if curveB:
1459 | rc = Rhino.Geometry.Intersect.Intersection.CurveCurve(curveA, curveB, tolerance, 0.0)
1460 | else:
1461 | rc = Rhino.Geometry.Intersect.Intersection.CurveSelf(curveA, tolerance)
1462 | if rc:
1463 | events = []
1464 | for i in compat.RANGE(rc.Count):
1465 | event_type = 1
1466 | if( rc[i].IsOverlap ): event_type = 2
1467 | oa = rc[i].OverlapA
1468 | ob = rc[i].OverlapB
1469 | element = (event_type, rc[i].PointA, rc[i].PointA2, rc[i].PointB, rc[i].PointB2, oa[0], oa[1], ob[0], ob[1])
1470 | events.append(element)
1471 | return events
1472 |
1473 |
1474 | def CurveDegree(curve_id, segment_index=-1):
1475 | """Returns the degree of a curve object.
1476 | Parameters:
1477 | curve_id (guid): identifier of a curve object.
1478 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve.
1479 | Returns:
1480 | number: The degree of the curve if successful.
1481 | None: on error.
1482 | Example:
1483 | import rhinoscriptsyntax as rs
1484 | obj = rs.GetObject("Select a curve")
1485 | if rs.IsCurve(obj):
1486 | degree = rs.CurveDegree(obj)
1487 | print("Curve degree:{}".format(degree))
1488 | See Also:
1489 | CurveDomain
1490 | IsCurve
1491 | """
1492 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1493 | return curve.Degree
1494 |
1495 |
1496 | def CurveDeviation(curve_a, curve_b):
1497 | """Returns the minimum and maximum deviation between two curve objects
1498 | Parameters:
1499 | curve_a, curve_b (guid): identifiers of two curves
1500 | Returns:
1501 | tuple[number, number, number, number, number, number]: of deviation information on success
1502 | [0] = curve_a parameter at maximum overlap distance point
1503 | [1] = curve_b parameter at maximum overlap distance point
1504 | [2] = maximum overlap distance
1505 | [3] = curve_a parameter at minimum overlap distance point
1506 | [4] = curve_b parameter at minimum overlap distance point
1507 | [5] = minimum distance between curves
1508 | None on error
1509 | Example:
1510 | import rhinoscriptsyntax as rs
1511 | curveA = rs.GetObject("Select first curve to test", rs.filter.curve)
1512 | curveB = rs.GetObject("Select second curve to test", rs.filter.curve)
1513 | deviation = rs.CurveDeviation(curveA, curveB)
1514 | if deviation:
1515 | print("Minimum deviation = {}".format(deviation[5]))
1516 | print("Maximum deviation = {}".format(deviation[2]))
1517 | See Also:
1518 | CurveArea
1519 | CurveAreaCentroid
1520 | """
1521 | curve_a = rhutil.coercecurve(curve_a, -1, True)
1522 | curve_b = rhutil.coercecurve(curve_b, -1, True)
1523 | tol = scriptcontext.doc.ModelAbsoluteTolerance
1524 | rc = Rhino.Geometry.Curve.GetDistancesBetweenCurves(curve_a, curve_b, tol)
1525 | if not rc[0]: return scriptcontext.errorhandler()
1526 | maxa = rc[2]
1527 | maxb = rc[3]
1528 | maxd = rc[1]
1529 | mina = rc[5]
1530 | minb = rc[6]
1531 | mind = rc[4]
1532 | return maxa, maxb, maxd, mina, minb, mind
1533 |
1534 |
1535 | def CurveDim(curve_id, segment_index=-1):
1536 | """Returns the dimension of a curve object
1537 | Parameters:
1538 | curve_id (guid): identifier of a curve object.
1539 | segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve.
1540 | Returns:
1541 | number: The dimension of the curve if successful. None on error.
1542 | Example:
1543 | import rhinoscriptsyntax as rs
1544 | curve = rs.GetObject("Select a curve")
1545 | if rs.IsCurve(curve):
1546 | print("Curve dimension = {}".format(rs.CurveDim(curve)))
1547 | See Also:
1548 | CurveDegree
1549 | CurveDomain
1550 | """
1551 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1552 | return curve.Dimension
1553 |
1554 |
1555 | def CurveDirectionsMatch(curve_id_0, curve_id_1):
1556 | """Tests if two curve objects are generally in the same direction or if they
1557 | would be more in the same direction if one of them were flipped. When testing
1558 | curve directions, both curves must be either open or closed - you cannot test
1559 | one open curve and one closed curve.
1560 | Parameters:
1561 | curve_id_0 (guid): identifier of first curve object
1562 | curve_id_1 (guid): identifier of second curve object
1563 | Returns:
1564 | bool: True if the curve directions match, otherwise False.
1565 | Example:
1566 | import rhinoscriptsyntax as rs
1567 | curve1 = rs.GetObject("Select first curve to compare", rs.filter.curve)
1568 | curve2 = rs.GetObject("Select second curve to compare", rs.filter.curve)
1569 | if rs.CurveDirectionsMatch(curve1, curve2):
1570 | print("Curves are in the same direction")
1571 | else:
1572 | print("Curve are not in the same direction")
1573 | See Also:
1574 | ReverseCurve
1575 | """
1576 | curve0 = rhutil.coercecurve(curve_id_0, -1, True)
1577 | curve1 = rhutil.coercecurve(curve_id_1, -1, True)
1578 | return Rhino.Geometry.Curve.DoDirectionsMatch(curve0, curve1)
1579 |
1580 |
1581 | def CurveDiscontinuity(curve_id, style):
1582 | """Search for a derivatitive, tangent, or curvature discontinuity in
1583 | a curve object.
1584 | Parameters:
1585 | curve_id (guid): identifier of curve object
1586 | style (number): The type of continuity to test for. The types of
1587 | continuity are as follows:
1588 | Value Description
1589 | 1 C0 - Continuous function
1590 | 2 C1 - Continuous first derivative
1591 | 3 C2 - Continuous first and second derivative
1592 | 4 G1 - Continuous unit tangent
1593 | 5 G2 - Continuous unit tangent and curvature
1594 | Returns:
1595 | list(point, ...): 3D points where the curve is discontinuous
1596 | Example:
1597 | import rhinoscriptsyntax as rs
1598 | curve = rs.GetObject("Select a curve", rs.filter.curve)
1599 | if rs.IsCurve(curve):
1600 | points = rs.CurveDiscontinuity(curve, 2)
1601 | if points: rs.AddPoints( points )
1602 | See Also:
1603 | IsCurve
1604 | """
1605 | curve = rhutil.coercecurve(curve_id, -1, True)
1606 | dom = curve.Domain
1607 | t0 = dom.Min
1608 | t1 = dom.Max
1609 | points = []
1610 | get_next = True
1611 | while get_next:
1612 | get_next, t = curve.GetNextDiscontinuity(System.Enum.ToObject(Rhino.Geometry.Continuity, style), t0, t1)
1613 | if get_next:
1614 | points.append(curve.PointAt(t))
1615 | t0 = t # Advance to the next parameter
1616 | return points
1617 |
1618 |
1619 | def CurveDomain(curve_id, segment_index=-1):
1620 | """Returns the domain of a curve object
1621 | as an indexable object with two elements.
1622 | Parameters:
1623 | curve_id (guid): identifier of the curve object
1624 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve.
1625 | Returns:
1626 | list(number, number): the domain of the curve if successful.
1627 | [0] Domain minimum
1628 | [1] Domain maximum
1629 | None: on error
1630 |
1631 | Example:
1632 | import rhinoscriptsyntax as rs
1633 | obj = rs.GetObject("Select a curve")
1634 | if rs.IsCurve(obj):
1635 | domain = rs.CurveDomain(obj)
1636 | print("Curve domain: {} to {}".format(domain[0], domain[1]))
1637 | See Also:
1638 | CurveDegree
1639 | IsCurve
1640 | """
1641 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1642 | return curve.Domain
1643 |
1644 |
1645 | def CurveEditPoints(curve_id, return_parameters=False, segment_index=-1):
1646 | """Returns the edit, or Greville, points of a curve object.
1647 | For each curve control point, there is a corresponding edit point.
1648 | Parameters:
1649 | curve_id (guid): identifier of the curve object
1650 | return_parameters (bool, optional): if True, return as a list of curve parameters.
1651 | If False, return as a list of 3d points
1652 | segment_index (number, optional): the curve segment index is `curve_id` identifies a polycurve
1653 | Returns:
1654 | list(point, ....): curve edit points on success
1655 | None on error
1656 | Example:
1657 | import rhinoscriptsyntax as rs
1658 | obj = rs.GetObject("Select a curve")
1659 | if rs.IsCurve(obj):
1660 | points = rs.CurveEditPoints(obj)
1661 | if points: rs.AddPointCloud( points )
1662 | See Also:
1663 | IsCurve
1664 | CurvePointCount
1665 | CurvePoints
1666 | """
1667 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1668 | nc = curve.ToNurbsCurve()
1669 | if not nc: return scriptcontext.errorhandler()
1670 | if return_parameters: return nc.GrevilleParameters()
1671 | return list(nc.GrevillePoints())
1672 |
1673 |
1674 | def CurveEndPoint(curve_id, segment_index=-1):
1675 | """Returns the end point of a curve object
1676 | Parameters:
1677 | curve_id (guid): identifier of the curve object
1678 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
1679 | Returns:
1680 | point: The 3d endpoint of the curve if successful.
1681 | None: on error
1682 | Example:
1683 | import rhinoscriptsyntax as rs
1684 | object = rs.GetObject("Select a curve")
1685 | if rs.IsCurve(object):
1686 | point = rs.CurveEndPoint(object)
1687 | rs.AddPoint(point)
1688 | See Also:
1689 | CurveMidPoint
1690 | CurveStartPoint
1691 | IsCurve
1692 | """
1693 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1694 | return curve.PointAtEnd
1695 |
1696 |
1697 | def CurveFilletPoints(curve_id_0, curve_id_1, radius=1.0, base_point_0=None, base_point_1=None, return_points=True):
1698 | """Find points at which to cut a pair of curves so that a fillet of a
1699 | specified radius fits. A fillet point is a pair of points (point0, point1)
1700 | such that there is a circle of radius tangent to curve curve0 at point0 and
1701 | tangent to curve curve1 at point1. Of all possible fillet points, this
1702 | function returns the one which is the closest to the base point base_point_0,
1703 | base_point_1. Distance from the base point is measured by the sum of arc
1704 | lengths along the two curves.
1705 | Parameters:
1706 | curve_id_0 (guid): identifier of the first curve object.
1707 | curve_id_1 (guid): identifier of the second curve object.
1708 | radius (number, optional): The fillet radius. If omitted, a radius
1709 | of 1.0 is specified.
1710 | base_point_0 (point, optional): The base point on the first curve.
1711 | If omitted, the starting point of the curve is used.
1712 | base_point_1 (point, optional): The base point on the second curve. If omitted,
1713 | the starting point of the curve is used.
1714 | return_points (bool, optional): If True (Default), then fillet points are
1715 | returned. Otherwise, a fillet curve is created and
1716 | it's identifier is returned.
1717 | Returns:
1718 | list(point, point, point, vector, vector, vector): If return_points is True, then a list of point and vector values
1719 | if successful. The list elements are as follows:
1720 | [0] A point on the first curve at which to cut (point).
1721 | [1] A point on the second curve at which to cut (point).
1722 | [2] The fillet plane's origin (point). This point is also
1723 | the center point of the fillet
1724 | [3] The fillet plane's X axis (vector).
1725 | [4] The fillet plane's Y axis (vector).
1726 | [5] The fillet plane's Z axis (vector).
1727 |
1728 | guid: If return_points is False, then the identifier of the fillet curve
1729 | if successful.
1730 | None: if not successful, or on error.
1731 | Example:
1732 | import rhinoscriptsyntax as rs
1733 | curve0 = rs.AddLine([0,0,0], [5,1,0])
1734 | curve1 = rs.AddLine([0,0,0], [1,5,0])
1735 | fillet = rs.CurveFilletPoints(curve0, curve1)
1736 | if fillet:
1737 | rs.AddPoint( fillet[0] )
1738 | rs.AddPoint( fillet[1] )
1739 | rs.AddPoint( fillet[2] )
1740 | See Also:
1741 | AddFilletCurve
1742 | """
1743 | curve0 = rhutil.coercecurve(curve_id_0, -1, True)
1744 | curve1 = rhutil.coercecurve(curve_id_1, -1, True)
1745 | t0_base = curve0.Domain.Min
1746 |
1747 | if base_point_0:
1748 | rc = curve0.ClosestPoint(base_point_0, t0_base)
1749 | if not rc[0]: return scriptcontext.errorhandler()
1750 |
1751 | t1_base = curve1.Domain.Min
1752 | if base_point_1:
1753 | rc = curve1.ClosestPoint(base_point_1, t1_base)
1754 | if not rc[0]: return scriptcontext.errorhandler()
1755 |
1756 | r = radius if (radius and radius>0) else 1.0
1757 | rc = Rhino.Geometry.Curve.GetFilletPoints(curve0, curve1, r, t0_base, t1_base)
1758 | if rc[0]:
1759 | point_0 = curve0.PointAt(rc[1])
1760 | point_1 = curve1.PointAt(rc[2])
1761 | return point_0, point_1, rc[3].Origin, rc[3].XAxis, rc[3].YAxis, rc[3].ZAxis
1762 | return scriptcontext.errorhandler()
1763 |
1764 |
1765 | def CurveFrame(curve_id, parameter, segment_index=-1):
1766 | """Returns the plane at a parameter of a curve. The plane is based on the
1767 | tangent and curvature vectors at a parameter.
1768 | Parameters:
1769 | curve_id (guid): identifier of the curve object.
1770 | parameter (number): parameter to evaluate.
1771 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
1772 | Returns:
1773 | plane: The plane at the specified parameter if successful.
1774 | None: if not successful, or on error.
1775 | Example:
1776 | import rhinoscriptsyntax as rs
1777 | curve = rs.GetCurveObject("Select a curve")
1778 | if curve:
1779 | plane = rs.CurveFrame(curve[0], curve[4])
1780 | rs.AddPlaneSurface(plane, 5.0, 3.0)
1781 | See Also:
1782 | CurvePerpFrame
1783 | """
1784 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1785 | domain = curve.Domain
1786 | if not domain.IncludesParameter(parameter):
1787 | tol = scriptcontext.doc.ModelAbsoluteTolerance
1788 | if parameter>domain.Max and (parameter-domain.Max)<=tol:
1789 | parameter = domain.Max
1790 | elif parameter<domain.Min and (domain.Min-parameter)<=tol:
1791 | parameter = domain.Min
1792 | else:
1793 | return scriptcontext.errorhandler()
1794 | rc, frame = curve.FrameAt(parameter)
1795 | if rc and frame.IsValid: return frame
1796 | return scriptcontext.errorhandler()
1797 |
1798 |
1799 | def CurveKnotCount(curve_id, segment_index=-1):
1800 | """Returns the knot count of a curve object.
1801 | Parameters:
1802 | curve_id (guid): identifier of the curve object.
1803 | segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve.
1804 | Returns:
1805 | number: The number of knots if successful.
1806 | None: if not successful or on error.
1807 | Example:
1808 | import rhinoscriptsyntax as rs
1809 | obj = rs.GetObject("Select a curve")
1810 | if rs.IsCurve(obj):
1811 | count = rs.CurveKnotCount(obj)
1812 | print("Curve knot count:{}".format(count))
1813 | See Also:
1814 | DivideCurve
1815 | IsCurve
1816 | """
1817 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1818 | nc = curve.ToNurbsCurve()
1819 | if not nc: return scriptcontext.errorhandler()
1820 | return nc.Knots.Count
1821 |
1822 |
1823 | def CurveKnots(curve_id, segment_index=-1):
1824 | """Returns the knots, or knot vector, of a curve object
1825 | Parameters:
1826 | curve_id (guid): identifier of the curve object.
1827 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve.
1828 | Returns:
1829 | list(number, ....): knot values if successful.
1830 | None: if not successful or on error.
1831 | Example:
1832 | import rhinoscriptsyntax as rs
1833 | obj = rs.GetObject("Select a curve")
1834 | if rs.IsCurve(obj):
1835 | knots = rs.CurveKnots(obj)
1836 | if knots:
1837 | for knot in knots: print("Curve knot value:{}".format(knot))
1838 | See Also:
1839 | CurveKnotCount
1840 | IsCurve
1841 | """
1842 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1843 | nc = curve.ToNurbsCurve()
1844 | if not nc: return scriptcontext.errorhandler()
1845 | rc = [nc.Knots[i] for i in range(nc.Knots.Count)]
1846 | return rc
1847 |
1848 |
1849 | def CurveLength(curve_id, segment_index=-1, sub_domain=None):
1850 | """Returns the length of a curve object.
1851 | Parameters:
1852 | curve_id (guid): identifier of the curve object
1853 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
1854 | sub_domain ([number, number], optional): list of two numbers identifying the sub-domain of the
1855 | curve on which the calculation will be performed. The two parameters
1856 | (sub-domain) must be non-decreasing. If omitted, the length of the
1857 | entire curve is returned.
1858 | Returns:
1859 | number: The length of the curve if successful.
1860 | None: if not successful, or on error.
1861 | Example:
1862 | import rhinoscriptsyntax as rs
1863 | object = rs.GetObject("Select a curve")
1864 | if rs.IsCurve(object):
1865 | length = rs.CurveLength(object)
1866 | print("Curve length:{}".format(length))
1867 | See Also:
1868 | CurveDomain
1869 | IsCurve
1870 | """
1871 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1872 | if sub_domain:
1873 | if len(sub_domain)==2:
1874 | dom = Rhino.Geometry.Interval(sub_domain[0], sub_domain[1])
1875 | return curve.GetLength(dom)
1876 | return scriptcontext.errorhandler()
1877 | return curve.GetLength()
1878 |
1879 |
1880 | def CurveMidPoint(curve_id, segment_index=-1):
1881 | """Returns the mid point of a curve object.
1882 | Parameters:
1883 | curve_id (guid): identifier of the curve object
1884 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
1885 | Returns:
1886 | point: The 3D midpoint of the curve if successful.
1887 | None: if not successful, or on error.
1888 | Example:
1889 | import rhinoscriptsyntax as rs
1890 | object = rs.GetObject("Select a curve")
1891 | if rs.IsCurve(object):
1892 | point = rs.CurveMidPoint(pbject)
1893 | rs.AddPoint( point )
1894 | See Also:
1895 | CurveEndPoint
1896 | CurveStartPoint
1897 | IsCurve
1898 | """
1899 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1900 | rc, t = curve.NormalizedLengthParameter(0.5)
1901 | if rc: return curve.PointAt(t)
1902 | return scriptcontext.errorhandler()
1903 |
1904 |
1905 | def CurveNormal(curve_id, segment_index=-1):
1906 | """Returns the normal direction of the plane in which a planar curve object lies.
1907 | Parameters:
1908 | curve_id (guid): identifier of the curve object
1909 | segment_index (number, optional): the curve segment if curve_id identifies a polycurve
1910 | Returns:
1911 | vector: The 3D normal vector if successful.
1912 | None: if not successful, or on error.
1913 | Example:
1914 | import rhinoscriptsyntax as rs
1915 | object = rs.GetObject("Select a planar curve")
1916 | if rs.IsCurve(object) and rs.IsCurvePlanar(object):
1917 | normal = rs.CurveNormal(object)
1918 | if normal: print("Curve Normal:{}".format(normal))
1919 | See Also:
1920 | IsCurve
1921 | IsCurvePlanar
1922 | """
1923 | curve = rhutil.coercecurve(curve_id, segment_index, True)
1924 | tol = scriptcontext.doc.ModelAbsoluteTolerance
1925 | rc, plane = curve.TryGetPlane(tol)
1926 | if rc: return plane.Normal
1927 | return scriptcontext.errorhandler()
1928 |
1929 |
1930 | def CurveNormalizedParameter(curve_id, parameter):
1931 | """Converts a curve parameter to a normalized curve parameter;
1932 | one that ranges between 0-1
1933 | Parameters:
1934 | curve_id (guid): identifier of the curve object
1935 | parameter (number): the curve parameter to convert
1936 | Returns:
1937 | number: normalized curve parameter
1938 | Example:
1939 | import rhinoscriptsyntax as rs
1940 | obj = rs.GetObject("Select curve")
1941 | if rs.IsCurve(obj):
1942 | domain = rs.CurveDomain(obj)
1943 | parameter = (domain[0]+domain[1])/2.0
1944 | print("Curve parameter:{}".format(parameter))
1945 | normalized = rs.CurveNormalizedParameter(obj, parameter)
1946 | print("Normalized parameter:{}".format(normalized))
1947 | See Also:
1948 | CurveDomain
1949 | CurveParameter
1950 | """
1951 | curve = rhutil.coercecurve(curve_id, -1, True)
1952 | return curve.Domain.NormalizedParameterAt(parameter)
1953 |
1954 |
1955 | def CurveParameter(curve_id, parameter):
1956 | """Converts a normalized curve parameter to a curve parameter;
1957 | one within the curve's domain
1958 | Parameters:
1959 | curve_id (guid): identifier of the curve object
1960 | parameter (number): the normalized curve parameter to convert
1961 | Returns:
1962 | number: curve parameter
1963 | Example:
1964 | import rhinoscriptsyntax as rs
1965 | obj = rs.GetObject("Select curve")
1966 | if rs.IsCurve(obj):
1967 | normalized = 0.5
1968 | print("Normalized parameter:{}".format(normalized))
1969 | parameter = rs.CurveParameter(obj, normalized)
1970 | print("Curve parameter:{}".format(parameter))
1971 | See Also:
1972 | CurveDomain
1973 | CurveNormalizedParameter
1974 | """
1975 | curve = rhutil.coercecurve(curve_id, -1, True)
1976 | return curve.Domain.ParameterAt(parameter)
1977 |
1978 |
1979 | def CurvePerpFrame(curve_id, parameter):
1980 | """Returns the perpendicular plane at a parameter of a curve. The result
1981 | is relatively parallel (zero-twisting) plane
1982 | Parameters:
1983 | curve_id (guid): identifier of the curve object
1984 | parameter (number): parameter to evaluate
1985 | Returns:
1986 | plane: Plane on success
1987 | None: on error
1988 | Example:
1989 | import rhinoscriptsyntax as rs
1990 | crv = rs.GetCurveObject("Select a curve")
1991 | if crv:
1992 | plane = rs.CurvePerpFrame(crv[0], crv[4])
1993 | rs.AddPlaneSurface( plane, 1, 1 )
1994 | See Also:
1995 | CurveFrame
1996 | """
1997 | curve = rhutil.coercecurve(curve_id, -1, True)
1998 | parameter = float(parameter)
1999 | rc, plane = curve.PerpendicularFrameAt(parameter)
2000 | if rc: return plane
2001 |
2002 |
2003 | def CurvePlane(curve_id, segment_index=-1):
2004 | """Returns the plane in which a planar curve lies. Note, this function works
2005 | only on planar curves.
2006 | Parameters:
2007 | curve_id (guid): identifier of the curve object
2008 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
2009 | Returns:
2010 | plane: The plane in which the curve lies if successful.
2011 | None: if not successful, or on error.
2012 | Example:
2013 | import rhinoscriptsyntax as rs
2014 | curve = rs.GetObject("Select a curve", rs.filter.curve)
2015 | if rs.IsCurvePlanar(curve):
2016 | plane = rs.CurvePlane(curve)
2017 | rs.ViewCPlane(None, plane)
2018 | See Also:
2019 | IsCurve
2020 | IsCurvePlanar
2021 | """
2022 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2023 | tol = scriptcontext.doc.ModelAbsoluteTolerance
2024 | rc, plane = curve.TryGetPlane(tol)
2025 | if rc: return plane
2026 | return scriptcontext.errorhandler()
2027 |
2028 |
2029 | def CurvePointCount(curve_id, segment_index=-1):
2030 | """Returns the control points count of a curve object.
2031 | Parameters:
2032 | curve_id (guid) identifier of the curve object
2033 | segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve
2034 | Returns:
2035 | number: Number of control points if successful.
2036 | None: if not successful
2037 | Example:
2038 | import rhinoscriptsyntax as rs
2039 | obj = rs.GetObject("Select a curve")
2040 | if rs.IsCurve(obj):
2041 | count = rs.CurvePointCount(obj)
2042 | print("Curve point count:{}".format(count))
2043 | See Also:
2044 | DivideCurve
2045 | IsCurve
2046 | """
2047 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2048 | nc = curve.ToNurbsCurve()
2049 | if nc: return nc.Points.Count
2050 | return scriptcontext.errorhandler()
2051 |
2052 |
2053 | def CurvePoints(curve_id, segment_index=-1):
2054 | """Returns the control points, or control vertices, of a curve object.
2055 | If the curve is a rational NURBS curve, the euclidean control vertices
2056 | are returned.
2057 | Parameters:
2058 | curve_id (guid): the object's identifier
2059 | segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve
2060 | Returns:
2061 | list(point, ...): the control points, or control vertices, of a curve object
2062 | Example:
2063 | import rhinoscriptsyntax as rs
2064 | obj = rs.GetObject("Select a curve")
2065 | if rs.IsCurve(obj):
2066 | points = rs.CurvePoints(obj)
2067 | if points: [rs.AddPoint(pt) for pt in points]
2068 | See Also:
2069 | CurvePointCount
2070 | IsCurve
2071 | """
2072 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2073 | nc = curve.ToNurbsCurve()
2074 | if nc is None: return scriptcontext.errorhandler()
2075 | points = [nc.Points[i].Location for i in compat.RANGE(nc.Points.Count)]
2076 | return points
2077 |
2078 |
2079 | def CurveRadius(curve_id, test_point, segment_index=-1):
2080 | """Returns the radius of curvature at a point on a curve.
2081 | Parameters:
2082 | curve_id (guid): identifier of the curve object
2083 | test_point (point): sampling point
2084 | segment_index (number, optional): the curve segment if curve_id identifies a polycurve
2085 | Returns:
2086 | number: The radius of curvature at the point on the curve if successful.
2087 | None: if not successful, or on error.
2088 | Example:
2089 | import rhinoscriptsyntax as rs
2090 | obj = rs.GetObject("Select a curve")
2091 | if rs.IsCurve(obj):
2092 | point = rs.GetPointOnCurve(obj, "Pick a test point")
2093 | if point:
2094 | radius = rs.CurveRadius(obj, point)
2095 | print("Radius of curvature:{}".format(radius))
2096 | See Also:
2097 | IsCurve
2098 | """
2099 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2100 | point = rhutil.coerce3dpoint(test_point, True)
2101 | rc, t = curve.ClosestPoint(point, 0.0)
2102 | if not rc: return scriptcontext.errorhandler()
2103 | v = curve.CurvatureAt( t )
2104 | k = v.Length
2105 | if k>Rhino.RhinoMath.ZeroTolerance: return 1/k
2106 | return scriptcontext.errorhandler()
2107 |
2108 |
2109 | def CurveSeam(curve_id, parameter):
2110 | """Adjusts the seam, or start/end, point of a closed curve.
2111 | Parameters:
2112 | curve_id (guid): identifier of the curve object
2113 | parameter (number): The parameter of the new start/end point.
2114 | Note, if successful, the resulting curve's
2115 | domain will start at `parameter`.
2116 | Returns:
2117 | bool: True or False indicating success or failure.
2118 | Example:
2119 | import rhinoscriptsyntax as rs
2120 | obj = rs.GetObject("Select closed curve", rs.filter.curve)
2121 | if rs.IsCurveClosed(obj):
2122 | domain = rs.CurveDomain(obj)
2123 | parameter = (domain[0] + domain[1])/2.0
2124 | rs.CurveSeam( obj, parameter )
2125 | See Also:
2126 | IsCurve
2127 | IsCurveClosed
2128 | """
2129 | curve = rhutil.coercecurve(curve_id, -1, True)
2130 | if (not curve.IsClosed or not curve.Domain.IncludesParameter(parameter)):
2131 | return False
2132 | dupe = curve.Duplicate()
2133 | if dupe:
2134 | dupe.ChangeClosedCurveSeam(parameter)
2135 | curve_id = rhutil.coerceguid(curve_id)
2136 | dupe_obj = scriptcontext.doc.Objects.Replace(curve_id, dupe)
2137 | return dupe_obj is not None
2138 | return False
2139 |
2140 |
2141 | def CurveStartPoint(curve_id, segment_index=-1, point=None):
2142 | """Returns the start point of a curve object
2143 | Parameters:
2144 | curve_id (guid): identifier of the curve object
2145 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
2146 | point (point, optional): new start point
2147 | Returns:
2148 | point: The 3D starting point of the curve if successful.
2149 | Example:
2150 | import rhinoscriptsyntax as rs
2151 | object = rs.GetObject("Select a curve")
2152 | if rs.IsCurve(object):
2153 | point = rs.CurveStartPoint(object)
2154 | rs.AddPoint(point)
2155 | See Also:
2156 | CurveEndPoint
2157 | CurveMidPoint
2158 | IsCurve
2159 | """
2160 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2161 | rc = curve.PointAtStart
2162 | if point:
2163 | point = rhutil.coerce3dpoint(point, True)
2164 | if point and curve.SetStartPoint(point):
2165 | curve_id = rhutil.coerceguid(curve_id, True)
2166 | scriptcontext.doc.Objects.Replace(curve_id, curve)
2167 | scriptcontext.doc.Views.Redraw()
2168 | return rc
2169 |
2170 |
2171 | def CurveSurfaceIntersection(curve_id, surface_id, tolerance=-1, angle_tolerance=-1):
2172 | """Calculates intersection of a curve object with a surface object.
2173 | Note, this function works on the untrimmed portion of the surface.
2174 | Parameters:
2175 | curve_id (guid): The identifier of the first curve object.
2176 | surface_id (guid): The identifier of the second curve object. If omitted,
2177 | the a self-intersection test will be performed on curve.
2178 | tolerance (number, optional): The absolute tolerance in drawing units. If omitted,
2179 | the document's current absolute tolerance is used.
2180 | angle_tolerance (number, optional) angle tolerance in degrees. The angle
2181 | tolerance is used to determine when the curve is tangent to the
2182 | surface. If omitted, the document's current angle tolerance is used.
2183 | Returns:
2184 | list(list(point, point, point, point, number, number, number, number, number, number), ...): of intersection information if successful.
2185 | The list will contain one or more of the following elements:
2186 | Element Type Description
2187 | [n][0] Number The intersection event type, either Point(1) or Overlap(2).
2188 | [n][1] Point3d If the event type is Point(1), then the intersection point
2189 | on the first curve. If the event type is Overlap(2), then
2190 | intersection start point on the first curve.
2191 | [n][2] Point3d If the event type is Point(1), then the intersection point
2192 | on the first curve. If the event type is Overlap(2), then
2193 | intersection end point on the first curve.
2194 | [n][3] Point3d If the event type is Point(1), then the intersection point
2195 | on the second curve. If the event type is Overlap(2), then
2196 | intersection start point on the surface.
2197 | [n][4] Point3d If the event type is Point(1), then the intersection point
2198 | on the second curve. If the event type is Overlap(2), then
2199 | intersection end point on the surface.
2200 | [n][5] Number If the event type is Point(1), then the first curve parameter.
2201 | If the event type is Overlap(2), then the start value of the
2202 | first curve parameter range.
2203 | [n][6] Number If the event type is Point(1), then the first curve parameter.
2204 | If the event type is Overlap(2), then the end value of the
2205 | curve parameter range.
2206 | [n][7] Number If the event type is Point(1), then the U surface parameter.
2207 | If the event type is Overlap(2), then the U surface parameter
2208 | for curve at (n, 5).
2209 | [n][8] Number If the event type is Point(1), then the V surface parameter.
2210 | If the event type is Overlap(2), then the V surface parameter
2211 | for curve at (n, 5).
2212 | [n][9] Number If the event type is Point(1), then the U surface parameter.
2213 | If the event type is Overlap(2), then the U surface parameter
2214 | for curve at (n, 6).
2215 | [n][10] Number If the event type is Point(1), then the V surface parameter.
2216 | If the event type is Overlap(2), then the V surface parameter
2217 | for curve at (n, 6).
2218 | Example:
2219 | import rhinoscriptsyntax as rs
2220 | def csx():
2221 | curve = rs.GetObject("Select curve", rs.filter.curve)
2222 | if curve is None: return
2223 | surface = rs.GetObject("Select surface", rs.filter.surface)
2224 | if surface is None: return
2225 | intersection_list = rs.CurveSurfaceIntersection(curve, surface)
2226 | if intersection_list is None:
2227 | print("Curve and surface do not intersect.")
2228 | return
2229 | for intersection in intersection_list:
2230 | if intersection[0]==1:
2231 | print("Point")
2232 | print("Intersection point on curve:{}".format(intersection[1]))
2233 | print("Intersection point on surface:{}".format(intersection[3]))
2234 | print("Curve parameter:{}".format(intersection[5]))
2235 | print("Surface parameter: {}, {}".format(intersection[7], intersection[8]))
2236 | else:
2237 | print("Overlap")
2238 | print("Intersection start point on curve:{}".format(intersection[1]))
2239 | print("Intersection end point on curve:{}".format(intersection[2]))
2240 | print("Intersection start point on surface:{}".format(intersection[3]))
2241 | print("Intersection end point on surface:{}".format(intersection[4]))
2242 | print("Curve parameter range: {} to {}".format(intersection[5], intersection[6]))
2243 | print("Surface parameter range: {}, {} to {}, {}".format(intersection[7] intersection[8], intersection[9], intersection[10]))
2244 | csx()
2245 | See Also:
2246 | CurveCurveIntersection
2247 | CurveBrepIntersect
2248 | """
2249 | curve = rhutil.coercecurve(curve_id, -1, True)
2250 | surface = rhutil.coercesurface(surface_id, True)
2251 | if tolerance is None or tolerance<0:
2252 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
2253 | if angle_tolerance is None or angle_tolerance<0:
2254 | angle_tolerance = scriptcontext.doc.ModelAngleToleranceRadians
2255 | else:
2256 | angle_tolerance = math.radians(angle_tolerance)
2257 | rc = Rhino.Geometry.Intersect.Intersection.CurveSurface(curve, surface, tolerance, angle_tolerance)
2258 | if rc:
2259 | events = []
2260 | for i in compat.RANGE(rc.Count):
2261 | event_type = 2 if rc[i].IsOverlap else 1
2262 | item = rc[i]
2263 | oa = item.OverlapA
2264 | u,v = item.SurfaceOverlapParameter()
2265 | e = (event_type, item.PointA, item.PointA2, item.PointB, item.PointB2, oa[0], oa[1], u[0], u[1], v[0], v[1])
2266 | events.append(e)
2267 | return events
2268 |
2269 |
2270 | def CurveTangent(curve_id, parameter, segment_index=-1):
2271 | """Returns a 3D vector that is the tangent to a curve at a parameter.
2272 | Parameters:
2273 | curve_id (guid): identifier of the curve object
2274 | parameter (number) parameter to evaluate
2275 | segment_index (number, optional) the curve segment index if `curve_id` identifies a polycurve
2276 | Returns:
2277 | vector: A 3D vector if successful.
2278 | None: on error.
2279 | Example:
2280 | import rhinoscriptsyntax as rs
2281 | obj = rs.GetObject("Select a curve", rs.filter.curve)
2282 | if obj:
2283 | point = rs.GetPointOnCurve(obj)
2284 | if point:
2285 | param = rs.CurveClosestPoint(obj, point)
2286 | normal = rs.CurveTangent(obj, param)
2287 | print(normal)
2288 | See Also:
2289 | CurveClosestPoint
2290 | CurveDomain
2291 | """
2292 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2293 | rc = Rhino.Geometry.Point3d.Unset
2294 | if curve.Domain.IncludesParameter(parameter):
2295 | return curve.TangentAt(parameter)
2296 | return scriptcontext.errorhandler()
2297 |
2298 |
2299 | def CurveWeights(curve_id, segment_index=-1):
2300 | """Returns list of weights that are assigned to the control points of a curve
2301 | Parameters:
2302 | curve_id (guid): identifier of the curve object
2303 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
2304 | Returns:
2305 | number: The weight values of the curve if successful.
2306 | None: if not successful, or on error.
2307 | Example:
2308 | import rhinoscriptsyntax as rs
2309 | obj = rs.GetObject("Select a curve")
2310 | if rs.IsCurve(obj):
2311 | weights = rs.CurveWeights(obj)
2312 | if weights:
2313 | for weight in weights:
2314 | print("Curve control point weight value:{}".format(weight))
2315 | See Also:
2316 | CurveKnots
2317 | IsCurve
2318 | """
2319 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2320 | nc = curve
2321 | if type(curve) is not Rhino.Geometry.NurbsCurve:
2322 | nc = curve.ToNurbsCurve()
2323 | if nc is None: return scriptcontext.errorhandler()
2324 | return [pt.Weight for pt in nc.Points]
2325 |
2326 |
2327 | def DivideCurve(curve_id, segments, create_points=False, return_points=True):
2328 | """Divides a curve object into a specified number of segments.
2329 | Parameters:
2330 | curve_id (guid):identifier of the curve object
2331 | segments (number): The number of segments.
2332 | create_points (bool, optional): Create the division points. If omitted or False,
2333 | points are not created.
2334 | return_points (bool, optional): If omitted or True, points are returned.
2335 | If False, then a list of curve parameters are returned.
2336 | Returns:
2337 | list(point|number, ...): If `return_points` is not specified or True, then a list containing 3D division points.
2338 | list(point|number, ...): If `return_points` is False, then an array containing division curve parameters.
2339 | None: if not successful, or on error.
2340 | Example:
2341 | import rhinoscriptsyntax as rs
2342 | obj = rs.GetObject("Select a curve")
2343 | if obj:
2344 | points = rs.DivideCurve(obj, 4)
2345 | for point in points: rs.AddPoint(point)
2346 | See Also:
2347 | DivideCurveEquidistant
2348 | DivideCurveLength
2349 | """
2350 | curve = rhutil.coercecurve(curve_id, -1, True)
2351 | rc = curve.DivideByCount(segments, True)
2352 | if not rc: return scriptcontext.errorhandler()
2353 | if return_points or create_points:
2354 | outputpoints = [curve.PointAt(t) for t in rc]
2355 | if return_points: rc = outputpoints
2356 | if create_points:
2357 | for point in outputpoints:
2358 | if point.IsValid: scriptcontext.doc.Objects.AddPoint(point)
2359 | scriptcontext.doc.Views.Redraw()
2360 | return rc
2361 |
2362 |
2363 | def DivideCurveEquidistant(curve_id, distance, create_points=False, return_points=True):
2364 | """Divides a curve such that the linear distance between the points is equal.
2365 | Parameters:
2366 | curve_id (guid): the object's identifier
2367 | distance (number): linear distance between division points
2368 | create_points (bool, optional): create the division points if True.
2369 | return_points (bool, optional): If True, return a list of points.
2370 | If False, return a list of curve parameters
2371 | Returns:
2372 | list(point|number, ...): points or curve parameters based on the value of return_points
2373 | none on error
2374 | Example:
2375 | import rhinoscriptsyntax as rs
2376 | obj = rs.GetObject("Select a curve", rs.filter.curve)
2377 | if obj:
2378 | points = rs.DivideCurveEquidistant(obj, 4, True)
2379 | See Also:
2380 | DivideCurve
2381 | DivideCurveLength
2382 | """
2383 | curve = rhutil.coercecurve(curve_id, -1, True)
2384 | points = curve.DivideEquidistant(distance)
2385 | if not points: return scriptcontext.errorhandler()
2386 | if create_points:
2387 | for point in points: scriptcontext.doc.Objects.AddPoint(point)
2388 | scriptcontext.doc.Views.Redraw()
2389 | if return_points: return points
2390 | tvals = []
2391 | for point in points:
2392 | rc, t = curve.ClosestPoint(point)
2393 | tvals.append(t)
2394 | return tvals
2395 |
2396 |
2397 | def DivideCurveLength(curve_id, length, create_points=False, return_points=True):
2398 | """Divides a curve object into segments of a specified length.
2399 | Parameters:
2400 | curve_id (guid): identifier of the curve object
2401 | length (number): The length of each segment.
2402 | create_points (bool, optional): Create the division points. If omitted or False,
2403 | points are not created.
2404 | return_points (bool, optional): If omitted or True, points are returned.
2405 | If False, then a list of curve parameters are returned.
2406 | Returns:
2407 | list(point, ...): If return_points is not specified or True, then a list containing division points.
2408 | list(number, ...): If return_points is False, then an array containing division curve parameters.
2409 | None: if not successful, or on error.
2410 | Example:
2411 | import rhinoscriptsyntax as rs
2412 | obj = rs.GetObject("Select a curve")
2413 | if rs.IsCurve(obj):
2414 | length = rs.CurveLength(obj) / 4
2415 | points = rs.DivideCurveLength(obj, length)
2416 | for point in points: rs.AddPoint(point)
2417 | See Also:
2418 | DivideCurve
2419 | DivideCurveEquidistant
2420 | """
2421 | curve = rhutil.coercecurve(curve_id, -1, True)
2422 | rc = curve.DivideByLength(length, True)
2423 | if not rc: return scriptcontext.errorhandler()
2424 | if return_points or create_points:
2425 | outputpoints = [curve.PointAt(t) for t in rc]
2426 | if create_points:
2427 | for point in outputpoints:
2428 | if (point.IsValid): scriptcontext.doc.Objects.AddPoint(point)
2429 | if return_points: rc = outputpoints
2430 | return rc
2431 |
2432 |
2433 | def EllipseCenterPoint(curve_id):
2434 | """Returns the center point of an elliptical-shaped curve object.
2435 | Parameters:
2436 | curve_id (guid): identifier of the curve object.
2437 | Returns:
2438 | point: The 3D center point of the ellipse if successful.
2439 | Example:
2440 | import rhinoscriptsyntax as rs
2441 | obj = rs.GetObject("Select ellipse")
2442 | if rs.IsEllipse(obj):
2443 | point = rs.EllipseCenterPoint(obj)
2444 | rs.AddPoint( point )
2445 | See Also:
2446 | IsEllipse
2447 | EllipseQuadPoints
2448 | """
2449 | curve = rhutil.coercecurve(curve_id, -1, True)
2450 | rc, ellipse = curve.TryGetEllipse()
2451 | if not rc: raise ValueError("curve is not an ellipse")
2452 | return ellipse.Plane.Origin
2453 |
2454 |
2455 | def EllipseQuadPoints(curve_id):
2456 | """Returns the quadrant points of an elliptical-shaped curve object.
2457 | Parameters:
2458 | curve_id (guid): identifier of the curve object.
2459 | Returns:
2460 | list(point, point, point, point): Four points identifying the quadrants of the ellipse
2461 | Example:
2462 | import rhinoscriptsyntax as rs
2463 | obj = rs.GetObject("Select ellipse")
2464 | if rs.IsEllipse(obj):
2465 | rs.AddPoints( rs.EllipseQuadPoints(obj) )
2466 | See Also:
2467 | IsEllipse
2468 | EllipseCenterPoint
2469 | """
2470 | curve = rhutil.coercecurve(curve_id, -1, True)
2471 | rc, ellipse = curve.TryGetEllipse()
2472 | if not rc: raise ValueError("curve is not an ellipse")
2473 | origin = ellipse.Plane.Origin;
2474 | xaxis = ellipse.Radius1 * ellipse.Plane.XAxis;
2475 | yaxis = ellipse.Radius2 * ellipse.Plane.YAxis;
2476 | return (origin-xaxis, origin+xaxis, origin-yaxis, origin+yaxis)
2477 |
2478 |
2479 | def EvaluateCurve(curve_id, t, segment_index=-1):
2480 | """Evaluates a curve at a parameter and returns a 3D point
2481 | Parameters:
2482 | curve_id (guid): identifier of the curve object
2483 | t (number): the parameter to evaluate
2484 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
2485 | Returns:
2486 | point: a 3-D point if successful
2487 | None: if not successful
2488 | Example:
2489 | import rhinoscriptsyntax as rs
2490 | obj = rs.GetObject("Select a curve")
2491 | if rs.IsCurve(obj):
2492 | domain = rs.CurveDomain(obj)
2493 | t = domain[1]/2.0
2494 | point = rs.EvaluateCurve(obj, t)
2495 | rs.AddPoint( point )
2496 | See Also:
2497 | CurveClosestPoint
2498 | IsCurve
2499 | """
2500 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2501 | return curve.PointAt(t)
2502 |
2503 |
2504 | def ExplodeCurves(curve_ids, delete_input=False):
2505 | """Explodes, or un-joins, one curves. Polycurves will be exploded into curve
2506 | segments. Polylines will be exploded into line segments. ExplodeCurves will
2507 | return the curves in topological order.
2508 | Parameters:
2509 | curve_ids (guid): the curve object(s) to explode.
2510 | delete_input (bool, optional): Delete input objects after exploding if True.
2511 | Returns:
2512 | list(guid, ...): identifying the newly created curve objects
2513 | Example:
2514 | import rhinoscriptsyntax as rs
2515 | crv = rs.GetObject("Select curve to explode", rs.filter.curve)
2516 | if rs.IsCurve(crv): rs.ExplodeCurves(crv)
2517 | See Also:
2518 | IsCurve
2519 | IsPolyCurve
2520 | IsPolyline
2521 | JoinCurves
2522 | """
2523 | if( type(curve_ids) is list or type(curve_ids) is tuple ): pass
2524 | else: curve_ids = [curve_ids]
2525 | rc = []
2526 | for id in curve_ids:
2527 | curve = rhutil.coercecurve(id, -1, True)
2528 | pieces = curve.DuplicateSegments()
2529 | if pieces:
2530 | for piece in pieces:
2531 | rc.append(scriptcontext.doc.Objects.AddCurve(piece))
2532 | if delete_input:
2533 | id = rhutil.coerceguid(id, True)
2534 | scriptcontext.doc.Objects.Delete(id, True)
2535 | if rc: scriptcontext.doc.Views.Redraw()
2536 | return rc
2537 |
2538 |
2539 | def ExtendCurve(curve_id, extension_type, side, boundary_object_ids):
2540 | """Extends a non-closed curve object by a line, arc, or smooth extension
2541 | until it intersects a collection of objects.
2542 | Parameters:
2543 | curve_id (guid): identifier of curve to extend
2544 | extension_type (number):
2545 | 0 = line
2546 | 1 = arc
2547 | 2 = smooth
2548 | side (number):
2549 | 0=extend from the start of the curve
2550 | 1=extend from the end of the curve
2551 | 2=extend from both the start and the end of the curve
2552 | boundary_object_ids (guid): curve, surface, and polysurface objects to extend to
2553 | Returns:
2554 | guid: The identifier of the new object if successful.
2555 | None: if not successful
2556 | Example:
2557 | import rhinoscriptsyntax as rs
2558 | filter = rs.filter.curve | rs.filter.surface | rs.filter.polysurface
2559 | objects = rs.GetObjects("Select boundary objects", filter)
2560 | if objects:
2561 | curve = rs.GetObject("Select curve to extend", rs.filter.curve)
2562 | if curve: rs.ExtendCurve( curve, 2, 1, objects )
2563 | See Also:
2564 | ExtendCurveLength
2565 | ExtendCurvePoint
2566 | """
2567 | curve = rhutil.coercecurve(curve_id, -1, True)
2568 | if extension_type==0: extension_type = Rhino.Geometry.CurveExtensionStyle.Line
2569 | elif extension_type==1: extension_type = Rhino.Geometry.CurveExtensionStyle.Arc
2570 | elif extension_type==2: extension_type = Rhino.Geometry.CurveExtensionStyle.Smooth
2571 | else: raise ValueError("extension_type must be 0, 1, or 2")
2572 |
2573 | if side==0: side = Rhino.Geometry.CurveEnd.Start
2574 | elif side==1: side = Rhino.Geometry.CurveEnd.End
2575 | elif side==2: side = Rhino.Geometry.CurveEnd.Both
2576 | else: raise ValueError("side must be 0, 1, or 2")
2577 |
2578 | rhobjs = [rhutil.coercerhinoobject(id) for id in boundary_object_ids]
2579 | if not rhobjs: raise ValueError("boundary_object_ids must contain at least one item")
2580 | geometry = [obj.Geometry for obj in rhobjs]
2581 | newcurve = curve.Extend(side, extension_type, geometry)
2582 | if newcurve and newcurve.IsValid:
2583 | curve_id = rhutil.coerceguid(curve_id, True)
2584 | if scriptcontext.doc.Objects.Replace(curve_id, newcurve):
2585 | scriptcontext.doc.Views.Redraw()
2586 | return curve_id
2587 | return scriptcontext.errorhandler()
2588 |
2589 |
2590 | def ExtendCurveLength(curve_id, extension_type, side, length):
2591 | """Extends a non-closed curve by a line, arc, or smooth extension for a
2592 | specified distance
2593 | Parameters:
2594 | curve_id (guid): curve to extend
2595 | extension_type (number):
2596 | 0 = line
2597 | 1 = arc
2598 | 2 = smooth
2599 | side (number):
2600 | 0=extend from start of the curve
2601 | 1=extend from end of the curve
2602 | 2=Extend from both ends
2603 | length (number): distance to extend
2604 | Returns:
2605 | guid: The identifier of the new object
2606 | None: if not successful
2607 | Example:
2608 | import rhinoscriptsyntax as rs
2609 | curve = rs.GetObject("Select curve to extend", rs.filter.curve)
2610 | if curve:
2611 | length = rs.GetReal("Length to extend", 3.0)
2612 | if length: rs.ExtendCurveLength( curve, 2, 2, length )
2613 | See Also:
2614 | ExtendCurve
2615 | ExtendCurvePoint
2616 | """
2617 | curve = rhutil.coercecurve(curve_id, -1, True)
2618 | if extension_type==0: extension_type = Rhino.Geometry.CurveExtensionStyle.Line
2619 | elif extension_type==1: extension_type = Rhino.Geometry.CurveExtensionStyle.Arc
2620 | elif extension_type==2: extension_type = Rhino.Geometry.CurveExtensionStyle.Smooth
2621 | else: raise ValueError("extension_type must be 0, 1, or 2")
2622 |
2623 | if side==0: side = Rhino.Geometry.CurveEnd.Start
2624 | elif side==1: side = Rhino.Geometry.CurveEnd.End
2625 | elif side==2: side = Rhino.Geometry.CurveEnd.Both
2626 | else: raise ValueError("side must be 0, 1, or 2")
2627 | newcurve = None
2628 | if length<0: newcurve = curve.Trim(side, -length)
2629 | else: newcurve = curve.Extend(side, length, extension_type)
2630 | if newcurve and newcurve.IsValid:
2631 | curve_id = rhutil.coerceguid(curve_id, True)
2632 | if scriptcontext.doc.Objects.Replace(curve_id, newcurve):
2633 | scriptcontext.doc.Views.Redraw()
2634 | return curve_id
2635 | return scriptcontext.errorhandler()
2636 |
2637 |
2638 | def ExtendCurvePoint(curve_id, side, point, extension_type=2):
2639 | """Extends a non-closed curve by smooth extension to a point
2640 | Parameters:
2641 | curve_id (guid): curve to extend
2642 | side (number):
2643 | 0=extend from start of the curve
2644 | 1=extend from end of the curve
2645 | point (guid|point): point to extend to
2646 | extension_type (number, optional): type of extension
2647 | 0 = Line
2648 | 1 = Arc
2649 | 2 = Smooth
2650 | Returns:
2651 | guid: The identifier of the new object if successful.
2652 | None: if not successful, or on error.
2653 | Example:
2654 | import rhinoscriptsyntax as rs
2655 | curve = rs.GetObject("Select curve to extend", rs.filter.curve)
2656 | if curve:
2657 | point = rs.GetPoint("Point to extend to")
2658 | if point: rs.ExtendCurvePoint(curve, 1, point)
2659 | See Also:
2660 | ExtendCurve
2661 | ExtendCurveLength
2662 | """
2663 | curve = rhutil.coercecurve(curve_id, -1, True)
2664 | point = rhutil.coerce3dpoint(point, True)
2665 |
2666 | if side==0: side = Rhino.Geometry.CurveEnd.Start
2667 | elif side==1: side = Rhino.Geometry.CurveEnd.End
2668 | elif side==2: side = Rhino.Geometry.CurveEnd.Both
2669 | else: raise ValueError("side must be 0, 1, or 2")
2670 |
2671 | if extension_type==0: extension_type = Rhino.Geometry.CurveExtensionStyle.Line
2672 | elif extension_type==1: extension_type = Rhino.Geometry.CurveExtensionStyle.Arc
2673 | elif extension_type==2: extension_type = Rhino.Geometry.CurveExtensionStyle.Smooth
2674 | else: raise ValueError("extension_type must be 0, 1, or 2")
2675 |
2676 | newcurve = curve.Extend(side, extension_type, point)
2677 | if newcurve and newcurve.IsValid:
2678 | curve_id = rhutil.coerceguid(curve_id, True)
2679 | if scriptcontext.doc.Objects.Replace( curve_id, newcurve ):
2680 | scriptcontext.doc.Views.Redraw()
2681 | return curve_id
2682 | return scriptcontext.errorhandler()
2683 |
2684 |
2685 | def FairCurve(curve_id, tolerance=1.0):
2686 | """Fairs a curve. Fair works best on degree 3 (cubic) curves. Fair attempts
2687 | to remove large curvature variations while limiting the geometry changes to
2688 | be no more than the specified tolerance. Sometimes several applications of
2689 | this method are necessary to remove nasty curvature problems.
2690 | Parameters:
2691 | curve_id (guid): curve to fair
2692 | tolerance (number, optional): fairing tolerance
2693 | Returns:
2694 | bool: True or False indicating success or failure
2695 | Example:
2696 | import rhinoscriptsyntax as rs
2697 | curves = rs.GetObjects("Select curves to fair", rs.filter.curve)
2698 | if curves:
2699 | [rs.FairCurve(curve) for curve in curves]
2700 | See Also:
2701 |
2702 | """
2703 | curve = rhutil.coercecurve(curve_id, -1, True)
2704 | angle_tol = 0.0
2705 | clamp = 0
2706 | if curve.IsPeriodic:
2707 | curve = curve.ToNurbsCurve()
2708 | clamp = 1
2709 | newcurve = curve.Fair(tolerance, angle_tol, clamp, clamp, 100)
2710 | if not newcurve: return False
2711 | curve_id = rhutil.coerceguid(curve_id, True)
2712 | if scriptcontext.doc.Objects.Replace(curve_id, newcurve):
2713 | scriptcontext.doc.Views.Redraw()
2714 | return True
2715 | return False
2716 |
2717 |
2718 | def FitCurve(curve_id, degree=3, distance_tolerance=-1, angle_tolerance=-1):
2719 | """Reduces number of curve control points while maintaining the curve's same
2720 | general shape. Use this function for replacing curves with many control
2721 | points. For more information, see the Rhino help for the FitCrv command.
2722 | Parameters:
2723 | curve_id (guid): Identifier of the curve object
2724 | degree (number, optional): The curve degree, which must be greater than 1.
2725 | The default is 3.
2726 | distance_tolerance (number, optional): The fitting tolerance. If distance_tolerance
2727 | is not specified or <= 0.0, the document absolute tolerance is used.
2728 | angle_tolerance (number, optional): The kink smoothing tolerance in degrees. If
2729 | angle_tolerance is 0.0, all kinks are smoothed. If angle_tolerance
2730 | is > 0.0, kinks smaller than angle_tolerance are smoothed. If
2731 | angle_tolerance is not specified or < 0.0, the document angle
2732 | tolerance is used for the kink smoothing.
2733 | Returns:
2734 | guid: The identifier of the new object
2735 | None: if not successful, or on error.
2736 | Example:
2737 | import rhinoscriptsyntax as rs
2738 | oldCurve = rs.GetObject("Select curve to fit", rs.filter.curve)
2739 | if oldCurve:
2740 | newCurve = rs.FitCurve(oldCurve)
2741 | if newCurve: rs.DeleteObject(oldCurve)
2742 | See Also:
2743 |
2744 | """
2745 | curve = rhutil.coercecurve(curve_id, -1, True)
2746 | if distance_tolerance is None or distance_tolerance<0:
2747 | distance_tolerance = scriptcontext.doc.ModelAbsoluteTolerance
2748 | if angle_tolerance is None or angle_tolerance<0:
2749 | angle_tolerance = scriptcontext.doc.ModelAngleToleranceRadians
2750 | nc = curve.Fit(degree, distance_tolerance, angle_tolerance)
2751 | if nc:
2752 | rhobj = rhutil.coercerhinoobject(curve_id)
2753 | rc = None
2754 | if rhobj:
2755 | rc = scriptcontext.doc.Objects.AddCurve(nc, rhobj.Attributes)
2756 | else:
2757 | rc = scriptcontext.doc.Objects.AddCurve(nc)
2758 | if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
2759 | scriptcontext.doc.Views.Redraw()
2760 | return rc
2761 | return scriptcontext.errorhandler()
2762 |
2763 |
2764 | def InsertCurveKnot(curve_id, parameter, symmetrical=False ):
2765 | """Inserts a knot into a curve object
2766 | Parameters:
2767 | curve_id (guid): identifier of the curve object
2768 | parameter (number): parameter on the curve
2769 | symmetrical (bool, optional): if True, then knots are added on both sides of
2770 | the center of the curve
2771 | Returns:
2772 | bool: True or False indicating success or failure
2773 | Example:
2774 | import rhinoscriptsyntax as rs
2775 | obj = rs.GetObject("Select curve for knot insertion", rs.filter.curve)
2776 | if obj:
2777 | point = rs.GetPointOnCurve(obj, "Point on curve to add knot")
2778 | if point:
2779 | parameter = rs.CurveClosestPoint(obj, point)
2780 | rs.InsertCurveKnot( obj, parameter )
2781 | See Also:
2782 | CurveKnotCount
2783 | CurveKnots
2784 | """
2785 | curve = rhutil.coercecurve(curve_id, -1, True)
2786 | if not curve.Domain.IncludesParameter(parameter): return False
2787 | nc = curve.ToNurbsCurve()
2788 | if not nc: return False
2789 | rc, t = curve.GetNurbsFormParameterFromCurveParameter(parameter)
2790 | if rc:
2791 | rc = nc.Knots.InsertKnot(t,1)
2792 | if rc and symmetrical:
2793 | domain = nc.Domain
2794 | t_sym = domain.T1 - t + domain.T0
2795 | if abs(t_sym)>Rhino.RhinoMath.SqrtEpsilon:
2796 | rc = nc.Knots.InsertKnot(t_sym,1)
2797 | if rc:
2798 | curve_id = rhutil.coerceguid(curve_id)
2799 | rc = scriptcontext.doc.Objects.Replace(curve_id, nc)
2800 | if rc: scriptcontext.doc.Views.Redraw()
2801 | return rc
2802 |
2803 |
2804 | def IsArc(curve_id, segment_index=-1):
2805 | """Verifies an object is an open arc curve
2806 | Parameters:
2807 | curve_id (guid): Identifier of the curve object
2808 | segment_index (number): the curve segment index if `curve_id` identifies a polycurve
2809 | Returns:
2810 | bool: True or False
2811 | Example:
2812 | import rhinoscriptsyntax as rs
2813 | obj = rs.GetObject("Select an arc")
2814 | if rs.IsArc(obj):
2815 | print("The object is an arc.")
2816 | else:
2817 | print("The object is not an arc.")
2818 | See Also:
2819 | AddArc3Pt
2820 | ArcAngle
2821 | ArcCenterPoint
2822 | ArcMidPoint
2823 | ArcRadius
2824 | """
2825 | curve = rhutil.coercecurve(curve_id, segment_index, True)
2826 | return curve.IsArc() and not curve.IsClosed
2827 |
2828 |
2829 | def IsCircle(curve_id, tolerance=None):
2830 | """Verifies an object is a circle curve
2831 | Parameters:
2832 | curve_id (guid): Identifier of the curve object
2833 | tolerance (number, optional) If the curve is not a circle, then the tolerance used
2834 | to determine whether or not the NURBS form of the curve has the
2835 | properties of a circle. If omitted, Rhino's internal zero tolerance is used
2836 | Returns:
2837 | bool: True or False
2838 | Example:
2839 | import rhinoscriptsyntax as rs
2840 | obj = rs.GetObject("Select a circle")
2841 | if rs.IsCircle(obj):
2842 | print("The object is a circle.")
2843 | else:
2844 | print("The object is not a circle.")
2845 | See Also:
2846 | AddCircle
2847 | AddCircle3Pt
2848 | CircleCenterPoint
2849 | CircleCircumference
2850 | CircleRadius
2851 | """
2852 | curve = rhutil.coercecurve(curve_id, -1, True)
2853 | if tolerance is None or tolerance < 0:
2854 | tolerance = Rhino.RhinoMath.ZeroTolerance
2855 | return curve.IsCircle(tolerance)
2856 |
2857 |
2858 | def IsCurve(object_id):
2859 | """Verifies an object is a curve
2860 | Parameters:
2861 | object_id (guid): the object's identifier
2862 | Returns:
2863 | bool: True or False
2864 | Example:
2865 | import rhinoscriptsyntax as rs
2866 | object = rs.GetObject("Select a curve")
2867 | if rs.IsCurve(object):
2868 | print("The object is a curve.")
2869 | else:
2870 | print("The object is not a curve.")
2871 | See Also:
2872 | IsCurveClosed
2873 | IsCurveLinear
2874 | IsCurvePeriodic
2875 | IsCurvePlanar
2876 | """
2877 | curve = rhutil.coercecurve(object_id)
2878 | return curve is not None
2879 |
2880 |
2881 | def IsCurveClosable(curve_id, tolerance=None):
2882 | """Decide if it makes sense to close off the curve by moving the end point
2883 | to the start point based on start-end gap size and length of curve as
2884 | approximated by chord defined by 6 points
2885 | Parameters:
2886 | curve_id (guid): identifier of the curve object
2887 | tolerance[opt] = maximum allowable distance between start point and end
2888 | point. If omitted, the document's current absolute tolerance is used
2889 | Returns:
2890 | bool: True or False
2891 | Example:
2892 | import rhinoscriptsyntax as rs
2893 | crv = rs.GetObject("Select curve", rs.filter.curve)
2894 | if not rs.IsCurveClosed(crv) and rs.IsCurveClosable(crv):
2895 | rs.CloseCurve( crv, 0.1 )
2896 | See Also:
2897 | CloseCurve
2898 | IsCurveClosed
2899 | """
2900 | curve = rhutil.coercecurve(curve_id, -1, True)
2901 | if tolerance is None: tolerance = scriptcontext.doc.ModelAbsoluteTolerance
2902 | return curve.IsClosable(tolerance)
2903 |
2904 |
2905 | def IsCurveClosed(object_id):
2906 | """Verifies an object is a closed curve object
2907 | Parameters:
2908 | object_id (guid): the object's identifier
2909 | Returns:
2910 | bool: True if successful otherwise False. None on error
2911 | Example:
2912 | import rhinoscriptsyntax as rs
2913 | object = rs.GetObject("Select a curve")
2914 | if rs.IsCurve(object):
2915 | if rs.IsCurveClosed(oObject):
2916 | print("The object is a closed curve.")
2917 | else:
2918 | print("The object is not a closed curve.")
2919 | else:
2920 | print("The object is not a curve.")
2921 | See Also:
2922 | IsCurve
2923 | IsCurveLinear
2924 | IsCurvePeriodic
2925 | IsCurvePlanar
2926 | """
2927 | curve = rhutil.coercecurve(object_id)
2928 | return None if not curve else curve.IsClosed
2929 |
2930 |
2931 | def IsCurveInPlane(object_id, plane=None):
2932 | """Test a curve to see if it lies in a specific plane
2933 | Parameters:
2934 | object_id (guid): the object's identifier
2935 | plane (plane, optional): plane to test. If omitted, the active construction plane is used
2936 | Returns:
2937 | bool: True or False
2938 | Example:
2939 | import rhinoscriptsyntax as rs
2940 | obj = rs.GetObject("Select a curve")
2941 | if rs.IsCurve(obj) and rs.IsCurvePlanar(obj):
2942 | if rs.IsCurveInPlane(obj):
2943 | print("The curve lies in the current cplane.")
2944 | else:
2945 | print("The curve does not lie in the current cplane.")
2946 | else:
2947 | print("The object is not a planar curve.")
2948 | See Also:
2949 | IsCurve
2950 | IsCurvePlanar
2951 | """
2952 | curve = rhutil.coercecurve(object_id, -1, True)
2953 | if not plane:
2954 | plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
2955 | else:
2956 | plane = rhutil.coerceplane(plane, True)
2957 | return curve.IsInPlane(plane, scriptcontext.doc.ModelAbsoluteTolerance)
2958 |
2959 |
2960 | def IsCurveLinear(object_id, segment_index=-1):
2961 | """Verifies an object is a linear curve
2962 | Parameters:
2963 | curve_id (guid):identifier of the curve object
2964 | segment_index (number): the curve segment index if `curve_id` identifies a polycurve
2965 | Returns:
2966 | bool: True or False indicating success or failure
2967 | Example:
2968 | import rhinoscriptsyntax as rs
2969 | id = rs.GetObject("Select a curve")
2970 | if rs.IsCurve(id):
2971 | if rs.IsCurveLinear(id):
2972 | print("The object is a linear curve.")
2973 | else:
2974 | print("The object is not a linear curve.")
2975 | else:
2976 | print("The object is not a curve.")
2977 | See Also:
2978 | IsCurve
2979 | IsCurveClosed
2980 | IsCurvePeriodic
2981 | IsCurvePlanar
2982 | """
2983 | curve = rhutil.coercecurve(object_id, segment_index, True)
2984 | return curve.IsLinear()
2985 |
2986 |
2987 | def IsCurvePeriodic(curve_id, segment_index=-1):
2988 | """Verifies an object is a periodic curve object
2989 | Parameters:
2990 | curve_id (guid): identifier of the curve object
2991 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
2992 | Returns:
2993 | bool: True or False
2994 | Example:
2995 | import rhinoscriptsyntax as rs
2996 | obj = rs.GetObject("Select a curve")
2997 | if rs.IsCurve(obj):
2998 | if rs.IsCurvePeriodic(obj):
2999 | print("The object is a periodic curve.")
3000 | else:
3001 | print("The object is not a periodic curve.")
3002 | else:
3003 | print("The object is not a curve.")
3004 | See Also:
3005 | IsCurve
3006 | IsCurveClosed
3007 | IsCurveLinear
3008 | IsCurvePlanar
3009 | """
3010 | curve = rhutil.coercecurve(curve_id, segment_index, True)
3011 | return curve.IsPeriodic
3012 |
3013 |
3014 | def IsCurvePlanar(curve_id, segment_index=-1):
3015 | """Verifies an object is a planar curve
3016 | Parameters:
3017 | curve_id (guid): identifier of the curve object
3018 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
3019 | Returns:
3020 | bool: True or False indicating success or failure
3021 | Example:
3022 | import rhinoscriptsyntax as rs
3023 | obj = rs.GetObject("Select a curve")
3024 | if rs.IsCurve(obj):
3025 | if rs.IsCurvePlanar(obj):
3026 | print("The object is a planar curve.")
3027 | else:
3028 | print("The object is not a planar curve.")
3029 | else:
3030 | print("The object is not a curve.")
3031 | See Also:
3032 | IsCurve
3033 | IsCurveClosed
3034 | IsCurveLinear
3035 | IsCurvePeriodic
3036 | """
3037 | curve = rhutil.coercecurve(curve_id, segment_index, True)
3038 | tol = scriptcontext.doc.ModelAbsoluteTolerance
3039 | return curve.IsPlanar(tol)
3040 |
3041 |
3042 | def IsCurveRational(curve_id, segment_index=-1):
3043 | """Verifies an object is a rational NURBS curve
3044 | Parameters:
3045 | curve_id (guid): identifier of the curve object
3046 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
3047 | Returns:
3048 | bool: True or False indicating success or failure
3049 | Example:
3050 | import rhinoscriptsyntax as rs
3051 | obj = rs.GetObject("Select a curve")
3052 | if rs.IsCurve(obj):
3053 | if rs.IsCurveRational(obj):
3054 | print("The object is a rational NURBS curve.")
3055 | else:
3056 | print("The object is not a rational NURBS curve.")
3057 | else:
3058 | print("The object is not a curve.")
3059 | See Also:
3060 | IsCurve
3061 | IsCurveClosed
3062 | IsCurveLinear
3063 | IsCurvePeriodic
3064 | """
3065 | curve = rhutil.coercecurve(curve_id, segment_index, True)
3066 | if isinstance(curve, Rhino.Geometry.NurbsCurve): return curve.IsRational
3067 | return False
3068 |
3069 |
3070 | def IsEllipse(object_id, segment_index=-1):
3071 | """Verifies an object is an elliptical-shaped curve
3072 | Parameters:
3073 | curve_id (guid): identifier of the curve object
3074 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
3075 | Returns:
3076 | bool: True or False indicating success or failure
3077 | Example:
3078 | import rhinoscriptsyntax as rs
3079 | obj = rs.GetObject("Select an ellipse")
3080 | if rs.IsEllipse(obj):
3081 | print("The object is an ellipse.")
3082 | else:
3083 | print("The object is not an ellipse.")
3084 | See Also:
3085 | EllipseCenterPoint
3086 | EllipseQuadPoints
3087 | """
3088 | curve = rhutil.coercecurve(object_id, segment_index, True)
3089 | return curve.IsEllipse()
3090 |
3091 |
3092 | def IsLine(object_id, segment_index=-1):
3093 | """Verifies an object is a line curve
3094 | Parameters:
3095 | curve_id (guid): identifier of the curve object
3096 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
3097 | Returns:
3098 | bool: True or False indicating success or failure
3099 | Example:
3100 | import rhinoscriptsyntax as rs
3101 | obj = rs.GetObject("Select a line")
3102 | if rs.IsLine(obj):
3103 | print("The object is a line.")
3104 | else:
3105 | print("The object is not a line.")
3106 | See Also:
3107 | AddLine
3108 | """
3109 | curve = rhutil.coercecurve(object_id, segment_index, True)
3110 | if isinstance(curve, Rhino.Geometry.LineCurve): return True
3111 | rc, polyline = curve.TryGetPolyline()
3112 | if rc and polyline.Count==2: return True
3113 | return False
3114 |
3115 |
3116 | def IsPointOnCurve(object_id, point, segment_index=-1):
3117 | """Verifies that a point is on a curve
3118 | Parameters:
3119 | curve_id (guid): identifier of the curve object
3120 | point (point): the test point
3121 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
3122 | Returns:
3123 | bool: True or False indicating success or failure
3124 | Example:
3125 | import rhinoscriptsyntax as rs
3126 | obj = rs.GetObject("Select a curve")
3127 | if rs.IsCurve(obj):
3128 | point = rs.GetPoint("Pick a test point")
3129 | if point:
3130 | if rs.IsPointOnCurve(obj, point):
3131 | print("The point is on the curve")
3132 | else:
3133 | print("The point is not on the curve")
3134 | See Also:
3135 | IsCurve
3136 | """
3137 | curve = rhutil.coercecurve(object_id, segment_index, True)
3138 | point = rhutil.coerce3dpoint(point, True)
3139 | rc, t = curve.ClosestPoint(point, Rhino.RhinoMath.SqrtEpsilon)
3140 | return rc
3141 |
3142 |
3143 | def IsPolyCurve(object_id, segment_index=-1):
3144 | """Verifies an object is a PolyCurve curve
3145 | Parameters:
3146 | curve_id (guid): identifier of the curve object
3147 | segment_index (number, optional) the curve segment index if `curve_id` identifies a polycurve
3148 | Returns:
3149 | bool: True or False
3150 | Example:
3151 | import rhinoscriptsyntax as rs
3152 | obj = rs.GetObject("Select a polycurve")
3153 | if rs.IsPolyCurve(obj):
3154 | print("The object is a polycurve.")
3155 | else:
3156 | print("The object is not a polycurve.")
3157 | See Also:
3158 | PolyCurveCount
3159 | """
3160 | curve = rhutil.coercecurve(object_id, segment_index, True)
3161 | return isinstance(curve, Rhino.Geometry.PolyCurve)
3162 |
3163 |
3164 | def IsPolyline( object_id, segment_index=-1 ):
3165 | """Verifies an object is a Polyline curve object
3166 | Parameters:
3167 | curve_id (guid): identifier of the curve object
3168 | segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
3169 | Returns:
3170 | bool: True or False
3171 | Example:
3172 | import rhinoscriptsyntax as rs
3173 | obj = rs.GetObject("Select a polyline")
3174 | if rs.IsPolyline(obj):
3175 | print("The object is a polyline.")
3176 | else:
3177 | print("The object is not a polyline.")
3178 | See Also:
3179 | IsPolyline
3180 | PolylineVertices
3181 | """
3182 | curve = rhutil.coercecurve(object_id, segment_index, True)
3183 | return isinstance(curve, Rhino.Geometry.PolylineCurve)
3184 |
3185 |
3186 | def JoinCurves(object_ids, delete_input=False, tolerance=None):
3187 | """Joins multiple curves together to form one or more curves or polycurves
3188 | Parameters:
3189 | object_ids (guid): list of multiple curves
3190 | delete_input (bool, optional): delete input objects after joining
3191 | tolerance (number, optional): join tolerance. If omitted, 2.1 * document absolute
3192 | tolerance is used
3193 | Returns:
3194 | list(guid, ...): Object id representing the new curves
3195 | Example:
3196 | import rhinoscriptsyntax as rs
3197 | objs = rs.GetObjects("Select curves to join", rs.filter.curve)
3198 | if objs: rs.JoinCurves(objs)
3199 | See Also:
3200 | ExplodeCurves
3201 | IsCurve
3202 | IsCurveClosed
3203 | """
3204 | if len(object_ids)<2: raise ValueError("object_ids must contain at least 2 items")
3205 | curves = [rhutil.coercecurve(id, -1, True) for id in object_ids]
3206 | if tolerance is None:
3207 | tolerance = 2.1 * scriptcontext.doc.ModelAbsoluteTolerance
3208 | newcurves = Rhino.Geometry.Curve.JoinCurves(curves, tolerance)
3209 | rc = []
3210 | if newcurves:
3211 | rc = [scriptcontext.doc.Objects.AddCurve(crv) for crv in newcurves]
3212 | if rc and delete_input:
3213 | for id in object_ids:
3214 | id = rhutil.coerceguid(id, True)
3215 | scriptcontext.doc.Objects.Delete(id, False)
3216 | scriptcontext.doc.Views.Redraw()
3217 | return rc
3218 |
3219 |
3220 | def LineFitFromPoints(points):
3221 | """Returns a line that was fit through an array of 3D points
3222 | Parameters:
3223 | points ([point, point, ...]): a list of at least two 3D points
3224 | Returns:
3225 | line: line on success
3226 | Example:
3227 | import rhinoscriptsyntax as rs
3228 | points = rs.GetPoints()
3229 | if points and len(points)>1:
3230 | line=rs.LineFitFromPoints(points)
3231 | if line: rs.AddLine(line.From, line.To)
3232 | See Also:
3233 | AddLine
3234 | CurveEndPoint
3235 | CurveStartPoint
3236 | """
3237 | points = rhutil.coerce3dpointlist(points, True)
3238 | rc, line = Rhino.Geometry.Line.TryFitLineToPoints(points)
3239 | if rc: return line
3240 | return scriptcontext.errorhandler()
3241 |
3242 |
3243 | def MakeCurveNonPeriodic(curve_id, delete_input=False):
3244 | """Makes a periodic curve non-periodic. Non-periodic curves can develop
3245 | kinks when deformed
3246 | Parameters:
3247 | curve_id (guid): identifier of the curve object
3248 | delete_input (bool): delete the input curve. If omitted, the input curve will not be deleted.
3249 | Returns:
3250 | guid: id of the new or modified curve if successful
3251 | None: on error
3252 | Example:
3253 | import rhinoscriptsyntax as rs
3254 | curve = rs.GetObject("Select a curve", rs.filter.curve)
3255 | if rs.IsCurvePeriodic(curve): rs.MakeCurveNonPeriodic( curve )
3256 | See Also:
3257 | IsCurvePeriodic
3258 | """
3259 | curve = rhutil.coercecurve(curve_id, -1, True)
3260 | if not curve.IsPeriodic: return scriptcontext.errorhandler()
3261 | nc = curve.ToNurbsCurve()
3262 | if nc is None: return scriptcontext.errorhandler()
3263 | nc.Knots.ClampEnd( Rhino.Geometry.CurveEnd.Both )
3264 | rc = None
3265 | if delete_input:
3266 | if type(curve_id) is Rhino.DocObjects.ObjRef: pass
3267 | else: curve_id = rhutil.coerceguid(curve_id)
3268 | if curve_id:
3269 | rc = scriptcontext.doc.Objects.Replace(curve_id, nc)
3270 | if not rc: return scriptcontext.errorhandler()
3271 | rc = rhutil.coerceguid(curve_id)
3272 | else:
3273 | attrs = None
3274 | if type(scriptcontext.doc) is Rhino.RhinoDoc:
3275 | rhobj = rhutil.coercerhinoobject(curve_id)
3276 | if rhobj: attrs = rhobj.Attributes
3277 | rc = scriptcontext.doc.Objects.AddCurve(nc, attrs)
3278 | if rc==System.Guid.Empty: return scriptcontext.errorhandler()
3279 | scriptcontext.doc.Views.Redraw()
3280 | return rc
3281 |
3282 |
3283 | def MeanCurve(curve0, curve1, tolerance=None):
3284 | """Creates an average curve from two curves
3285 | Parameters:
3286 | curve0, curve1 (guid): identifiers of two curves
3287 | tolerance (number, optional): angle tolerance used to match kinks between curves
3288 | Returns:
3289 | guid: id of the new or modified curve if successful
3290 | None: on error
3291 | Example:
3292 | import rhinoscriptsyntax as rs
3293 | curve0 = rs.GetObject("Select the first curve", rs.filter.curve)
3294 | curve1 = rs.GetObject("Select the second curve", rs.filter.curve)
3295 | rs.MeanCurve( curve0, curve1 )
3296 | See Also:
3297 | UnitAngleTolerance
3298 | """
3299 | curve0 = rhutil.coercecurve(curve0, -1, True)
3300 | curve1 = rhutil.coercecurve(curve1, -1, True)
3301 | if tolerance is None: tolerance=Rhino.RhinoMath.UnsetValue
3302 | crv = Rhino.Geometry.Curve.CreateMeanCurve(curve0,curve1,tolerance)
3303 | if crv:
3304 | rc = scriptcontext.doc.Objects.AddCurve(crv)
3305 | scriptcontext.doc.Views.Redraw()
3306 | return rc
3307 |
3308 |
3309 | def MeshPolyline(polyline_id):
3310 | """Creates a polygon mesh object based on a closed polyline curve object.
3311 | The created mesh object is added to the document
3312 | Parameters:
3313 | polyline_id (guid): identifier of the polyline curve object
3314 | Returns:
3315 | guid: identifier of the new mesh object
3316 | None: on error
3317 | Example:
3318 | import rhinoscriptsyntax as rs
3319 | polyline = rs.GetObject("Select a polyline", rs.filter.curve)
3320 | if polyline:
3321 | if rs.IsPolyline(polyline) and rs.IsCurveClosed(polyline):
3322 | rs.MeshPolyline( polyline )
3323 | See Also:
3324 | IsCurveClosed
3325 | IsPolyline
3326 | """
3327 | curve = rhutil.coercecurve(polyline_id, -1, True)
3328 | ispolyline, polyline = curve.TryGetPolyline()
3329 | if not ispolyline: return scriptcontext.errorhandler()
3330 | mesh = Rhino.Geometry.Mesh.CreateFromClosedPolyline(polyline)
3331 | if not mesh: return scriptcontext.errorhandler()
3332 | rc = scriptcontext.doc.Objects.AddMesh(mesh)
3333 | scriptcontext.doc.Views.Redraw()
3334 | return rc
3335 |
3336 |
3337 | def OffsetCurve(object_id, direction, distance, normal=None, style=1):
3338 | """Offsets a curve by a distance. The offset curve will be added to Rhino
3339 | Parameters:
3340 | object_id (guid): identifier of a curve object
3341 | direction (point): point describing direction of the offset
3342 | distance (number): distance of the offset
3343 | normal (vector, optional): normal of the plane in which the offset will occur.
3344 | If omitted, the normal of the active construction plane will be used
3345 | style (number, optional): the corner style. If omitted, the style is sharp.
3346 | 0 = None
3347 | 1 = Sharp
3348 | 2 = Round
3349 | 3 = Smooth
3350 | 4 = Chamfer
3351 | Returns:
3352 | list(guid, ...): list of ids for the new curves on success
3353 | None: on error
3354 | Example:
3355 | import rhinoscriptsyntax as rs
3356 | obj = rs.GetObject("Select a curve", rs.filter.curve)
3357 | if rs.IsCurve(obj):
3358 | rs.OffsetCurve( obj, [0,0,0], 1.0 )
3359 | See Also:
3360 | OffsetCurveOnSurface
3361 | OffsetSurface
3362 | """
3363 | curve = rhutil.coercecurve(object_id, -1, True)
3364 | direction = rhutil.coerce3dpoint(direction, True)
3365 | if normal:
3366 | normal = rhutil.coerce3dvector(normal, True)
3367 | else:
3368 | normal = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane().Normal
3369 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3370 | style = System.Enum.ToObject(Rhino.Geometry.CurveOffsetCornerStyle, style)
3371 | curves = curve.Offset(direction, normal, distance, tolerance, style)
3372 | if curves is None: return scriptcontext.errorhandler()
3373 | rc = [scriptcontext.doc.Objects.AddCurve(curve) for curve in curves]
3374 | scriptcontext.doc.Views.Redraw()
3375 | return rc
3376 |
3377 |
3378 | def OffsetCurveOnSurface(curve_id, surface_id, distance_or_parameter):
3379 | """Offset a curve on a surface. The source curve must lie on the surface.
3380 | The offset curve or curves will be added to Rhino
3381 | Parameters:
3382 | curve_id, surface_id (guid): curve and surface identifiers
3383 | distance_or_parameter (number|tuple(number, number)): If a single number is passed, then this is the
3384 | distance of the offset. Based on the curve's direction, a positive value
3385 | will offset to the left and a negative value will offset to the right.
3386 | If a tuple of two values is passed, this is interpreted as the surface
3387 | U,V parameter that the curve will be offset through
3388 | Returns:
3389 | list(guid, ...): identifiers of the new curves if successful
3390 | None: on error
3391 | Example:
3392 | import rhinoscriptsyntax as rs
3393 | def TestOffset():
3394 | curve = rs.GetObject("Select curve on a surface", rs.filter.curve)
3395 | if curve is None: return False
3396 | surface = rs.GetObject("Select base surface", rs.filter.surface)
3397 | if surface is None: return False
3398 | point = rs.GetPointOnSurface( surface, "Through point" )
3399 | if point is None: return False
3400 | parameter = rs.SurfaceClosestPoint(surface, point)
3401 | rc = rs.OffsetCurveOnSurface( curve, surface, parameter )
3402 | return rc is not None
3403 |
3404 | TestOffset()
3405 | See Also:
3406 | OffsetCurve
3407 | OffsetSurface
3408 | """
3409 | curve = rhutil.coercecurve(curve_id, -1, True)
3410 | surface = rhutil.coercesurface(surface_id, True)
3411 | x = None
3412 | if type(distance_or_parameter) is list or type(distance_or_parameter) is tuple:
3413 | x = Rhino.Geometry.Point2d( distance_or_parameter[0], distance_or_parameter[1] )
3414 | else:
3415 | x = float(distance_or_parameter)
3416 | tol = scriptcontext.doc.ModelAbsoluteTolerance
3417 | curves = curve.OffsetOnSurface(surface, x, tol)
3418 | if curves is None: return scriptcontext.errorhandler()
3419 | curves = [curve.ExtendOnSurface(Rhino.Geometry.CurveEnd.Both, surface) for curve in curves]
3420 | rc = [scriptcontext.doc.Objects.AddCurve(curve) for curve in curves]
3421 | if rc: scriptcontext.doc.Views.Redraw()
3422 | return rc
3423 |
3424 |
3425 | def PlanarClosedCurveContainment(curve_a, curve_b, plane=None, tolerance=None):
3426 | """Determines the relationship between the regions bounded by two coplanar
3427 | simple closed curves
3428 | Parameters:
3429 | curve_a, curve_b (guid): identifiers of two planar, closed curves
3430 | plane (plane, optional): test plane. If omitted, the currently active construction
3431 | plane is used
3432 | tolerance (number, optional): if omitted, the document absolute tolerance is used
3433 | Returns:
3434 | number: a number identifying the relationship if successful
3435 | 0 = the regions bounded by the curves are disjoint
3436 | 1 = the two curves intersect
3437 | 2 = the region bounded by curve_a is inside of curve_b
3438 | 3 = the region bounded by curve_b is inside of curve_a
3439 | None: if not successful
3440 | Example:
3441 | import rhinoscriptsyntax as rs
3442 | curve1 = rs.GetObject("Select first curve", rs.filter.curve )
3443 | curve2 = rs.GetObject("Select second curve", rs.filter.curve )
3444 | if rs.IsCurvePlanar(curve1) and rs.IsCurvePlanar(curve2):
3445 | if rs.IsCurveClosed(curve1) and rs.IsCurveClosed(curve2):
3446 | if rs.IsCurveInPlane(curve1) and rs.IsCurveInPlane(curve2):
3447 | result = rs.PlanarClosedCurveContainment(curve1, curve2)
3448 | if result==0: print("The regions bounded by the curves are disjoint.")
3449 | elif result==1: print("The two curves intersect..")
3450 | elif result==2: print("The region bounded by Curve1 is inside of Curve2.")
3451 | else: print("The region bounded by Curve2 is inside of Curve1.")
3452 | See Also:
3453 | PlanarCurveCollision
3454 | PointInPlanarClosedCurve
3455 | """
3456 | curve_a = rhutil.coercecurve(curve_a, -1, True)
3457 | curve_b = rhutil.coercecurve(curve_b, -1, True)
3458 | if tolerance is None or tolerance<=0:
3459 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3460 | if plane:
3461 | plane = rhutil.coerceplane(plane)
3462 | else:
3463 | plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
3464 | rc = Rhino.Geometry.Curve.PlanarClosedCurveRelationship(curve_a, curve_b, plane, tolerance)
3465 | return int(rc)
3466 |
3467 |
3468 | def PlanarCurveCollision(curve_a, curve_b, plane=None, tolerance=None):
3469 | """Determines if two coplanar curves intersect
3470 | Parameters:
3471 | curve_a, curve_b (guid): identifiers of two planar curves
3472 | plane (plane, optional): test plane. If omitted, the currently active construction
3473 | plane is used
3474 | tolerance (number, optional): if omitted, the document absolute tolerance is used
3475 | Returns:
3476 | bool: True if the curves intersect; otherwise False
3477 | Example:
3478 | import rhinoscriptsyntax as rs
3479 | curve1 = rs.GetObject("Select first curve")
3480 | curve2 = rs.GetObject("Select second curve")
3481 | if( rs.IsCurvePlanar(curve1) and rs.IsCurvePlanar(curve2) and rs.IsCurveInPlane(curve1) and rs.IsCurveInPlane(curve2) ):
3482 | if rs.PlanarCurveCollision(curve1, curve2):
3483 | print("The coplanar curves intersect.")
3484 | else:
3485 | print("The coplanar curves do not intersect.")
3486 | See Also:
3487 | CurveCurveIntersection
3488 | PlanarClosedCurveContainment
3489 | PointInPlanarClosedCurve
3490 | """
3491 | curve_a = rhutil.coercecurve(curve_a, -1, True)
3492 | curve_b = rhutil.coercecurve(curve_b, -1, True)
3493 | if tolerance is None or tolerance<=0:
3494 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3495 | if plane:
3496 | plane = rhutil.coerceplane(plane)
3497 | else:
3498 | plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
3499 | return Rhino.Geometry.Curve.PlanarCurveCollision(curve_a, curve_b, plane, tolerance)
3500 |
3501 |
3502 | def PointInPlanarClosedCurve(point, curve, plane=None, tolerance=None):
3503 | """Determines if a point is inside of a closed curve, on a closed curve, or
3504 | outside of a closed curve
3505 | Parameters:
3506 | point (point|guid): text point
3507 | curve (guid): identifier of a curve object
3508 | plane (plane, optional): plane containing the closed curve and point. If omitted,
3509 | the currently active construction plane is used
3510 | tolerance (number, optional) it omitted, the document abosulte tolerance is used
3511 | Returns:
3512 | number: number identifying the result if successful
3513 | 0 = point is outside of the curve
3514 | 1 = point is inside of the curve
3515 | 2 = point in on the curve
3516 | Example:
3517 | import rhinoscriptsyntax as rs
3518 | curve = rs.GetObject("Select a planar, closed curve", rs.filter.curve)
3519 | if rs.IsCurveClosed(curve) and rs.IsCurvePlanar(curve):
3520 | point = rs.GetPoint("Pick a point")
3521 | if point:
3522 | result = rs.PointInPlanarClosedCurve(point, curve)
3523 | if result==0: print("The point is outside of the closed curve.")
3524 | elif result==1: print("The point is inside of the closed curve.")
3525 | else: print("The point is on the closed curve.")
3526 | See Also:
3527 | PlanarClosedCurveContainment
3528 | PlanarCurveCollision
3529 | """
3530 | point = rhutil.coerce3dpoint(point, True)
3531 | curve = rhutil.coercecurve(curve, -1, True)
3532 | if tolerance is None or tolerance<=0:
3533 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3534 | if plane:
3535 | plane = rhutil.coerceplane(plane)
3536 | else:
3537 | plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
3538 | rc = curve.Contains(point, plane, tolerance)
3539 | if rc==Rhino.Geometry.PointContainment.Unset: raise Exception("Curve.Contains returned Unset")
3540 | if rc==Rhino.Geometry.PointContainment.Outside: return 0
3541 | if rc==Rhino.Geometry.PointContainment.Inside: return 1
3542 | return 2
3543 |
3544 |
3545 | def PolyCurveCount(curve_id, segment_index=-1):
3546 | """Returns the number of curve segments that make up a polycurve
3547 | Parameters:
3548 | curve_id (guid): the object's identifier
3549 | segment_index (number, optional): if `curve_id` identifies a polycurve object, then `segment_index` identifies the curve segment of the polycurve to query.
3550 | Returns:
3551 | number: the number of curve segments in a polycurve if successful
3552 | None: if not successful
3553 | Example:
3554 | import rhinoscriptsyntax as rs
3555 | obj = rs.GetObject("Select a polycurve")
3556 | if rs.IsPolyCurve(obj):
3557 | count = rs.PolyCurveCount(obj)
3558 | if count: print("The polycurve contains {} curves".format(count))
3559 | See Also:
3560 | IsPolyCurve
3561 | """
3562 | curve = rhutil.coercecurve(curve_id, segment_index, True)
3563 | if isinstance(curve, Rhino.Geometry.PolyCurve): return curve.SegmentCount
3564 | raise ValueError("curve_id does not reference a polycurve")
3565 |
3566 |
3567 | def PolylineVertices(curve_id, segment_index=-1):
3568 | """Returns the vertices of a polyline curve on success
3569 | Parameters:
3570 | curve_id (guid): the object's identifier
3571 | segment_index (number, optional): if curve_id identifies a polycurve object, then segment_index identifies the curve segment of the polycurve to query.
3572 | Returns:
3573 | list(point, ...): an list of Point3d vertex points if successful
3574 | None: if not successful
3575 | Example:
3576 | import rhinoscriptsyntax as rs
3577 | obj = rs.GetObject("Select a polyline")
3578 | if rs.IsPolyline(obj):
3579 | points = rs.PolylineVertices(obj)
3580 | if points:
3581 | for point in points: rs.AddPoint(point)
3582 | See Also:
3583 | AddPolyline
3584 | IsPolyline
3585 | """
3586 | curve = rhutil.coercecurve(curve_id, segment_index, True)
3587 | rc, polyline = curve.TryGetPolyline()
3588 | if rc: return [pt for pt in polyline]
3589 | raise ValueError("curve_id does not reference a polyline")
3590 |
3591 |
3592 | def ProjectCurveToMesh(curve_ids, mesh_ids, direction):
3593 | """Projects one or more curves onto one or more surfaces or meshes
3594 | Parameters:
3595 | curve_ids ([guid, ...]): identifiers of curves to project
3596 | mesh_ids ([guid, ...]): identifiers of meshes to project onto
3597 | direction (vector): projection direction
3598 | Returns:
3599 | list(guid, ...): list of identifiers for the resulting curves.
3600 | Example:
3601 | import rhinoscriptsyntax as rs
3602 | mesh = rs.GetObject("Select mesh to project onto", rs.filter.mesh)
3603 | curve= rs.GetObject("Select curve to project", rs.filter.curve)
3604 | #Project down...
3605 | results = rs.ProjectCurveToMesh(curve, mesh, (0,0,-1))
3606 | See Also:
3607 | ProjectCurveToSurface
3608 | ProjectPointToMesh
3609 | ProjectPointToSurface
3610 | """
3611 | curve_ids = rhutil.coerceguidlist(curve_ids)
3612 | mesh_ids = rhutil.coerceguidlist(mesh_ids)
3613 | direction = rhutil.coerce3dvector(direction, True)
3614 | curves = [rhutil.coercecurve(id, -1, True) for id in curve_ids]
3615 | meshes = [rhutil.coercemesh(id, True) for id in mesh_ids]
3616 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3617 | newcurves = Rhino.Geometry.Curve.ProjectToMesh(curves, meshes, direction, tolerance)
3618 | ids = [scriptcontext.doc.Objects.AddCurve(curve) for curve in newcurves]
3619 | if ids: scriptcontext.doc.Views.Redraw()
3620 | return ids
3621 |
3622 |
3623 | def ProjectCurveToSurface(curve_ids, surface_ids, direction):
3624 | """Projects one or more curves onto one or more surfaces or polysurfaces
3625 | Parameters:
3626 | curve_ids ([guid, ...]): identifiers of curves to project
3627 | surface_ids ([guid, ...]): identifiers of surfaces to project onto
3628 | direction (vector): projection direction
3629 | Returns:
3630 | list(guid, ...): list of identifiers
3631 | Example:
3632 | import rhinoscriptsyntax as rs
3633 | surface = rs.GetObject("Select surface to project onto", rs.filter.surface)
3634 | curve = rs.GetObject("Select curve to project", rs.filter.curve)
3635 | # Project down...
3636 | results = rs.ProjectCurveToSurface(curve, surface, (0,0,-1))
3637 | See Also:
3638 | ProjectCurveToMesh
3639 | ProjectPointToMesh
3640 | ProjectPointToSurface
3641 | """
3642 | curve_ids = rhutil.coerceguidlist(curve_ids)
3643 | surface_ids = rhutil.coerceguidlist(surface_ids)
3644 | direction = rhutil.coerce3dvector(direction, True)
3645 | curves = [rhutil.coercecurve(id, -1, True) for id in curve_ids]
3646 | breps = [rhutil.coercebrep(id, True) for id in surface_ids]
3647 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3648 | newcurves = Rhino.Geometry.Curve.ProjectToBrep(curves, breps, direction, tolerance)
3649 | ids = [scriptcontext.doc.Objects.AddCurve(curve) for curve in newcurves]
3650 | if ids: scriptcontext.doc.Views.Redraw()
3651 | return ids
3652 |
3653 |
3654 | def RebuildCurve(curve_id, degree=3, point_count=10):
3655 | """Rebuilds a curve to a given degree and control point count. For more
3656 | information, see the Rhino help for the Rebuild command.
3657 | Parameters:
3658 | curve_id (guid): identifier of the curve object
3659 | degree (number, optional): new degree (must be greater than 0)
3660 | point_count (number, optional) new point count, which must be bigger than degree.
3661 | Returns:
3662 | bool: True of False indicating success or failure
3663 | Example:
3664 | import rhinoscriptsyntax as rs
3665 | curve = rs.GetObject("Select curve to rebuild", rs.filter.curve)
3666 | if curve: rs.RebuildCurve(curve, 3, 10)
3667 | See Also:
3668 | RebuildSurface
3669 | """
3670 | curve = rhutil.coercecurve(curve_id, -1, True)
3671 | if degree<1: raise ValueError("degree must be greater than 0")
3672 | newcurve = curve.Rebuild(point_count, degree, False)
3673 | if not newcurve: return False
3674 | scriptcontext.doc.Objects.Replace(curve_id, newcurve)
3675 | scriptcontext.doc.Views.Redraw()
3676 | return True
3677 |
3678 |
3679 | def RemoveCurveKnot(curve, parameter):
3680 | """Deletes a knot from a curve object.
3681 | Parameters:
3682 | curve (guid): The reference of the source object
3683 | parameter (number): The parameter on the curve. Note, if the parameter is not equal to one
3684 | of the existing knots, then the knot closest to the specified parameter
3685 | will be removed.
3686 | Returns:
3687 | bool: True of False indicating success or failure
3688 | Example:
3689 | import rhinoscriptsyntax as rs
3690 |
3691 | crv_info = rs.GetCurveObject("Select curve near knot to be removed")
3692 | if crv_info:
3693 | crv_id = crv_info[0]
3694 | crv_param = crv_info[4]
3695 | rs.RemoveCurveKnot(crv_id, crv_param)
3696 | See Also:
3697 | RemoveSurfaceKnot
3698 | """
3699 | curve_inst = rhutil.coercecurve(curve, -1, True)
3700 | success, n_param = curve_inst.GetCurveParameterFromNurbsFormParameter(parameter)
3701 | if not success: return False
3702 | n_curve = curve_inst.ToNurbsCurve()
3703 | if not n_curve: return False
3704 | success = n_curve.Knots.RemoveKnotAt(n_param)
3705 | if not success: return False
3706 | scriptcontext.doc.Objects.Replace(curve, n_curve)
3707 | scriptcontext.doc.Views.Redraw()
3708 | return True
3709 |
3710 |
3711 | def ReverseCurve(curve_id):
3712 | """Reverses the direction of a curve object. Same as Rhino's Dir command
3713 | Parameters:
3714 | curve_id (guid): identifier of the curve object
3715 | Returns:
3716 | bool: True or False indicating success or failure
3717 | Example:
3718 | import rhinoscriptsyntax as rs
3719 | curve = rs.GetObject("Select a curve to reverse")
3720 | if rs.IsCurve(curve): rs.ReverseCurve(curve)
3721 | See Also:
3722 | CurveDirectionsMatch
3723 | """
3724 | curve = rhutil.coercecurve(curve_id, -1, True)
3725 | if curve.Reverse():
3726 | curve_id = rhutil.coerceguid(curve_id, True)
3727 | scriptcontext.doc.Objects.Replace(curve_id, curve)
3728 | return True
3729 | return False
3730 |
3731 |
3732 | def SimplifyCurve(curve_id, flags=0):
3733 | """Replace a curve with a geometrically equivalent polycurve.
3734 |
3735 | The polycurve will have the following properties:
3736 | - All the polycurve segments are lines, polylines, arcs, or NURBS curves.
3737 | - The NURBS curves segments do not have fully multiple interior knots.
3738 | - Rational NURBS curves do not have constant weights.
3739 | - Any segment for which IsCurveLinear or IsArc is True is a line, polyline segment, or an arc.
3740 | - Adjacent co-linear or co-circular segments are combined.
3741 | - Segments that meet with G1-continuity have there ends tuned up so that they meet with G1-continuity to within machine precision.
3742 | - If the polycurve is a polyline, a polyline will be created
3743 |
3744 |
3745 | Parameters:
3746 | curve_id (guid): the object's identifier
3747 | flags (number, optional): the simplification methods to use. By default, all methods are used (flags = 0)
3748 | Value Description
3749 | 0 Use all methods.
3750 | 1 Do not split NURBS curves at fully multiple knots.
3751 | 2 Do not replace segments with IsCurveLinear = True with line curves.
3752 | 4 Do not replace segments with IsArc = True with arc curves.
3753 | 8 Do not replace rational NURBS curves with constant denominator with an equivalent non-rational NURBS curve.
3754 | 16 Do not adjust curves at G1-joins.
3755 | 32 Do not merge adjacent co-linear lines or co-circular arcs or combine consecutive line segments into a polyline.
3756 |
3757 | Returns:
3758 | bool: True or False
3759 | Example:
3760 | import rhinoscriptsyntax as rs
3761 | curve = rs.GetObject("Select a curve to simplify", rs.filter.curve)
3762 | if curve: rs.SimplifyCurve(curve)
3763 | See Also:
3764 | IsArc
3765 | IsCurveLinear
3766 | """
3767 | curve = rhutil.coercecurve(curve_id, -1, True)
3768 | _flags = Rhino.Geometry.CurveSimplifyOptions.All
3769 | if( flags&1 ==1 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.SplitAtFullyMultipleKnots)
3770 | if( flags&2 ==2 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.RebuildLines)
3771 | if( flags&4 ==4 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.RebuildArcs)
3772 | if( flags&8 ==8 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.RebuildRationals)
3773 | if( flags&16==16 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.AdjustG1)
3774 | if( flags&32==32 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.Merge)
3775 | tol = scriptcontext.doc.ModelAbsoluteTolerance
3776 | ang_tol = scriptcontext.doc.ModelAngleToleranceRadians
3777 | newcurve = curve.Simplify(_flags, tol, ang_tol)
3778 | if newcurve:
3779 | curve_id = rhutil.coerceguid(curve_id, True)
3780 | scriptcontext.doc.Objects.Replace(curve_id, newcurve)
3781 | scriptcontext.doc.Views.Redraw()
3782 | return True
3783 | return False
3784 |
3785 |
3786 | def SplitCurve(curve_id, parameter, delete_input=True):
3787 | """Splits, or divides, a curve at a specified parameter. The parameter must
3788 | be in the interior of the curve's domain
3789 | Parameters:
3790 | curve_id (guid): the curve to split
3791 | parameter ({number, ...]) one or more parameters to split the curve at
3792 | delete_input (bool, optional): delete the input curve
3793 | Returns:
3794 | list(guid, ....): list of new curves on success
3795 | None: on error
3796 | Example:
3797 | import rhinoscriptsyntax as rs
3798 | curve = rs.GetObject("Select a curve to split", rs.filter.curve)
3799 | if rs.IsCurve(curve):
3800 | domain = rs.CurveDomain(curve)
3801 | parameter = domain[1] / 2.0
3802 | rs.SplitCurve( curve, parameter )
3803 | See Also:
3804 | TrimCurve
3805 | """
3806 | curve = rhutil.coercecurve(curve_id, -1, True)
3807 | newcurves = curve.Split(parameter)
3808 | if newcurves is None: return scriptcontext.errorhandler()
3809 | att = None
3810 | rhobj = rhutil.coercerhinoobject(curve_id)
3811 | if rhobj: att = rhobj.Attributes
3812 | rc = [scriptcontext.doc.Objects.AddCurve(crv, att) for crv in newcurves]
3813 | if rc and delete_input:
3814 | id = rhutil.coerceguid(curve_id, True)
3815 | scriptcontext.doc.Objects.Delete(id, True)
3816 | scriptcontext.doc.Views.Redraw()
3817 | return rc
3818 |
3819 |
3820 | def TrimCurve(curve_id, interval, delete_input=True):
3821 | """Trims a curve by removing portions of the curve outside a specified interval
3822 | Parameters:
3823 | curve_id (guid):the curve to trim
3824 | interval ([number, number]): two numbers identifying the interval to keep. Portions of
3825 | the curve before domain[0] and after domain[1] will be removed. If the
3826 | input curve is open, the interval must be increasing. If the input
3827 | curve is closed and the interval is decreasing, then the portion of
3828 | the curve across the start and end of the curve is returned
3829 | delete_input (bool): delete the input curve. If omitted the input curve is deleted.
3830 | Returns:
3831 | list(guid, ...): identifier of the new curve on success
3832 | None: on failure
3833 | Example:
3834 | import rhinoscriptsyntax as rs
3835 | curve = rs.GetObject("Select a curve to trim", rs.filter.curve)
3836 | if rs.IsCurve(curve):
3837 | domain = rs.CurveDomain(curve)
3838 | domain[1] /= 2.0
3839 | rs.TrimCurve( curve, domain )
3840 | See Also:
3841 | SplitCurve
3842 | """
3843 | curve = rhutil.coercecurve(curve_id, -1, True)
3844 | if interval[0]==interval[1]: raise ValueError("interval values are equal")
3845 | newcurve = curve.Trim(interval[0], interval[1])
3846 | if not newcurve: return scriptcontext.errorhandler()
3847 | att = None
3848 | rhobj = rhutil.coercerhinoobject(curve_id)
3849 | if rhobj: att = rhobj.Attributes
3850 | rc = scriptcontext.doc.Objects.AddCurve(newcurve, att)
3851 | if delete_input:
3852 | id = rhutil.coerceguid(curve_id, True)
3853 | scriptcontext.doc.Objects.Delete(id, True)
3854 | scriptcontext.doc.Views.Redraw()
3855 | return rc
3856 |
3857 |
3858 | def ChangeCurveDegree(object_id, degree):
3859 | """Changes the degree of a curve object. For more information see the Rhino help file for the ChangeDegree command.
3860 | Parameters:
3861 | object_id (guid): the object's identifier.
3862 | degree (number): the new degree.
3863 | Returns:
3864 | bool: True of False indicating success or failure.
3865 | None: on failure
3866 | Example:
3867 |
3868 | See Also:
3869 | IsCurve
3870 | CurveDegree
3871 | """
3872 | curve = rhutil.coercerhinoobject(object_id)
3873 | if not curve: return None
3874 | if not isinstance(curve, Rhino.DocObjects.CurveObject): return None
3875 |
3876 | curve = curve.CurveGeometry
3877 | if not isinstance(curve, Rhino.Geometry.NurbsCurve):
3878 | curve = curve.ToNurbsCurve()
3879 |
3880 | max_nurbs_degree = 11
3881 | if degree < 1 or degree > max_nurbs_degree or curve.Degree == degree:
3882 | return None
3883 |
3884 | r = False
3885 | if curve.IncreaseDegree(degree):
3886 | r = scriptcontext.doc.Objects.Replace(object_id, curve)
3887 | return r
3888 |
3889 |
3890 | def AddTweenCurves(from_curve_id, to_curve_id, number_of_curves = 1, method = 0, sample_number = 10):
3891 | """Creates curves between two open or closed input curves.
3892 | Parameters:
3893 | from_curve_id (guid): identifier of the first curve object.
3894 | to_curve_id (guid): identifier of the second curve object.
3895 | number_of_curves (number): The number of curves to create. The default is 1.
3896 | method (number): The method for refining the output curves, where:
3897 | 0: (Default) Uses the control points of the curves for matching. So the first control point of first curve is matched to first control point of the second curve.
3898 | 1: Refits the output curves like using the FitCurve method. Both the input curve and the output curve will have the same structure. The resulting curves are usually more complex than input unless input curves are compatible.
3899 | 2: Input curves are divided to the specified number of points on the curve, corresponding points define new points that output curves go through. If you are making one tween curve, the method essentially does the following: 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.
3900 | sample_number (number): The number of samples points to use if method is 2. The default is 10.
3901 | Returns:
3902 | list(guid, ...): The identifiers of the new tween objects if successful, None on error.
3903 | Example:
3904 | import rhinoscriptsyntax as rs
3905 | curveA = rs.GetObject("Select first curve", rs.filter.curve)
3906 | curveB = rs.GetObject("Select second curve", rs.filter.curve)
3907 | arrResult = rs.AddTweenCurves(curveA, curveB, 6, 2, 30)
3908 | """
3909 | curve0 = rhutil.coercecurve(from_curve_id, -1, True)
3910 | curve1 = rhutil.coercecurve(to_curve_id, -1, True)
3911 | out_curves = 0
3912 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3913 | if method == 0:
3914 | out_curves = Rhino.Geometry.Curve.CreateTweenCurves(curve0, curve1, number_of_curves, tolerance)
3915 | elif method == 1:
3916 | out_curves = Rhino.Geometry.Curve.CreateTweenCurvesWithMatching(curve0, curve1, number_of_curves, tolerance)
3917 | elif method == 2:
3918 | out_curves = Rhino.Geometry.Curve.CreateTweenCurvesWithSampling(curve0, curve1, number_of_curves, sample_number, tolerance)
3919 | else: raise ValueError("method must be 0, 1, or 2")
3920 | curves = None
3921 | if out_curves:
3922 | curves = []
3923 | for curve in out_curves:
3924 | if curve and curve.IsValid:
3925 | rc = scriptcontext.doc.Objects.AddCurve(curve)
3926 | curve.Dispose()
3927 | if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
3928 | curves.append(rc)
3929 | scriptcontext.doc.Views.Redraw()
3930 | return curves
3931 |
```