#
tokens: 50912/50000 1/82 files (page 8/8)
lines: on (toggle) GitHub
raw markdown copy reset
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 | 
```
Page 8/8FirstPrevNextLast