#
tokens: 38765/50000 1/82 files (page 7/7)
lines: off (toggle) GitHub
raw markdown copy
This is page 7 of 7. Use http://codebase.md/jingcheng-chen/rhinomcp?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
import math

import System

import Rhino

import scriptcontext

import rhinocompat as compat
from rhinoscript import utility as rhutil


def AddArc(plane, radius, angle_degrees):
    """Adds an arc curve to the document
    Parameters:
      plane (str): plane on which the arc will lie. The origin of the plane will be
        the center point of the arc. x-axis of the plane defines the 0 angle
        direction.
      radius(number): radius of the arc
      angle_degrees (number): interval of arc in degrees
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as  rs
      plane = rs.WorldXYPlane()
      plane = rs.RotatePlane(plane,  45.0, [0,0,1])
      rs.AddArc( plane, 5.0, 45.0  )
    See Also:
      AddArc3Pt
      ArcAngle
      ArcCenterPoint
      ArcMidPoint
      ArcRadius
      IsArc
    """
    plane = rhutil.coerceplane(plane, True)
    radians = math.radians(angle_degrees)
    arc = Rhino.Geometry.Arc(plane, radius, radians)
    rc = scriptcontext.doc.Objects.AddArc(arc)
    if rc==System.Guid.Empty: raise Exception("Unable to add arc to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddArc3Pt(start, end, point_on_arc):
    """Adds a 3-point arc curve to the document
    Parameters:
      start, end (point|guid): endpoints of the arc
      point_on_arc (point|guid): a point on the arc
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as rs
      start = rs.GetPoint("Start of arc")
      if start is not None:
          end = rs.GetPoint("End of arc")
          if end is not None:
              pton = rs.GetPoint("Point on arc")
              if pton is not None:
                  rs.AddArc3Pt(start, end, pton)
    See Also:
      AddArc
      ArcAngle
      ArcCenterPoint
      ArcMidPoint
      ArcRadius
      IsArc
    """
    start = rhutil.coerce3dpoint(start, True)
    end = rhutil.coerce3dpoint(end, True)
    pton = rhutil.coerce3dpoint(point_on_arc, True)
    arc = Rhino.Geometry.Arc(start, pton, end)
    rc = scriptcontext.doc.Objects.AddArc(arc)
    if rc==System.Guid.Empty: raise Exception("Unable to add arc to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddArcPtTanPt(start, direction, end):
    """Adds an arc curve, created from a start point, a start direction, and an
    end point, to the document
    Parameters:
      start (point): the starting point of the arc
      direction (vector): the arc direction at start
      end (point): the ending point of the arc
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as rs
      pick = rs.GetCurveObject("Select curve to extend")
      point = rs.GetPoint("End of extension")
      domain = rs.CurveDomain(pick[0])
      if abs(pick[4]-domain[0]) < abs(pick[4]-domain[1]):
          origin = rs.CurveStartPoint(pick[0])
          tangent = rs.VectorReverse(rs.CurveTangent(pick[0], domain[0]))
      else:
          origin = rs.CurveEndPoint(pick[0])
          tangent = rs.CurveTangent(pick[0], domain[1])
      rs.AddArcPtTanPt(origin, tangent, point)
    See Also:
      AddArc
      AddArc3Pt
      IsArc
    """
    start = rhutil.coerce3dpoint(start, True)
    direction = rhutil.coerce3dvector(direction, True)
    end = rhutil.coerce3dpoint(end, True)
    arc = Rhino.Geometry.Arc(start, direction, end)
    rc = scriptcontext.doc.Objects.AddArc(arc)
    if rc==System.Guid.Empty: raise Exception("Unable to add arc to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddBlendCurve(curves, parameters, reverses, continuities):
    """Makes a curve blend between two curves
    Parameters:
      curves ([guid|curve, guid|curve]): list of two curves
      parameters ([number, number]): list of two curve parameters defining the blend end points
      reverses ([bool, bool]): list of two boolean values specifying to use the natural or opposite direction of the curve
      continuities ([number, number]): list of two numbers specifying continuity at end points
                                            0 = position
                                            1 = tangency
                                            2 = curvature
    Returns:
      guid: identifier of new curve on success
    Example:
        import rhinoscriptsyntax as rs
        curve0 = rs.AddLine((0,0,0), (0,9,0))
        curve1 = rs.AddLine((1,10,0), (10,10,0))
        curves = curve0, curve1
        domain_crv0 = rs.CurveDomain(curve0)
        domain_crv1 = rs.CurveDomain(curve1)
        params = domain_crv0[1], domain_crv1[0]
        revs = False, True
        cont = 2,2
        rs.AddBlendCurve( curves, params, revs, cont )
    See Also:
      AddFilletCurve
    """
    crv0 = rhutil.coercecurve(curves[0], -1, True)
    crv1 = rhutil.coercecurve(curves[1], -1, True)
    c0 = System.Enum.ToObject(Rhino.Geometry.BlendContinuity, continuities[0])
    c1 = System.Enum.ToObject(Rhino.Geometry.BlendContinuity, continuities[1])
    curve = Rhino.Geometry.Curve.CreateBlendCurve(crv0, parameters[0], reverses[0], c0, crv1, parameters[1], reverses[1], c1)
    rc = scriptcontext.doc.Objects.AddCurve(curve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddCircle(plane_or_center, radius):
    """Adds a circle curve to the document
    Parameters:
      plane_or_center (point|plane): plane on which the circle will lie. If a point is
        passed, this will be the center of the circle on the active
        construction plane
      radius (number): the radius of the circle
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as rs
      plane = rs.WorldXYPlane()
      rs.AddCircle( plane, 5.0 )
    See Also:
      AddCircle3Pt
      CircleCenterPoint
      CircleCircumference
      CircleRadius
      IsCircle
    """
    rc = None
    plane = rhutil.coerceplane(plane_or_center, False)
    if plane:
        circle = Rhino.Geometry.Circle(plane, radius)
        rc = scriptcontext.doc.Objects.AddCircle(circle)
    else:
        center = rhutil.coerce3dpoint(plane_or_center, True)
        view = scriptcontext.doc.Views.ActiveView
        plane = view.ActiveViewport.ConstructionPlane()
        plane.Origin = center
        circle = Rhino.Geometry.Circle(plane, radius)
        rc = scriptcontext.doc.Objects.AddCircle(circle)
    if rc==System.Guid.Empty: raise Exception("Unable to add circle to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddCircle3Pt(first, second, third):
    """Adds a 3-point circle curve to the document
    Parameters:
      first, second, third (point|guid): points on the circle
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as rs
      point1 = rs.GetPoint("First point on circle")
      if point1:
          point2 = rs.GetPoint("Second point on circle")
          if point2:
              point3 = rs.GetPoint("Third point on circle")
              if point3:
                  rs.AddCircle3Pt(point1, point2, point3)
    See Also:
      AddCircle
      CircleCenterPoint
      CircleCircumference
      CircleRadius
      IsCircle
    """
    start = rhutil.coerce3dpoint(first, True)
    end = rhutil.coerce3dpoint(second, True)
    third = rhutil.coerce3dpoint(third, True)
    circle = Rhino.Geometry.Circle(start, end, third)
    rc = scriptcontext.doc.Objects.AddCircle(circle)
    if rc==System.Guid.Empty: raise Exception("Unable to add circle to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddCurve(points, degree=3):
    """Adds a control points curve object to the document
    Parameters:
      points ([point|guid, ...]) a list of points
      degree (number): degree of the curve
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as rs
      points = rs.GetPoints(True, message1="Pick curve point")
      if points: rs.AddCurve(points)
    See Also:
      AddInterpCurve
      IsCurve
    """
    points = rhutil.coerce3dpointlist(points, True)
    curve = Rhino.Geometry.Curve.CreateControlPointCurve(points, degree)
    if not curve: raise Exception("unable to create control point curve from given points")
    rc = scriptcontext.doc.Objects.AddCurve(curve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddEllipse(plane, radiusX, radiusY):
    """Adds an elliptical curve to the document
    Parameters:
      plane (plane) the plane on which the ellipse will lie. The origin of
              the plane will be the center of the ellipse
      radiusX, radiusY (number): radius in the X and Y axis directions
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      plane = rs.WorldXYPlane()
      rs.AddEllipse( plane, 5.0, 10.0 )
    See Also:
      AddEllipse3Pt
      IsEllipse
      EllipseCenterPoint
      EllipseQuadPoints
    """
    plane = rhutil.coerceplane(plane, True)
    ellipse = Rhino.Geometry.Ellipse(plane, radiusX, radiusY)
    rc = scriptcontext.doc.Objects.AddEllipse(ellipse)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddEllipse3Pt(center, second, third):
    """Adds a 3-point elliptical curve to the document
    Parameters:
      center (point|guid): center point of the ellipse
      second (point|guid): end point of the x axis
      third  (point|guid): end point of the y axis
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      center = (0,0,0)
      second = (5,0,0)
      third = (0,10,0)
      rs.AddEllipse3Pt( center, second, third )
    See Also:
      AddEllipse
      IsEllipse
      EllipseCenterPoint
      EllipseQuadPoints
    """
    center = rhutil.coerce3dpoint(center, True)
    second = rhutil.coerce3dpoint(second, True)
    third = rhutil.coerce3dpoint(third, True)
    ellipse = Rhino.Geometry.Ellipse(center, second, third)
    rc = scriptcontext.doc.Objects.AddEllipse(ellipse)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddFilletCurve(curve0id, curve1id, radius=1.0, base_point0=None, base_point1=None):
    """Adds a fillet curve between two curve objects
    Parameters:
      curve0id (guid): identifier of the first curve object
      curve1id (guid): identifier of the second curve object
      radius (number, optional): fillet radius
      base_point0 (point|guid, optional): base point of the first curve. If omitted,
                          starting point of the curve is used
      base_point1 (point|guid, optional): base point of the second curve. If omitted,
                          starting point of the curve is used
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      curve0 = rs.AddLine([0,0,0], [5,1,0])
      curve1 = rs.AddLine([0,0,0], [1,5,0])
      rs.AddFilletCurve( curve0, curve1 )
    See Also:
      CurveFilletPoints
    """
    if base_point0: base_point0 = rhutil.coerce3dpoint(base_point0, True)
    else: base_point0 = Rhino.Geometry.Point3d.Unset
    if base_point1: base_point1 = rhutil.coerce3dpoint(base_point1, True)
    else: base_point1 = Rhino.Geometry.Point3d.Unset
    curve0 = rhutil.coercecurve(curve0id, -1, True)
    curve1 = rhutil.coercecurve(curve1id, -1, True)
    crv0_t = 0.0
    if base_point0==Rhino.Geometry.Point3d.Unset:
        crv0_t = curve0.Domain.Min
    else:
        rc, t = curve0.ClosestPoint(base_point0, 0.0)
        if not rc: raise Exception("ClosestPoint failed")
        crv0_t = t
    crv1_t = 0.0
    if base_point1==Rhino.Geometry.Point3d.Unset:
        crv1_t = curve1.Domain.Min
    else:
        rc, t = curve1.ClosestPoint(base_point1, 0.0)
        if not rc: raise Exception("ClosestPoint failed")
        crv1_t = t
    arc = Rhino.Geometry.Curve.CreateFillet(curve0, curve1, radius, crv0_t, crv1_t)
    rc = scriptcontext.doc.Objects.AddArc(arc)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddInterpCrvOnSrf(surface_id, points):
    """Adds an interpolated curve object that lies on a specified
    surface.  Note, this function will not create periodic curves,
    but it will create closed curves.
    Parameters:
      surface_id (guid): identifier of the surface to create the curve on
      points ([point|guid, point|guid, ...])list of 3D points that lie on the specified surface.
               The list must contain at least 2 points
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      surface_id = rs.GetObject("Select surface to draw curve on", rs.filter.surface)
      if surface_id:
          point1 = rs.GetPointOnSurface( surface_id, "First point on surface")
          if point1:
              point2 = rs.GetPointOnSurface( surface_id, "Second point on surface")
              if point2:
                  rs.AddInterpCrvOnSrf( surface_id, [point1, point2])
    See Also:
      AddCurve
      AddInterpCurve
      AddInterpCrvOnSrfUV
    """
    surface = rhutil.coercesurface(surface_id, True)
    points = rhutil.coerce3dpointlist(points, True)
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    curve = surface.InterpolatedCurveOnSurface(points, tolerance)
    if not curve: raise Exception("unable to create InterpolatedCurveOnSurface")
    rc = scriptcontext.doc.Objects.AddCurve(curve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddInterpCrvOnSrfUV(surface_id, points):
    """Adds an interpolated curve object based on surface parameters,
    that lies on a specified surface. Note, this function will not
    create periodic curves, but it will create closed curves.
    Parameters:
      surface_id (guid): identifier of the surface to create the curve on
      points ([[number, number}, [number,number], ...]): a list of 2D surface parameters. The list must contain
                                                         at least 2 sets of parameters
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      surface_id = rs.GetObject("Select surface to draw curve on", rs.filter.surface)
      if surface_id:
          domainU = rs.SurfaceDomain( surface_id, 0)
          u0 = domainU[0]/2
          u1 = domainU[1]/2
          domainV = rs.SurfaceDomain( surface_id, 1)
          v0 = domainV[0]/2
          v1 = domainV[1]/2
          rs.AddInterpCrvOnSrfUV( surface_id, [[u0,v0],[u1,v1]])
    See Also:
      AddCurve
      AddInterpCurve
      AddInterpCrvOnSrf
    """
    surface = rhutil.coercesurface(surface_id, True)
    points = rhutil.coerce2dpointlist(points)
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    curve = surface.InterpolatedCurveOnSurfaceUV(points, tolerance)
    if not curve: raise Exception("unable to create InterpolatedCurveOnSurfaceUV")
    rc = scriptcontext.doc.Objects.AddCurve(curve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddInterpCurve(points, degree=3, knotstyle=0, start_tangent=None, end_tangent=None):
    """Adds an interpolated curve object to the document. Options exist to make
    a periodic curve or to specify the tangent at the endpoints. The resulting
    curve is a non-rational NURBS curve of the specified degree.
    Parameters:
      points (point|guid, point|guid, ...]): a list containing 3D points to interpolate. For periodic curves,
          if the final point is a duplicate of the initial point, it is
          ignored. The number of control points must be >= (degree+1).
      degree (number, optional): The degree of the curve (must be >=1).
          Periodic curves must have a degree >= 2. For knotstyle = 1 or 2,
          the degree must be 3. For knotstyle = 4 or 5, the degree must be odd
      knotstyle(opt):
          0 Uniform knots.  Parameter spacing between consecutive knots is 1.0.
          1 Chord length spacing.  Requires degree = 3 with arrCV1 and arrCVn1 specified.
          2 Sqrt (chord length).  Requires degree = 3 with arrCV1 and arrCVn1 specified.
          3 Periodic with uniform spacing.
          4 Periodic with chord length spacing.  Requires an odd degree value.
          5 Periodic with sqrt (chord length) spacing.  Requires an odd degree value.
      start_tangent (vector, optional): a vector that specifies a tangency condition at the
          beginning of the curve. If the curve is periodic, this argument must be omitted.
      end_tangent (vector, optional): 3d vector that specifies a tangency condition at the
          end of the curve. If the curve is periodic, this argument must be omitted.
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      points = (0,0,0), (1,1,0), (2,0,0), (3,1,0), (4,0,0), (5,1,0)
      rs.AddInterpCurve(points)
    See Also:
      AddCurve
      CurvePointCount
      IsCurve
    """
    points = rhutil.coerce3dpointlist(points, True)
    if not start_tangent: start_tangent = Rhino.Geometry.Vector3d.Unset
    start_tangent = rhutil.coerce3dvector(start_tangent, True)
    if not end_tangent: end_tangent = Rhino.Geometry.Vector3d.Unset
    end_tangent = rhutil.coerce3dvector(end_tangent, True)
    knotstyle = System.Enum.ToObject(Rhino.Geometry.CurveKnotStyle, knotstyle)
    curve = Rhino.Geometry.Curve.CreateInterpolatedCurve(points, degree, knotstyle, start_tangent, end_tangent)
    if not curve: raise Exception("unable to CreateInterpolatedCurve")
    rc = scriptcontext.doc.Objects.AddCurve(curve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddLine(start, end):
    """Adds a line curve to the current model.
    Parameters:
      start, end (point|guid) end points of the line
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as rs
      start = rs.GetPoint("Start of line")
      if start:
          end = rs.GetPoint("End of line")
          if end: rs.AddLine(start, end)
    See Also:
      CurveEndPoint
      CurveStartPoint
      IsLine
    """
    start = rhutil.coerce3dpoint(start, True)
    end = rhutil.coerce3dpoint(end, True)
    rc = scriptcontext.doc.Objects.AddLine(start, end)
    if rc==System.Guid.Empty: raise Exception("Unable to add line to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddNurbsCurve(points, knots, degree, weights=None):
    """Adds a NURBS curve object to the document
    Parameters:
      points ([guid|point, guid|point, ...]): a list containing 3D control points
      knots ([number, number, ...]): Knot values for the curve. The number of elements in knots must
          equal the number of elements in points plus degree minus 1
      degree (number): degree of the curve. must be greater than of equal to 1
      weights([number, number, ...], optional) weight values for the curve. Number of elements should
          equal the number of elements in points. Values must be greater than 0
    Returns:
      guid: the identifier of the new object if successful, otherwise None
    Example:
      import rhinoscriptsyntax as rs
      curve_id = rs.GetObject("Pick a curve", rs.filter.curve)
      if curve_id:
          points = rs.CurvePoints(curve_id)
          knots = rs.CurveKnots(curve_id)
          degree = rs.CurveDegree(curve_id)
          newcurve = rs.AddNurbsCurve( points, knots, degree)
          if newcurve: rs.SelectObject(newcurve)
    See Also:
      CurveDegree
      CurveKnots
      CurvePoints
    """
    points = rhutil.coerce3dpointlist(points, True)
    cvcount = len(points)
    knotcount = cvcount + degree - 1
    if len(knots)!=knotcount:
        raise Exception("Number of elements in knots must equal the number of elements in points plus degree minus 1")
    if weights and len(weights)!=cvcount:
        raise Exception("Number of elements in weights should equal the number of elements in points")
    rational = (weights!=None)
    
    nc = Rhino.Geometry.NurbsCurve(3,rational,degree+1,cvcount)
    if rational: 
        for i in compat.RANGE(cvcount):
            nc.Points.SetPoint(i, points[i], weights[i])
    else:
        for i in compat.RANGE(cvcount):
            nc.Points.SetPoint(i, points[i])
    for i in compat.RANGE(knotcount): nc.Knots[i] = knots[i]
    rc = scriptcontext.doc.Objects.AddCurve(nc)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddPolyline(points, replace_id=None):
    """Adds a polyline curve to the current model
    Parameters:
      points ([guid|point, guid|point, ...]): list of 3D points. Duplicate, consecutive points will be
               removed. The list must contain at least two points. If the
               list contains less than four points, then the first point and
               last point must be different.
      replace_id (guid, optional): If set to the id of an existing object, the object
               will be replaced by this polyline
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      points = rs.GetPoints(True)
      if points: rs.AddPolyline(points)
    See Also:
      IsPolyline
    """
    points = rhutil.coerce3dpointlist(points, True)
    if replace_id: replace_id = rhutil.coerceguid(replace_id, True)
    rc = System.Guid.Empty
    pl = Rhino.Geometry.Polyline(points)
    pl.DeleteShortSegments(scriptcontext.doc.ModelAbsoluteTolerance)
    if replace_id:
        if scriptcontext.doc.Objects.Replace(replace_id, pl):
            rc = replace_id
    else:
        rc = scriptcontext.doc.Objects.AddPolyline(pl)
    if rc==System.Guid.Empty: raise Exception("Unable to add polyline to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddRectangle(plane, width, height):
    """Add a rectangular curve to the document
    Parameters:
      plane (plane) plane on which the rectangle will lie
      width, height (number): width and height of rectangle as measured along the plane's
        x and y axes
    Returns:
      guid: id of new rectangle
    Example:
      import rhinoscriptsyntax as rs
      plane = rs.WorldXYPlane()
      plane = rs.RotatePlane(plane, 45.0, [0,0,1])
      rs.AddRectangle( plane, 5.0, 15.0 )
    See Also:
      
    """
    plane = rhutil.coerceplane(plane, True)
    rect = Rhino.Geometry.Rectangle3d(plane, width, height)
    poly = rect.ToPolyline()
    rc = scriptcontext.doc.Objects.AddPolyline(poly)
    if rc==System.Guid.Empty: raise Exception("Unable to add polyline to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddSpiral(point0, point1, pitch, turns, radius0, radius1=None):
    """Adds a spiral or helical curve to the document
    Parameters:
      point0 (point|guid): helix axis start point or center of spiral
      point1 (point|guid): helix axis end point or point normal on spiral plane
      pitch (number): distance between turns. If 0, then a spiral. If > 0 then the
              distance between helix "threads"
      turns (number): number of turns
      radius0 (number): starting radius of spiral
      radius1 (number, optional): ending radius of spiral. If omitted, the starting radius is used for the complete spiral.
    Returns:
      guid: id of new curve on success
    Example:
      import rhinoscriptsyntax as rs
      point0 = (0,0,0)
      point1 = (0,0,10)
      pitch = 1
      turns = 10
      radius0 = 5.0
      radius1 = 8.0
      rs.AddSpiral(point0, point1, pitch, turns, radius0, radius1)
    See Also:
      
    """
    if radius1 is None: radius1 = radius0
    point0 = rhutil.coerce3dpoint(point0, True)
    point1 = rhutil.coerce3dpoint(point1, True)
    dir = point1 - point0
    plane = Rhino.Geometry.Plane(point0, dir)
    point2 = point0 + plane.XAxis
    curve = Rhino.Geometry.NurbsCurve.CreateSpiral(point0, dir, point2, pitch, turns, radius0, radius1)
    rc = scriptcontext.doc.Objects.AddCurve(curve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddSubCrv(curve_id, param0, param1):
    """Add a curve object based on a portion, or interval of an existing curve
    object. Similar in operation to Rhino's SubCrv command
    Parameters:
      curve_id (guid): identifier of a closed planar curve object
      param0, param1 (number): first and second parameters on the source curve
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      getresult = rs.GetCurveObject()
      if getresult:
          curve_id = getresult[0]
          point0 = rs.GetPointOnCurve( curve_id )
          if point0:
              point1 = rs.GetPointOnCurve( curve_id )
              if point1:
                  t0 = rs.CurveClosestPoint( curve_id, point0)
                  t1 = rs.CurveClosestPoint( curve_id, point1)
                  rs.AddSubCrv( curve_id, t0, t1 )
    See Also:
      CurveClosestPoint
      GetCurveObject
      GetPointOnCurve
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    trimcurve = curve.Trim(param0, param1)
    if not trimcurve: raise Exception("unable to trim curve")
    rc = scriptcontext.doc.Objects.AddCurve(trimcurve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def ArcAngle(curve_id, segment_index=-1):
    """Returns the angle of an arc curve object.
    Parameters:
      curve_id (guid): identifier of a curve object
      segment_index (number, optional): identifies the curve segment if
      curve_id (guid): identifies a polycurve
    Returns:
      number: The angle in degrees if successful.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select arc")
      if rs.IsArc(id):
          angle = rs.ArcAngle(id)
          print("Arc angle: {}".format(angle))
    See Also:
      AddArc3Pt
      ArcCenterPoint
      ArcMidPoint
      ArcRadius
      IsArc
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
    if not rc: raise Exception("curve is not arc")
    return arc.AngleDegrees


def ArcCenterPoint(curve_id, segment_index=-1):
    """Returns the center point of an arc curve object
    Parameters:
      curve_id (guid): identifier of a curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      point: The 3D center point of the arc if successful.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select arc")
      if rs.IsArc(id):
      point = rs.ArcCenterPoint(id)
      rs.AddPoint(point)
    See Also:
      AddArc3Pt
      ArcAngle
      ArcMidPoint
      ArcRadius
      IsArc
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
    if not rc: raise Exception("curve is not arc")
    return arc.Center


def ArcMidPoint(curve_id, segment_index=-1):
    """Returns the mid point of an arc curve object
    Parameters:
      curve_id (guid): identifier of a curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      point: The 3D mid point of the arc if successful.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select arc")
      if rs.IsArc(id):
          point = rs.ArcMidPoint(id)
          rs.AddPoint(point)
    See Also:
      AddArc3Pt
      ArcAngle
      ArcCenterPoint
      ArcRadius
      IsArc
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
    if not rc: raise Exception("curve is not arc")
    return arc.MidPoint


def ArcRadius(curve_id, segment_index=-1):
    """Returns the radius of an arc curve object
    Parameters:
      curve_id (guid): identifier of a curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      number: The radius of the arc if successful.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select arc")
      if rs.IsArc(id):
          radius = rs.ArcRadius(id)
          print("Arc radius: {}".format(radius))
    See Also:
      AddArc3Pt
      ArcAngle
      ArcCenterPoint
      ArcMidPoint
      IsArc
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, arc = curve.TryGetArc( Rhino.RhinoMath.ZeroTolerance )
    if not rc: raise Exception("curve is not arc")
    return arc.Radius


def CircleCenterPoint(curve_id, segment_index=-1, return_plane=False):
    """Returns the center point of a circle curve object
    Parameters:
      curve_id (guid): identifier of a curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
      return_plane (bool, optional): if True, the circle's plane is returned. If omitted the plane is not returned.
    Returns:
      point: The 3D center point of the circle if successful.
      plane: The plane of the circle if return_plane is True
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select circle")
      if rs.IsCircle(id):
          point = rs.CircleCenterPoint(id)
          rs.AddPoint( point )
    See Also:
      AddCircle
      AddCircle3Pt
      CircleCircumference
      CircleRadius
      IsCircle
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, circle = curve.TryGetCircle(Rhino.RhinoMath.ZeroTolerance)
    if not rc: raise Exception("curve is not circle")
    if return_plane: return circle.Plane
    return circle.Center


def CircleCircumference(curve_id, segment_index=-1):
    """Returns the circumference of a circle curve object
    Parameters:
      curve_id (guid): identifier of a curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      number: The circumference of the circle if successful.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select circle")
      if rs.IsCircle(id):
          circumference = rs.CircleCircumference(id)
          print("Circle circumference: {}".format(circumference))
    See Also:
      AddCircle
      AddCircle3Pt
      CircleCenterPoint
      CircleRadius
      IsCircle
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, circle = curve.TryGetCircle( Rhino.RhinoMath.ZeroTolerance )
    if not rc: raise Exception("curve is not circle")
    return circle.Circumference


def CircleRadius(curve_id, segment_index=-1):
    """Returns the radius of a circle curve object
    Parameters:
      curve_id (guid): identifier of a curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      number: The radius of the circle if successful.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select circle")
      if rs.IsCircle(id):
          radius = rs.CircleRadius(id)
          print("Circle radius: {}".format(radius))
    See Also:
      AddCircle
      AddCircle3Pt
      CircleCenterPoint
      CircleCircumference
      IsCircle
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, circle = curve.TryGetCircle( Rhino.RhinoMath.ZeroTolerance )
    if not rc: raise Exception("curve is not circle")
    return circle.Radius


def CloseCurve(curve_id, tolerance=-1.0):
    """Closes an open curve object by making adjustments to the end points so
    they meet at a point
    Parameters:
      curve_id (guid): identifier of a curve object
      tolerance (number, optional): maximum allowable distance between start and end
                                    point. If omitted, the current absolute tolerance is used
    Returns:
      guid: id of the new curve object if successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select curve", rs.filter.curve)
      if not rs.IsCurveClosed(obj) and rs.IsCurveClosable(obj):
          rs.CloseCurve( obj )
    See Also:
      IsCurveClosable
      IsCurveClosed
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if curve.IsClosed: return curve_id
    if tolerance<0.0: tolerance = Rhino.RhinoMath.ZeroTolerance
    if not curve.MakeClosed(tolerance): return scriptcontext.errorhandler()
    rc = scriptcontext.doc.Objects.AddCurve(curve)
    if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def ClosedCurveOrientation(curve_id, direction=(0,0,1)):
    """Determine the orientation (counter-clockwise or clockwise) of a closed,
    planar curve
    Parameters:
      curve_id (guid): identifier of a curve object
      direction (vector, optional): 3d vector that identifies up, or Z axs, direction of
                                    the plane to test against
    Returns:
      number: 1 if the curve's orientation is counter-clockwise
             -1 if the curve's orientation is clockwise
              0 if unable to compute the curve's orientation
    Example:
    See Also:
    """
    curve = rhutil.coercecurve(curve_id, -1 ,True)
    direction = rhutil.coerce3dvector(direction, True)
    if not curve.IsClosed: return 0
    orientation = curve.ClosedCurveOrientation(direction)
    return int(orientation)


def ConvertCurveToPolyline(curve_id, angle_tolerance=5.0, tolerance=0.01, delete_input=False, min_edge_length=0, max_edge_length=0):
    """Convert curve to a polyline curve
    Parameters:
      curve_id (guid): identifier of a curve object
      angle_tolerance (number, optional): The maximum angle between curve tangents at line endpoints.
                                          If omitted, the angle tolerance is set to 5.0.
      tolerance(number, optional): The distance tolerance at segment midpoints. If omitted, the tolerance is set to 0.01.
      delete_input(bool, optional): Delete the curve object specified by curve_id. If omitted, curve_id will not be deleted.
      min_edge_length (number, optional): Minimum segment length
      max_edge_length (number, optonal): Maximum segment length
    Returns:
      guid: The new curve if successful.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          polyline = rs.ConvertCurveToPolyline(obj)
          if polyline: rs.SelectObject(polyline)
    See Also:
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if angle_tolerance<=0: angle_tolerance = 5.0
    angle_tolerance = Rhino.RhinoMath.ToRadians(angle_tolerance)
    if tolerance<=0.0: tolerance = 0.01;
    polyline_curve = curve.ToPolyline( 0, 0, angle_tolerance, 0.0, 0.0, tolerance, min_edge_length, max_edge_length, True)
    if not polyline_curve: return scriptcontext.errorhandler()
    id = System.Guid.Empty
    if delete_input:
        if scriptcontext.doc.Objects.Replace( curve_id, polyline_curve): id = curve_id
    else:
        id = scriptcontext.doc.Objects.AddCurve( polyline_curve )
    if System.Guid.Empty==id: return scriptcontext.errorhandler()
    return id

  
def CurveArcLengthPoint(curve_id, length, from_start=True):
    """Returns the point on the curve that is a specified arc length
    from the start of the curve.
    Parameters:
      curve_id (guid): identifier of a curve object
      length (number): The arc length from the start of the curve to evaluate.
      from_start (bool, optional): If not specified or True, then the arc length point is
          calculated from the start of the curve. If False, the arc length
          point is calculated from the end of the curve.
    Returns:
      point: on curve if successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          length = rs.CurveLength(obj)
          point = rs.CurveArcLengthPoint(obj, length/3.0)
          rs.AddPoint( point )
    See Also:
      CurveEndPoint
      CurveMidPoint
      CurveStartPoint
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    curve_length = curve.GetLength()
    if curve_length>=length:
        s = 0.0
        if length==0.0: s = 0.0
        elif length==curve_length: s = 1.0
        else: s = length / curve_length
        dupe = curve.Duplicate()
        if dupe:
            if from_start==False: dupe.Reverse()
            rc, t = dupe.NormalizedLengthParameter(s)
            if rc: return dupe.PointAt(t)
            dupe.Dispose()


def CurveArea(curve_id):
    """Returns area of closed planar curves. The results are based on the
    current drawing units.
    Parameters:
      curve_id (guid): The identifier of a closed, planar curve object.
    Returns:
      list[number, number]: List of area information. The list will contain the following information:
        Element  Description
        [0]      The area. If more than one curve was specified, the
                   value will be the cumulative area.
        [1]      The absolute (+/-) error bound for the area.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select a curve", rs.filter.curve)
      if id:
          props = rs.CurveArea(id)
          if props:
              print("The curve area is: {}".format(props[0]))
    See Also:
      IsCurve
      IsCurveClosed
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    mp = Rhino.Geometry.AreaMassProperties.Compute(curve, tol)
    if mp == None: return None
    return mp.Area, mp.AreaError


def CurveAreaCentroid(curve_id):
    """Returns area centroid of closed, planar curves. The results are based
    on the current drawing units.
    Parameters:
      curve_id (guid)The identifier of a closed, planar curve object.
    Returns:
      tuple(point, vector): of area centroid information containing the following information:
        Element  Description
        [0]        The 3d centroid point. If more than one curve was specified,
                 the value will be the cumulative area.
        [1]        A 3d vector with the absolute (+/-) error bound for the area
                 centroid.
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select a curve", rs.filter.curve)
      if id:
          props = rs.CurveAreaCentroid(id)
          if props:
              print("The curve area centroid is: {}".format(props[0]))
    See Also:
      IsCurve
      IsCurveClosed
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    mp = Rhino.Geometry.AreaMassProperties.Compute(curve, tol)
    if mp == None: return None
    return mp.Centroid, mp.CentroidError


def CurveArrows(curve_id, arrow_style=None):
    """Enables or disables a curve object's annotation arrows
    Parameters:
      curve_id (guid): identifier of a curve
      arrow_style (number, optional): the style of annotation arrow to be displayed. If omitted the current type is returned.
        0 = no arrows
        1 = display arrow at start of curve
        2 = display arrow at end of curve
        3 = display arrow at both start and end of curve
      Returns:
        number: if arrow_style is not specified, the current annotation arrow style
        number: if arrow_style is specified, the previous arrow style
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve", rs.filter.curve)
      if rs.CurveArrows(obj)!=3: rs.CurveArrows(obj, 3)
    See Also:
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    rhobj = rhutil.coercerhinoobject(curve_id, True, True)
    attr = rhobj.Attributes
    rc = attr.ObjectDecoration
    none_obj_decor = compat.ENUM_NONE(Rhino.DocObjects.ObjectDecoration)
    if arrow_style is not None:
        if arrow_style==0:
            attr.ObjectDecoration = none_obj_decor
        elif arrow_style==1:
            attr.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.StartArrowhead
        elif arrow_style==2:
            attr.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.EndArrowhead
        elif arrow_style==3:
            attr.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.BothArrowhead
        id = rhutil.coerceguid(curve_id, True)
        scriptcontext.doc.Objects.ModifyAttributes(id, attr, True)
        scriptcontext.doc.Views.Redraw()
    if rc==none_obj_decor: return 0
    if rc==Rhino.DocObjects.ObjectDecoration.StartArrowhead: return 1
    if rc==Rhino.DocObjects.ObjectDecoration.EndArrowhead: return 2
    if rc==Rhino.DocObjects.ObjectDecoration.BothArrowhead: return 3


def CurveBooleanDifference(curve_id_0, curve_id_1, tolerance=None):
    """Calculates the difference between two closed, planar curves and
    adds the results to the document. Note, curves must be coplanar.
    Parameters:
      curve_id_0 (guid): identifier of the first curve object.
      curve_id_1 (guid): identifier of the second curve object.
      tolerance (float, optional): a positive tolerance value, or None for the doc default.
    Returns:
      list(guid, ...): The identifiers of the new objects if successful, None on error.
    Example:
      import rhinoscriptsyntax as rs
      curveA = rs.GetObject("Select first curve", rs.filter.curve)
      curveB = rs.GetObject("Select second curve", rs.filter.curve)
      arrResult = rs.CurveBooleanDifference(curveA, curveB)
      if arrResult:
          rs.DeleteObject( curveA )
          rs.DeleteObject( curveB )
    See Also:
      CurveBooleanIntersection
      CurveBooleanUnion
    """
    curve0 = rhutil.coercecurve(curve_id_0, -1, True)
    curve1 = rhutil.coercecurve(curve_id_1, -1, True)
    if tolerance is None or tolerance<0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    out_curves = Rhino.Geometry.Curve.CreateBooleanDifference(curve0, curve1, tolerance)
    curves = []
    if out_curves:
        for curve in out_curves:
            if curve and curve.IsValid:
                rc = scriptcontext.doc.Objects.AddCurve(curve)
                curve.Dispose()
                if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
                curves.append(rc)
    scriptcontext.doc.Views.Redraw()
    return curves


def CurveBooleanIntersection(curve_id_0, curve_id_1, tolerance=None):
    """Calculates the intersection of two closed, planar curves and adds
    the results to the document. Note, curves must be coplanar.
    Parameters:
      curve_id_0 (guid): identifier of the first curve object.
      curve_id_1 (guid): identifier of the second curve object.
      tolerance (float, optional): a positive tolerance value, or None for the doc default.
    Returns:
      list(guid, ...): The identifiers of the new objects.
    Example:
      import rhinoscriptsyntax as rs
      curveA = rs.GetObject("Select first curve", rs.filter.curve)
      curveB = rs.GetObject("Select second curve", rs.filter.curve)
      result = rs.CurveBooleanIntersection(curveA, curveB)
      if result:
          rs.DeleteObject( curveA )
          rs.DeleteObject( curveB )
    See Also:
      CurveBooleanDifference
      CurveBooleanUnion
    """
    curve0 = rhutil.coercecurve(curve_id_0, -1, True)
    curve1 = rhutil.coercecurve(curve_id_1, -1, True)
    if tolerance is None or tolerance<0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    out_curves = Rhino.Geometry.Curve.CreateBooleanIntersection(curve0, curve1, tolerance)
    curves = []
    if out_curves:
        for curve in out_curves:
            if curve and curve.IsValid:
                rc = scriptcontext.doc.Objects.AddCurve(curve)
                curve.Dispose()
                if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
                curves.append(rc)
    scriptcontext.doc.Views.Redraw()
    return curves


def CurveBooleanUnion(curve_id, tolerance=None):
    """Calculate the union of two or more closed, planar curves and
    add the results to the document. Note, curves must be coplanar.
    Parameters:
      curve_id ([guid, guid, ...])list of two or more close planar curves identifiers
      tolerance (float, optional): a positive tolerance value, or None for the doc default.
    Returns:
      list(guid, ...): The identifiers of the new objects.
    Example:
      import rhinoscriptsyntax as rs
      curve_ids = rs.GetObjects("Select curves to union", rs.filter.curve)
      if curve_ids and len(curve_ids)>1:
          result = rs.CurveBooleanUnion(curve_ids)
          if result: rs.DeleteObjects(curve_ids)
    See Also:
      CurveBooleanDifference
      CurveBooleanIntersection
    """
    in_curves = [rhutil.coercecurve(id,-1,True) for id in curve_id]
    if len(in_curves)<2: raise ValueException("curve_id must have at least 2 curves")
    if tolerance is None or tolerance<0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    out_curves = Rhino.Geometry.Curve.CreateBooleanUnion(in_curves, tolerance)
    curves = []
    if out_curves:
        for curve in out_curves:
            if curve and curve.IsValid:
                rc = scriptcontext.doc.Objects.AddCurve(curve)
                curve.Dispose()
                if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
                curves.append(rc)
        scriptcontext.doc.Views.Redraw()
    return curves


def CurveBrepIntersect(curve_id, brep_id, tolerance=None):
    """Intersects a curve object with a brep object. Note, unlike the
    CurveSurfaceIntersection function, this function works on trimmed surfaces.
    Parameters:
      curve_id (guid): identifier of a curve object
      brep_id (guid): identifier of a brep object
      tolerance (number, optional): distance tolerance at segment midpoints.
                        If omitted, the current absolute tolerance is used.
    Returns:
      list(guid, ...): identifiers for the newly created intersection objects if successful.
      None: on error.
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve", rs.filter.curve)
      if curve:
          brep = rs.GetObject("Select a brep", rs.filter.surface + rs.filter.polysurface)
          if brep: rs.CurveBrepIntersect( curve, brep )
    See Also:
      CurveSurfaceIntersection
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    brep = rhutil.coercebrep(brep_id, True)
    if tolerance is None or tolerance<0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    rc, out_curves, out_points = Rhino.Geometry.Intersect.Intersection.CurveBrep(curve, brep, tolerance)
    if not rc: return scriptcontext.errorhandler()
    
    curves = []
    points = []
    for curve in out_curves:
        if curve and curve.IsValid:
            rc = scriptcontext.doc.Objects.AddCurve(curve)
            curve.Dispose()
            if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
            curves.append(rc)
    for point in out_points:
        if point and point.IsValid:
            rc = scriptcontext.doc.Objects.AddPoint(point)
            points.append(rc)
    if not curves and not points: return None
    scriptcontext.doc.Views.Redraw()
    return curves, points


def CurveClosestObject(curve_id, object_ids):
    """Returns the 3D point locations on two objects where they are closest to
    each other. Note, this function provides similar functionality to that of
    Rhino's ClosestPt command.
    Parameters:
      curve_id (guid):identifier of the curve object to test
      object_ids ([guid, ...]) list of identifiers of point cloud, curve, surface, or
        polysurface to test against
    Returns:
      tuple[guid, point, point]: containing the results of the closest point calculation.
      The elements are as follows:
        [0]    The identifier of the closest object.
        [1]    The 3-D point that is closest to the closest object.
        [2]    The 3-D point that is closest to the test curve.
    Example:
      import rhinoscriptsyntax as rs
      filter = rs.filter.curve | rs.filter.pointcloud | rs.filter.surface | rs.filter.polysurface
      objects = rs.GetObjects("Select target objects for closest point", filter)
      if objects:
          curve = rs.GetObject("Select curve")
          if curve:
              results = rs.CurveClosestObject(curve, objects)
              if results:
                  print("Curve id: {}".format(results[0]))
                  rs.AddPoint( results[1] )
                  rs.AddPoint( results[2] )
    See Also:
      CurveClosestPoint
      EvaluateCurve
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id,-1,True)
    geometry = []
    id = rhutil.coerceguid(object_ids, False)
    if id: object_ids = [id]
    for object_id in object_ids:
        rhobj = rhutil.coercerhinoobject(object_id, True, True)
        geometry.append( rhobj.Geometry )
    if not geometry: raise ValueError("object_ids must contain at least one item")
    success, curve_point, geom_point, which_geom = curve.ClosestPoints(geometry, 0.0)
    if success: return object_ids[which_geom], geom_point, curve_point

    
def CurveClosestPoint(curve_id, test_point, segment_index=-1 ):
    """Returns parameter of the point on a curve that is closest to a test point.
    Parameters:
      curve_id (guid): identifier of a curve object
      point (point): sampling point
      segment_index (number, optional): curve segment index if `curve_id` identifies a polycurve
    Returns:
      number: The parameter of the closest point on the curve
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select a curve")
      if id:
          point = rs.GetPointOnCurve(id, "Pick a test point")
          if point:
              param = rs.CurveClosestPoint(id, point)
              print("Curve parameter: {}".format(param))
    See Also:
      EvaluateCurve
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    point = rhutil.coerce3dpoint(test_point, True)
    rc, t = curve.ClosestPoint(point, 0.0)
    if not rc: raise Exception("ClosestPoint failed")
    return t


def CurveContourPoints(curve_id, start_point, end_point, interval=None):
    """Returns the 3D point locations calculated by contouring a curve object.
    Parameters:
      curve_id (guid): identifier of a curve object.
      start_point (point): 3D starting point of a center line.
      end_point (point): 3D ending point of a center line.
      interval (number, optional): The distance between contour curves. If omitted,
      the interval will be equal to the diagonal distance of the object's
      bounding box divided by 50.
    Returns:
      list(point, ....): A list of 3D points, one for each contour
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select curve", rs.filter.curve)
      start_point = rs.GetPoint("Base point of center line")
      end_point = rs.GetPoint("Endpoint of center line", start_point)
      contour = rs.CurveContourPoints(obj, start_point, end_point)
      if contour: rs.AddPoints(contour)
    See Also:
      AddSrfContourCrvs
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    start_point = rhutil.coerce3dpoint(start_point, True)
    end_point = rhutil.coerce3dpoint(end_point, True)
    if start_point.DistanceTo(end_point)<Rhino.RhinoMath.ZeroTolerance:
        raise Exception("start and end point are too close to define a line")
    if not interval:
        bbox = curve.GetBoundingBox(True)
        diagonal = bbox.Max - bbox.Min
        interval = diagonal.Length / 50.0
    rc = curve.DivideAsContour( start_point, end_point, interval )
    return list(rc)


def CurveCurvature(curve_id, parameter):
    """Returns the curvature of a curve at a parameter. See the Rhino help for
    details on curve curvature
    Parameters:
      curve_id (guid): identifier of the curve
      parameter (number): parameter to evaluate
    Returns:
      tuple[point, vector, point, number, vector]: of curvature information on success
        [0] = point at specified parameter
        [1] = tangent vector
        [2] = center of radius of curvature
        [3] = radius of curvature
        [4] = curvature vector
      None: on failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          point = rs.GetPointOnCurve(obj, "Pick a test point")
          if point:
              param = rs.CurveClosestPoint(obj, point)
              if param:
                  data = rs.CurveCurvature(obj, param)
                  if data:
                      print("Curve curvature evaluation at parameter {}".format(param, ":"))
                      print(" 3-D Point: {}".format(data[0]))
                      print(" 3-D Tangent: {}".format(data[1]))
                      print(" Center of radius of curvature: {}".format(data[2]))
                      print(" Radius of curvature: {}".format(data[3]))
                      print(" 3-D Curvature: {}".format(data[4]))
    See Also:
      SurfaceCurvature
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    point = curve.PointAt(parameter)
    tangent = curve.TangentAt(parameter)
    if tangent.IsTiny(0): return scriptcontext.errorhandler()
    cv = curve.CurvatureAt(parameter)
    k = cv.Length
    if k<Rhino.RhinoMath.SqrtEpsilon: return scriptcontext.errorhandler()
    rv = cv / (k*k)
    circle = Rhino.Geometry.Circle(point, tangent, point + 2.0*rv)
    center = point + rv
    radius = circle.Radius
    return point, tangent, center, radius, cv


def CurveCurveIntersection(curveA, curveB=None, tolerance=-1):
    """Calculates intersection of two curve objects.
    Parameters:
      curveA (guid): identifier of the first curve object.
      curveB  (guid, optional): identifier of the second curve object. If omitted, then a
               self-intersection test will be performed on curveA.
      tolerance (number, optional): absolute tolerance in drawing units. If omitted,
                        the document's current absolute tolerance is used.
    Returns:
      list of tuples: containing intersection information if successful.
      The list will contain one or more of the following elements:
        Element Type     Description
        [n][0]  Number   The intersection event type, either Point (1) or Overlap (2).
        [n][1]  Point3d  If the event type is Point (1), then the intersection point 
                         on the first curve. If the event type is Overlap (2), then
                         intersection start point on the first curve.
        [n][2]  Point3d  If the event type is Point (1), then the intersection point
                         on the first curve. If the event type is Overlap (2), then
                         intersection end point on the first curve.
        [n][3]  Point3d  If the event type is Point (1), then the intersection point 
                         on the second curve. If the event type is Overlap (2), then
                         intersection start point on the second curve.
        [n][4]  Point3d  If the event type is Point (1), then the intersection point
                         on the second curve. If the event type is Overlap (2), then
                         intersection end point on the second curve.
        [n][5]  Number   If the event type is Point (1), then the first curve parameter.
                         If the event type is Overlap (2), then the start value of the
                         first curve parameter range.
        [n][6]  Number   If the event type is Point (1), then the first curve parameter.
                         If the event type is Overlap (2), then the end value of the
                         first curve parameter range.
        [n][7]  Number   If the event type is Point (1), then the second curve parameter.
                         If the event type is Overlap (2), then the start value of the
                         second curve parameter range.
        [n][8]  Number   If the event type is Point (1), then the second curve parameter.
                         If the event type is Overlap (2), then the end value of the 
                         second curve parameter range.
    Example:
      import rhinoscriptsyntax as rs
      def ccx():
          curve1 = rs.GetObject("Select first curve", rs.filter.curve)
          if curve1 is None: return
          curve2 = rs.GetObject("Select second curve", rs.filter.curve)
          if curve2 is None: return
          intersection_list = rs.CurveCurveIntersection(curve1, curve2)
          if intersection_list is None:
              print("Selected curves do not intersect.")
              return
          for intersection in intersection_list:
              if intersection[0] == 1:
                  print("Point")
                  print("Intersection point on first curve:  {}".format(intersection[1]))
                  print("Intersection point on second curve:  {}".format(intersection[3]))
                  print("First curve parameter:  {}".format(intersection[5]))
                  print("Second curve parameter:  {}".format(intersection[7]))
              else:
                  print("Overlap")
                  print("Intersection start point on first curve: {}".format(intersection[1]))
                  print("Intersection end point on first curve: {}".format(intersection[2]))
                  print("Intersection start point on second curve: {}".format(intersection[3]))
                  print("Intersection end point on second curve: {}".format(intersection[4]))
                  print("First curve parameter range: {} to {}".format(intersection[5], intersection[6]))
                  print("Second curve parameter range: {} to {}".format(intersection[7], intersection[8]))
      ccx()
    See Also:
      CurveSurfaceIntersection
    """
    curveA = rhutil.coercecurve(curveA, -1, True)
    if curveB: curveB = rhutil.coercecurve(curveB, -1, True)
    if tolerance is None or tolerance<0.0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    if curveB:
        rc = Rhino.Geometry.Intersect.Intersection.CurveCurve(curveA, curveB, tolerance, 0.0)
    else:
        rc = Rhino.Geometry.Intersect.Intersection.CurveSelf(curveA, tolerance)
    if rc:
        events = []
        for i in compat.RANGE(rc.Count):
            event_type = 1
            if( rc[i].IsOverlap ): event_type = 2
            oa = rc[i].OverlapA
            ob = rc[i].OverlapB
            element = (event_type, rc[i].PointA, rc[i].PointA2, rc[i].PointB, rc[i].PointB2, oa[0], oa[1], ob[0], ob[1])
            events.append(element)
        return events


def CurveDegree(curve_id, segment_index=-1):
    """Returns the degree of a curve object.
    Parameters:
      curve_id (guid): identifier of a curve object.
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve.
    Returns:
      number: The degree of the curve if successful.
      None: on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          degree = rs.CurveDegree(obj)
          print("Curve degree:{}".format(degree))
    See Also:
      CurveDomain
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    return curve.Degree


def CurveDeviation(curve_a, curve_b):
    """Returns the minimum and maximum deviation between two curve objects
    Parameters:
      curve_a, curve_b (guid): identifiers of two curves
    Returns:
      tuple[number, number, number, number, number, number]: of deviation information on success
        [0] = curve_a parameter at maximum overlap distance point
        [1] = curve_b parameter at maximum overlap distance point
        [2] = maximum overlap distance
        [3] = curve_a parameter at minimum overlap distance point
        [4] = curve_b parameter at minimum overlap distance point
        [5] = minimum distance between curves
      None on error
    Example:
      import rhinoscriptsyntax as rs
      curveA = rs.GetObject("Select first curve to test", rs.filter.curve)
      curveB = rs.GetObject("Select second curve to test", rs.filter.curve)
      deviation = rs.CurveDeviation(curveA, curveB)
      if deviation:
          print("Minimum deviation = {}".format(deviation[5]))
          print("Maximum deviation = {}".format(deviation[2]))
    See Also:
      CurveArea
      CurveAreaCentroid
    """
    curve_a = rhutil.coercecurve(curve_a, -1, True)
    curve_b = rhutil.coercecurve(curve_b, -1, True)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    rc = Rhino.Geometry.Curve.GetDistancesBetweenCurves(curve_a, curve_b, tol)
    if not rc[0]: return scriptcontext.errorhandler()
    maxa = rc[2]
    maxb = rc[3]
    maxd = rc[1]
    mina = rc[5]
    minb = rc[6]
    mind = rc[4]
    return maxa, maxb, maxd, mina, minb, mind


def CurveDim(curve_id, segment_index=-1):
    """Returns the dimension of a curve object
    Parameters:
      curve_id (guid): identifier of a curve object.
      segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve.
    Returns:
      number: The dimension of the curve if successful. None on error.
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve")
      if rs.IsCurve(curve):
          print("Curve dimension = {}".format(rs.CurveDim(curve)))
    See Also:
      CurveDegree
      CurveDomain
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    return curve.Dimension


def CurveDirectionsMatch(curve_id_0, curve_id_1):
    """Tests if two curve objects are generally in the same direction or if they
    would be more in the same direction if one of them were flipped. When testing
    curve directions, both curves must be either open or closed - you cannot test
    one open curve and one closed curve.
    Parameters:
      curve_id_0 (guid): identifier of first curve object
      curve_id_1 (guid): identifier of second curve object
    Returns:
      bool: True if the curve directions match, otherwise False.
    Example:
      import rhinoscriptsyntax as rs
      curve1 = rs.GetObject("Select first curve to compare", rs.filter.curve)
      curve2 = rs.GetObject("Select second curve to compare", rs.filter.curve)
      if rs.CurveDirectionsMatch(curve1, curve2):
          print("Curves are in the same direction")
      else:
          print("Curve are not in the same direction")
    See Also:
      ReverseCurve
    """
    curve0 = rhutil.coercecurve(curve_id_0, -1, True)
    curve1 = rhutil.coercecurve(curve_id_1, -1, True)
    return Rhino.Geometry.Curve.DoDirectionsMatch(curve0, curve1)


def CurveDiscontinuity(curve_id, style):   
    """Search for a derivatitive, tangent, or curvature discontinuity in
    a curve object.
    Parameters:
      curve_id (guid): identifier of curve object
      style (number): The type of continuity to test for. The types of
          continuity are as follows:
          Value    Description
          1        C0 - Continuous function
          2        C1 - Continuous first derivative
          3        C2 - Continuous first and second derivative
          4        G1 - Continuous unit tangent
          5        G2 - Continuous unit tangent and curvature
    Returns:
      list(point, ...): 3D points where the curve is discontinuous
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve", rs.filter.curve)
      if rs.IsCurve(curve):
          points = rs.CurveDiscontinuity(curve, 2)
          if points: rs.AddPoints( points )
    See Also:
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    dom = curve.Domain
    t0 = dom.Min
    t1 = dom.Max
    points = []
    get_next = True
    while get_next:
        get_next, t = curve.GetNextDiscontinuity(System.Enum.ToObject(Rhino.Geometry.Continuity, style), t0, t1)
        if get_next:
            points.append(curve.PointAt(t))
            t0 = t # Advance to the next parameter
    return points


def CurveDomain(curve_id, segment_index=-1):
    """Returns the domain of a curve object
    as an indexable object with two elements.
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve.
    Returns:
      list(number, number): the domain of the curve if successful.
         [0] Domain minimum
         [1] Domain maximum
      None: on error

    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          domain = rs.CurveDomain(obj)
          print("Curve domain: {} to {}".format(domain[0], domain[1]))
    See Also:
      CurveDegree
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    return curve.Domain


def CurveEditPoints(curve_id, return_parameters=False, segment_index=-1):
    """Returns the edit, or Greville, points of a curve object. 
    For each curve control point, there is a corresponding edit point.
    Parameters:
      curve_id (guid): identifier of the curve object
      return_parameters (bool, optional): if True, return as a list of curve parameters.
                                          If False, return as a list of 3d points
      segment_index (number, optional): the curve segment index is `curve_id` identifies a polycurve
    Returns:
      list(point, ....): curve edit points on success
      None on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          points = rs.CurveEditPoints(obj)
          if points: rs.AddPointCloud( points )
    See Also:
      IsCurve
      CurvePointCount
      CurvePoints
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    nc = curve.ToNurbsCurve()
    if not nc: return scriptcontext.errorhandler()
    if return_parameters: return nc.GrevilleParameters()
    return list(nc.GrevillePoints())


def CurveEndPoint(curve_id, segment_index=-1):
    """Returns the end point of a curve object
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      point: The 3d endpoint of the curve if successful.
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      object = rs.GetObject("Select a curve")
      if rs.IsCurve(object):
          point = rs.CurveEndPoint(object)
          rs.AddPoint(point)
    See Also:
      CurveMidPoint
      CurveStartPoint
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    return curve.PointAtEnd


def CurveFilletPoints(curve_id_0, curve_id_1, radius=1.0, base_point_0=None, base_point_1=None, return_points=True):
    """Find points at which to cut a pair of curves so that a fillet of a
    specified radius fits. A fillet point is a pair of points (point0, point1)
    such that there is a circle of radius tangent to curve curve0 at point0 and
    tangent to curve curve1 at point1. Of all possible fillet points, this
    function returns the one which is the closest to the base point base_point_0,
    base_point_1. Distance from the base point is measured by the sum of arc
    lengths along the two curves. 
    Parameters:
      curve_id_0 (guid): identifier of the first curve object.
      curve_id_1 (guid): identifier of the second curve object.
      radius (number, optional): The fillet radius. If omitted, a radius
                     of 1.0 is specified.
      base_point_0 (point, optional): The base point on the first curve.
                     If omitted, the starting point of the curve is used.
      base_point_1 (point, optional): The base point on the second curve. If omitted,
                     the starting point of the curve is used.
      return_points (bool, optional): If True (Default), then fillet points are
                     returned. Otherwise, a fillet curve is created and
                     it's identifier is returned.
    Returns:
      list(point, point, point, vector, vector, vector): If return_points is True, then a list of point and vector values
      if successful. The list elements are as follows:
          [0]    A point on the first curve at which to cut (point).
          [1]    A point on the second curve at which to cut (point).
          [2]    The fillet plane's origin (point). This point is also
                   the center point of the fillet
          [3]    The fillet plane's X axis (vector).
          [4]    The fillet plane's Y axis (vector).
          [5]    The fillet plane's Z axis (vector).
      
      guid: If return_points is False, then the identifier of the fillet curve
            if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      curve0 = rs.AddLine([0,0,0], [5,1,0])
      curve1 = rs.AddLine([0,0,0], [1,5,0])
      fillet = rs.CurveFilletPoints(curve0, curve1)
      if fillet:
          rs.AddPoint( fillet[0] )
          rs.AddPoint( fillet[1] )
          rs.AddPoint( fillet[2] )
    See Also:
      AddFilletCurve
    """
    curve0 = rhutil.coercecurve(curve_id_0, -1, True)
    curve1 = rhutil.coercecurve(curve_id_1, -1, True)
    t0_base = curve0.Domain.Min
    
    if base_point_0:
        rc = curve0.ClosestPoint(base_point_0, t0_base)
        if not rc[0]: return scriptcontext.errorhandler()
    
    t1_base = curve1.Domain.Min
    if base_point_1:
        rc = curve1.ClosestPoint(base_point_1, t1_base)
        if not rc[0]: return scriptcontext.errorhandler()

    r = radius if (radius and radius>0) else 1.0
    rc = Rhino.Geometry.Curve.GetFilletPoints(curve0, curve1, r, t0_base, t1_base)
    if rc[0]:
        point_0 = curve0.PointAt(rc[1])
        point_1 = curve1.PointAt(rc[2])
        return point_0, point_1, rc[3].Origin, rc[3].XAxis, rc[3].YAxis, rc[3].ZAxis
    return scriptcontext.errorhandler()


def CurveFrame(curve_id, parameter, segment_index=-1):
    """Returns the plane at a parameter of a curve. The plane is based on the
    tangent and curvature vectors at a parameter.
    Parameters:
      curve_id (guid): identifier of the curve object.
      parameter (number): parameter to evaluate.
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      plane: The plane at the specified parameter if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetCurveObject("Select a curve")
      if curve:
          plane = rs.CurveFrame(curve[0], curve[4])
          rs.AddPlaneSurface(plane, 5.0, 3.0)
    See Also:
      CurvePerpFrame
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    domain = curve.Domain
    if not domain.IncludesParameter(parameter):
        tol = scriptcontext.doc.ModelAbsoluteTolerance
        if parameter>domain.Max and (parameter-domain.Max)<=tol:
            parameter = domain.Max
        elif parameter<domain.Min and (domain.Min-parameter)<=tol:
            parameter = domain.Min
        else:
            return scriptcontext.errorhandler()
    rc, frame = curve.FrameAt(parameter)
    if rc and frame.IsValid: return frame
    return scriptcontext.errorhandler()


def CurveKnotCount(curve_id, segment_index=-1):
    """Returns the knot count of a curve object.
    Parameters:
      curve_id (guid): identifier of the curve object.
      segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve.
    Returns:
      number: The number of knots if successful.
      None: if not successful or on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          count = rs.CurveKnotCount(obj)
          print("Curve knot count:{}".format(count))
    See Also:
      DivideCurve
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    nc = curve.ToNurbsCurve()
    if not nc: return scriptcontext.errorhandler()
    return nc.Knots.Count


def CurveKnots(curve_id, segment_index=-1):
    """Returns the knots, or knot vector, of a curve object
    Parameters:
      curve_id (guid): identifier of the curve object.
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve.
    Returns:
      list(number, ....): knot values if successful.
      None: if not successful or on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          knots = rs.CurveKnots(obj)
          if knots:
              for knot in knots: print("Curve knot value:{}".format(knot))
    See Also:
      CurveKnotCount
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    nc = curve.ToNurbsCurve()
    if not nc: return scriptcontext.errorhandler()
    rc = [nc.Knots[i] for i in range(nc.Knots.Count)]
    return rc


def CurveLength(curve_id, segment_index=-1, sub_domain=None):
    """Returns the length of a curve object.
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
      sub_domain ([number, number], optional): list of two numbers identifying the sub-domain of the
          curve on which the calculation will be performed. The two parameters
          (sub-domain) must be non-decreasing. If omitted, the length of the
          entire curve is returned.
    Returns:
      number: The length of the curve if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      object = rs.GetObject("Select a curve")
      if rs.IsCurve(object):
          length = rs.CurveLength(object)
          print("Curve length:{}".format(length))
    See Also:
      CurveDomain
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    if sub_domain:
        if len(sub_domain)==2:
            dom = Rhino.Geometry.Interval(sub_domain[0], sub_domain[1])
            return curve.GetLength(dom)
        return scriptcontext.errorhandler()
    return curve.GetLength()


def CurveMidPoint(curve_id, segment_index=-1):
    """Returns the mid point of a curve object.
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      point: The 3D midpoint of the curve if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      object = rs.GetObject("Select a curve")
      if rs.IsCurve(object):
          point = rs.CurveMidPoint(pbject)
          rs.AddPoint( point )
    See Also:
      CurveEndPoint
      CurveStartPoint
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, t = curve.NormalizedLengthParameter(0.5)
    if rc: return curve.PointAt(t)
    return scriptcontext.errorhandler()


def CurveNormal(curve_id, segment_index=-1):
    """Returns the normal direction of the plane in which a planar curve object lies.
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment if curve_id identifies a polycurve
    Returns:
      vector: The 3D normal vector if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      object = rs.GetObject("Select a planar curve")
      if rs.IsCurve(object) and rs.IsCurvePlanar(object):
          normal = rs.CurveNormal(object)
          if normal: print("Curve Normal:{}".format(normal))
    See Also:
      IsCurve
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    rc, plane = curve.TryGetPlane(tol)
    if rc: return plane.Normal
    return scriptcontext.errorhandler()


def CurveNormalizedParameter(curve_id, parameter):
    """Converts a curve parameter to a normalized curve parameter;
    one that ranges between 0-1
    Parameters:
      curve_id (guid): identifier of the curve object
      parameter (number): the curve parameter to convert
    Returns:
      number: normalized curve parameter
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select curve")
      if rs.IsCurve(obj):
          domain = rs.CurveDomain(obj)
          parameter = (domain[0]+domain[1])/2.0
          print("Curve parameter:{}".format(parameter))
          normalized = rs.CurveNormalizedParameter(obj, parameter)
          print("Normalized parameter:{}".format(normalized))
    See Also:
      CurveDomain
      CurveParameter
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    return curve.Domain.NormalizedParameterAt(parameter)


def CurveParameter(curve_id, parameter):
    """Converts a normalized curve parameter to a curve parameter;
    one within the curve's domain
    Parameters:
      curve_id (guid): identifier of the curve object
      parameter (number): the normalized curve parameter to convert
    Returns:
      number: curve parameter
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select curve")
      if rs.IsCurve(obj):
          normalized = 0.5
          print("Normalized parameter:{}".format(normalized))
          parameter = rs.CurveParameter(obj, normalized)
          print("Curve parameter:{}".format(parameter))
    See Also:
      CurveDomain
      CurveNormalizedParameter
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    return curve.Domain.ParameterAt(parameter)


def CurvePerpFrame(curve_id, parameter):
    """Returns the perpendicular plane at a parameter of a curve. The result
    is relatively parallel (zero-twisting) plane
    Parameters:
      curve_id (guid): identifier of the curve object
      parameter (number): parameter to evaluate
    Returns:
      plane: Plane on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      crv = rs.GetCurveObject("Select a curve")
      if crv:
          plane = rs.CurvePerpFrame(crv[0], crv[4])
          rs.AddPlaneSurface( plane, 1, 1 )
    See Also:
      CurveFrame
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    parameter = float(parameter)
    rc, plane = curve.PerpendicularFrameAt(parameter)
    if rc: return plane


def CurvePlane(curve_id, segment_index=-1):
    """Returns the plane in which a planar curve lies. Note, this function works
    only on planar curves.
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      plane: The plane in which the curve lies if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve", rs.filter.curve)
      if rs.IsCurvePlanar(curve):
          plane = rs.CurvePlane(curve)
          rs.ViewCPlane(None, plane)
    See Also:
      IsCurve
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    rc, plane = curve.TryGetPlane(tol)
    if rc: return plane
    return scriptcontext.errorhandler()


def CurvePointCount(curve_id, segment_index=-1):
    """Returns the control points count of a curve object.
    Parameters:
      curve_id (guid) identifier of the curve object
      segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve
    Returns:
      number: Number of control points if successful.
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          count = rs.CurvePointCount(obj)
          print("Curve point count:{}".format(count))
    See Also:
      DivideCurve
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    nc = curve.ToNurbsCurve()
    if nc: return nc.Points.Count
    return scriptcontext.errorhandler()


def CurvePoints(curve_id, segment_index=-1):
    """Returns the control points, or control vertices, of a curve object.
    If the curve is a rational NURBS curve, the euclidean control vertices
    are returned.
    Parameters:
      curve_id (guid): the object's identifier
      segment_index (number, optional): the curve segment if `curve_id` identifies a polycurve
    Returns:
      list(point, ...): the control points, or control vertices, of a curve object
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          points = rs.CurvePoints(obj)
          if points: [rs.AddPoint(pt) for pt in points]
    See Also:
      CurvePointCount
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    nc = curve.ToNurbsCurve()
    if nc is None: return scriptcontext.errorhandler()
    points = [nc.Points[i].Location for i in compat.RANGE(nc.Points.Count)]
    return points


def CurveRadius(curve_id, test_point, segment_index=-1):
    """Returns the radius of curvature at a point on a curve.
    Parameters:
      curve_id (guid): identifier of the curve object
      test_point (point): sampling point
      segment_index (number, optional): the curve segment if curve_id identifies a polycurve
    Returns:
      number: The radius of curvature at the point on the curve if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          point = rs.GetPointOnCurve(obj, "Pick a test point")
          if point:
              radius = rs.CurveRadius(obj, point)
              print("Radius of curvature:{}".format(radius))
    See Also:
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    point = rhutil.coerce3dpoint(test_point, True)
    rc, t = curve.ClosestPoint(point, 0.0)
    if not rc: return scriptcontext.errorhandler()
    v = curve.CurvatureAt( t )
    k = v.Length
    if k>Rhino.RhinoMath.ZeroTolerance: return 1/k
    return scriptcontext.errorhandler()


def CurveSeam(curve_id, parameter):
    """Adjusts the seam, or start/end, point of a closed curve.
    Parameters:
      curve_id (guid): identifier of the curve object
      parameter (number): The parameter of the new start/end point.
                  Note, if successful, the resulting curve's
                  domain will start at `parameter`.
    Returns:
      bool: True or False indicating success or failure.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select closed curve", rs.filter.curve)
      if rs.IsCurveClosed(obj):
          domain = rs.CurveDomain(obj)
          parameter = (domain[0] + domain[1])/2.0
          rs.CurveSeam( obj, parameter )
    See Also:
      IsCurve
      IsCurveClosed
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if (not curve.IsClosed or not curve.Domain.IncludesParameter(parameter)):
        return False
    dupe = curve.Duplicate()
    if dupe:
        dupe.ChangeClosedCurveSeam(parameter)
        curve_id = rhutil.coerceguid(curve_id)
        dupe_obj = scriptcontext.doc.Objects.Replace(curve_id, dupe)
        return dupe_obj is not None
    return False


def CurveStartPoint(curve_id, segment_index=-1, point=None):
    """Returns the start point of a curve object
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
      point (point, optional): new start point
    Returns:
      point: The 3D starting point of the curve if successful.
    Example:
      import rhinoscriptsyntax as rs
      object = rs.GetObject("Select a curve")
      if rs.IsCurve(object):
          point = rs.CurveStartPoint(object)
          rs.AddPoint(point)
    See Also:
      CurveEndPoint
      CurveMidPoint
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc = curve.PointAtStart
    if point:
        point = rhutil.coerce3dpoint(point, True)
        if point and curve.SetStartPoint(point):
            curve_id = rhutil.coerceguid(curve_id, True)
            scriptcontext.doc.Objects.Replace(curve_id, curve)
            scriptcontext.doc.Views.Redraw()
    return rc


def CurveSurfaceIntersection(curve_id, surface_id, tolerance=-1, angle_tolerance=-1):
    """Calculates intersection of a curve object with a surface object.
    Note, this function works on the untrimmed portion of the surface.
    Parameters:
      curve_id (guid): The identifier of the first curve object.
      surface_id (guid): The identifier of the second curve object. If omitted,
          the a self-intersection test will be performed on curve.
      tolerance (number, optional): The absolute tolerance in drawing units. If omitted,
          the document's current absolute tolerance is used.
      angle_tolerance (number, optional) angle tolerance in degrees. The angle
          tolerance is used to determine when the curve is tangent to the
          surface. If omitted, the document's current angle tolerance is used.
    Returns:
      list(list(point, point, point, point, number, number, number, number, number, number), ...): of intersection information if successful.
      The list will contain one or more of the following elements:
        Element Type     Description
        [n][0]  Number   The intersection event type, either Point(1) or Overlap(2).
        [n][1]  Point3d  If the event type is Point(1), then the intersection point
                         on the first curve. If the event type is Overlap(2), then
                         intersection start point on the first curve.
        [n][2]  Point3d  If the event type is Point(1), then the intersection point
                         on the first curve. If the event type is Overlap(2), then
                         intersection end point on the first curve.
        [n][3]  Point3d  If the event type is Point(1), then the intersection point
                         on the second curve. If the event type is Overlap(2), then
                         intersection start point on the surface.
        [n][4]  Point3d  If the event type is Point(1), then the intersection point
                         on the second curve. If the event type is Overlap(2), then
                         intersection end point on the surface.
        [n][5]  Number   If the event type is Point(1), then the first curve parameter.
                         If the event type is Overlap(2), then the start value of the
                         first curve parameter range.
        [n][6]  Number   If the event type is Point(1), then the first curve parameter.
                         If the event type is Overlap(2), then the end value of the
                         curve parameter range.
        [n][7]  Number   If the event type is Point(1), then the U surface parameter.
                         If the event type is Overlap(2), then the U surface parameter
                         for curve at (n, 5).
        [n][8]  Number   If the event type is Point(1), then the V surface parameter.
                         If the event type is Overlap(2), then the V surface parameter
                         for curve at (n, 5).
        [n][9]  Number   If the event type is Point(1), then the U surface parameter.
                         If the event type is Overlap(2), then the U surface parameter
                         for curve at (n, 6).
        [n][10] Number   If the event type is Point(1), then the V surface parameter.
                         If the event type is Overlap(2), then the V surface parameter
                         for curve at (n, 6).
    Example:
      import rhinoscriptsyntax as rs
      def csx():
          curve = rs.GetObject("Select curve", rs.filter.curve)
          if curve is None: return
          surface = rs.GetObject("Select surface", rs.filter.surface)
          if surface is None: return
          intersection_list = rs.CurveSurfaceIntersection(curve, surface)
          if intersection_list is None:
              print("Curve and surface do not intersect.")
              return
          for intersection in intersection_list:
              if intersection[0]==1:
                  print("Point")
                  print("Intersection point on curve:{}".format(intersection[1]))
                  print("Intersection point on surface:{}".format(intersection[3]))
                  print("Curve parameter:{}".format(intersection[5]))
                  print("Surface parameter: {}, {}".format(intersection[7], intersection[8]))
              else:
                  print("Overlap")
                  print("Intersection start point on curve:{}".format(intersection[1]))
                  print("Intersection end point on curve:{}".format(intersection[2]))
                  print("Intersection start point on surface:{}".format(intersection[3]))
                  print("Intersection end point on surface:{}".format(intersection[4]))
                  print("Curve parameter range: {} to {}".format(intersection[5], intersection[6]))
                  print("Surface parameter range: {}, {} to {}, {}".format(intersection[7] intersection[8], intersection[9], intersection[10]))
      csx()
    See Also:
      CurveCurveIntersection
      CurveBrepIntersect
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    surface = rhutil.coercesurface(surface_id, True)
    if tolerance is None or tolerance<0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    if angle_tolerance is None or angle_tolerance<0:
        angle_tolerance = scriptcontext.doc.ModelAngleToleranceRadians
    else:
        angle_tolerance = math.radians(angle_tolerance)
    rc = Rhino.Geometry.Intersect.Intersection.CurveSurface(curve, surface, tolerance, angle_tolerance)
    if rc:
        events = []
        for i in compat.RANGE(rc.Count):
            event_type = 2 if rc[i].IsOverlap else 1
            item = rc[i]
            oa = item.OverlapA
            u,v = item.SurfaceOverlapParameter()
            e = (event_type, item.PointA, item.PointA2, item.PointB, item.PointB2, oa[0], oa[1], u[0], u[1], v[0], v[1])
            events.append(e)
        return events


def CurveTangent(curve_id, parameter, segment_index=-1):
    """Returns a 3D vector that is the tangent to a curve at a parameter.
    Parameters:
      curve_id (guid): identifier of the curve object
      parameter (number) parameter to evaluate
      segment_index (number, optional) the curve segment index if `curve_id` identifies a polycurve
    Returns:
      vector: A 3D vector if successful.
      None: on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve", rs.filter.curve)
      if obj:
          point = rs.GetPointOnCurve(obj)
          if point:
              param = rs.CurveClosestPoint(obj, point)
              normal = rs.CurveTangent(obj, param)
              print(normal)
    See Also:
      CurveClosestPoint
      CurveDomain
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc = Rhino.Geometry.Point3d.Unset
    if curve.Domain.IncludesParameter(parameter):
        return curve.TangentAt(parameter)
    return scriptcontext.errorhandler()


def CurveWeights(curve_id, segment_index=-1):
    """Returns list of weights that are assigned to the control points of a curve
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      number: The weight values of the curve if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          weights = rs.CurveWeights(obj)
          if weights:
              for weight in weights:
                  print("Curve control point weight value:{}".format(weight))
    See Also:
      CurveKnots
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    nc = curve
    if type(curve) is not Rhino.Geometry.NurbsCurve:
        nc = curve.ToNurbsCurve()
    if nc is None: return scriptcontext.errorhandler()
    return [pt.Weight for pt in nc.Points]


def DivideCurve(curve_id, segments, create_points=False, return_points=True):
    """Divides a curve object into a specified number of segments.
    Parameters:
      curve_id (guid):identifier of the curve object
      segments (number): The number of segments.
      create_points (bool, optional): Create the division points. If omitted or False,
          points are not created.
      return_points (bool, optional): If omitted or True, points are returned.
          If False, then a list of curve parameters are returned.
    Returns:
      list(point|number, ...): If `return_points` is not specified or True, then a list containing 3D division points.
      list(point|number, ...): If `return_points` is False, then an array containing division curve parameters.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if obj:
          points = rs.DivideCurve(obj, 4)
          for point in points: rs.AddPoint(point)
    See Also:
      DivideCurveEquidistant
      DivideCurveLength
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    rc = curve.DivideByCount(segments, True)
    if not rc: return scriptcontext.errorhandler()
    if return_points or create_points:
        outputpoints = [curve.PointAt(t) for t in rc]
        if return_points: rc = outputpoints
        if create_points:
            for point in outputpoints:
                if point.IsValid: scriptcontext.doc.Objects.AddPoint(point)
            scriptcontext.doc.Views.Redraw()
    return rc


def DivideCurveEquidistant(curve_id, distance, create_points=False, return_points=True):
    """Divides a curve such that the linear distance between the points is equal.
    Parameters:
      curve_id (guid): the object's identifier
      distance (number): linear distance between division points
      create_points (bool, optional): create the division points if True.
      return_points (bool, optional): If True, return a list of points.
                                      If False, return a list of curve parameters
    Returns:
      list(point|number, ...): points or curve parameters based on the value of return_points
      none on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve", rs.filter.curve)
      if obj:
          points = rs.DivideCurveEquidistant(obj, 4, True)
    See Also:
      DivideCurve
      DivideCurveLength
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    points = curve.DivideEquidistant(distance)
    if not points: return scriptcontext.errorhandler()
    if create_points:
        for point in points: scriptcontext.doc.Objects.AddPoint(point)
        scriptcontext.doc.Views.Redraw()
    if return_points: return points
    tvals = []
    for point in points:
        rc, t = curve.ClosestPoint(point)
        tvals.append(t)
    return tvals


def DivideCurveLength(curve_id, length, create_points=False, return_points=True):
    """Divides a curve object into segments of a specified length.
    Parameters:
      curve_id (guid): identifier of the curve object
      length (number): The length of each segment.
      create_points (bool, optional): Create the division points. If omitted or False,
          points are not created.
      return_points (bool, optional): If omitted or True, points are returned.
          If False, then a list of curve parameters are returned.
    Returns:
      list(point, ...): If return_points is not specified or True, then a list containing division points.
      list(number, ...): If return_points is False, then an array containing division curve parameters.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          length = rs.CurveLength(obj) / 4
          points = rs.DivideCurveLength(obj, length)
          for point in points: rs.AddPoint(point)
    See Also:
      DivideCurve
      DivideCurveEquidistant
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    rc = curve.DivideByLength(length, True)
    if not rc: return scriptcontext.errorhandler()
    if return_points or create_points:
        outputpoints = [curve.PointAt(t) for t in rc]
        if create_points:
            for point in outputpoints:
                if (point.IsValid): scriptcontext.doc.Objects.AddPoint(point)
        if return_points: rc = outputpoints
    return rc


def EllipseCenterPoint(curve_id):
    """Returns the center point of an elliptical-shaped curve object.
    Parameters:
      curve_id (guid): identifier of the curve object.
    Returns:
      point: The 3D center point of the ellipse if successful.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select ellipse")
      if rs.IsEllipse(obj):
          point = rs.EllipseCenterPoint(obj)
          rs.AddPoint( point )
    See Also:
      IsEllipse
      EllipseQuadPoints
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    rc, ellipse = curve.TryGetEllipse()
    if not rc: raise ValueError("curve is not an ellipse")
    return ellipse.Plane.Origin


def EllipseQuadPoints(curve_id):
    """Returns the quadrant points of an elliptical-shaped curve object.
    Parameters:
      curve_id (guid): identifier of the curve object.
    Returns:
      list(point, point, point, point): Four points identifying the quadrants of the ellipse
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select ellipse")
      if rs.IsEllipse(obj):
          rs.AddPoints( rs.EllipseQuadPoints(obj) )
    See Also:
      IsEllipse
      EllipseCenterPoint
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    rc, ellipse = curve.TryGetEllipse()
    if not rc: raise ValueError("curve is not an ellipse")
    origin = ellipse.Plane.Origin;
    xaxis = ellipse.Radius1 * ellipse.Plane.XAxis;
    yaxis = ellipse.Radius2 * ellipse.Plane.YAxis;
    return (origin-xaxis, origin+xaxis, origin-yaxis, origin+yaxis)


def EvaluateCurve(curve_id, t, segment_index=-1):
    """Evaluates a curve at a parameter and returns a 3D point
    Parameters:
      curve_id (guid): identifier of the curve object
      t (number): the parameter to evaluate
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      point: a 3-D point if successful
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          domain = rs.CurveDomain(obj)
          t = domain[1]/2.0
          point = rs.EvaluateCurve(obj, t)
          rs.AddPoint( point )
    See Also:
      CurveClosestPoint
      IsCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    return curve.PointAt(t)


def ExplodeCurves(curve_ids, delete_input=False):
    """Explodes, or un-joins, one curves. Polycurves will be exploded into curve
    segments. Polylines will be exploded into line segments. ExplodeCurves will
    return the curves in topological order. 
    Parameters:
      curve_ids (guid): the curve object(s) to explode.
      delete_input (bool, optional): Delete input objects after exploding if True.
    Returns:
      list(guid, ...): identifying the newly created curve objects
    Example:
      import rhinoscriptsyntax as rs
      crv = rs.GetObject("Select curve to explode", rs.filter.curve)
      if rs.IsCurve(crv): rs.ExplodeCurves(crv)
    See Also:
      IsCurve
      IsPolyCurve
      IsPolyline
      JoinCurves
    """
    if( type(curve_ids) is list or type(curve_ids) is tuple ): pass
    else: curve_ids = [curve_ids]
    rc = []
    for id in curve_ids:
        curve = rhutil.coercecurve(id, -1, True)
        pieces = curve.DuplicateSegments()
        if pieces:
            for piece in pieces:
                rc.append(scriptcontext.doc.Objects.AddCurve(piece))
            if delete_input:
                id = rhutil.coerceguid(id, True)
                scriptcontext.doc.Objects.Delete(id, True)
    if rc: scriptcontext.doc.Views.Redraw()
    return rc


def ExtendCurve(curve_id, extension_type, side, boundary_object_ids):
    """Extends a non-closed curve object by a line, arc, or smooth extension
    until it intersects a collection of objects.
    Parameters:
      curve_id (guid): identifier of curve to extend
      extension_type (number):
        0 = line
        1 = arc
        2 = smooth
      side (number):
        0=extend from the start of the curve
        1=extend from the end of the curve
        2=extend from both the start and the end of the curve
      boundary_object_ids (guid): curve, surface, and polysurface objects to extend to
    Returns:
      guid: The identifier of the new object if successful.
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      filter = rs.filter.curve | rs.filter.surface | rs.filter.polysurface
      objects = rs.GetObjects("Select boundary objects", filter)
      if objects:
          curve = rs.GetObject("Select curve to extend", rs.filter.curve)
          if curve: rs.ExtendCurve( curve, 2, 1, objects )
    See Also:
      ExtendCurveLength
      ExtendCurvePoint
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if extension_type==0: extension_type = Rhino.Geometry.CurveExtensionStyle.Line
    elif extension_type==1: extension_type = Rhino.Geometry.CurveExtensionStyle.Arc
    elif extension_type==2: extension_type = Rhino.Geometry.CurveExtensionStyle.Smooth
    else: raise ValueError("extension_type must be 0, 1, or 2")
    
    if side==0: side = Rhino.Geometry.CurveEnd.Start
    elif side==1: side = Rhino.Geometry.CurveEnd.End
    elif side==2: side = Rhino.Geometry.CurveEnd.Both
    else: raise ValueError("side must be 0, 1, or 2")
    
    rhobjs = [rhutil.coercerhinoobject(id) for id in boundary_object_ids]
    if not rhobjs: raise ValueError("boundary_object_ids must contain at least one item")
    geometry = [obj.Geometry for obj in rhobjs]
    newcurve = curve.Extend(side, extension_type, geometry)
    if newcurve and newcurve.IsValid:
        curve_id = rhutil.coerceguid(curve_id, True)
        if scriptcontext.doc.Objects.Replace(curve_id, newcurve):
            scriptcontext.doc.Views.Redraw()
            return curve_id
    return scriptcontext.errorhandler()


def ExtendCurveLength(curve_id, extension_type, side, length):
    """Extends a non-closed curve by a line, arc, or smooth extension for a
    specified distance
    Parameters:
      curve_id (guid): curve to extend
      extension_type (number):
        0 = line
        1 = arc
        2 = smooth
      side (number):
        0=extend from start of the curve
        1=extend from end of the curve
        2=Extend from both ends
      length (number): distance to extend
    Returns:
      guid: The identifier of the new object
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select curve to extend", rs.filter.curve)
      if curve:
          length = rs.GetReal("Length to extend", 3.0)
          if length: rs.ExtendCurveLength( curve, 2, 2, length )
    See Also:
      ExtendCurve
      ExtendCurvePoint
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if extension_type==0: extension_type = Rhino.Geometry.CurveExtensionStyle.Line
    elif extension_type==1: extension_type = Rhino.Geometry.CurveExtensionStyle.Arc
    elif extension_type==2: extension_type = Rhino.Geometry.CurveExtensionStyle.Smooth
    else: raise ValueError("extension_type must be 0, 1, or 2")
    
    if side==0: side = Rhino.Geometry.CurveEnd.Start
    elif side==1: side = Rhino.Geometry.CurveEnd.End
    elif side==2: side = Rhino.Geometry.CurveEnd.Both
    else: raise ValueError("side must be 0, 1, or 2")
    newcurve = None
    if length<0: newcurve = curve.Trim(side, -length)
    else: newcurve = curve.Extend(side, length, extension_type)
    if newcurve and newcurve.IsValid:
        curve_id = rhutil.coerceguid(curve_id, True)
        if scriptcontext.doc.Objects.Replace(curve_id, newcurve):
            scriptcontext.doc.Views.Redraw()
            return curve_id
    return scriptcontext.errorhandler()


def ExtendCurvePoint(curve_id, side, point, extension_type=2):
    """Extends a non-closed curve by smooth extension to a point
    Parameters:
      curve_id (guid): curve to extend
      side (number):
        0=extend from start of the curve
        1=extend from end of the curve
      point (guid|point): point to extend to
      extension_type (number, optional): type of extension
        0 = Line
        1 = Arc
        2 = Smooth
    Returns:
      guid: The identifier of the new object if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select curve to extend", rs.filter.curve)
      if curve:
          point = rs.GetPoint("Point to extend to")
          if point: rs.ExtendCurvePoint(curve, 1, point)
    See Also:
      ExtendCurve
      ExtendCurveLength
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    point = rhutil.coerce3dpoint(point, True)
    
    if side==0: side = Rhino.Geometry.CurveEnd.Start
    elif side==1: side = Rhino.Geometry.CurveEnd.End
    elif side==2: side = Rhino.Geometry.CurveEnd.Both
    else: raise ValueError("side must be 0, 1, or 2")
    
    if extension_type==0: extension_type = Rhino.Geometry.CurveExtensionStyle.Line
    elif extension_type==1: extension_type = Rhino.Geometry.CurveExtensionStyle.Arc
    elif extension_type==2: extension_type = Rhino.Geometry.CurveExtensionStyle.Smooth
    else: raise ValueError("extension_type must be 0, 1, or 2")
    
    newcurve = curve.Extend(side, extension_type, point)
    if newcurve and newcurve.IsValid:
        curve_id = rhutil.coerceguid(curve_id, True)
        if scriptcontext.doc.Objects.Replace( curve_id, newcurve ):
            scriptcontext.doc.Views.Redraw()
            return curve_id
    return scriptcontext.errorhandler()


def FairCurve(curve_id, tolerance=1.0):
    """Fairs a curve. Fair works best on degree 3 (cubic) curves. Fair attempts
    to remove large curvature variations while limiting the geometry changes to
    be no more than the specified tolerance. Sometimes several applications of
    this method are necessary to remove nasty curvature problems.
    Parameters:
      curve_id (guid): curve to fair
      tolerance (number, optional): fairing tolerance
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      curves = rs.GetObjects("Select curves to fair", rs.filter.curve)
      if curves:
          [rs.FairCurve(curve) for curve in curves]
    See Also:
      
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    angle_tol = 0.0
    clamp = 0
    if curve.IsPeriodic:
        curve = curve.ToNurbsCurve()
        clamp = 1
    newcurve = curve.Fair(tolerance, angle_tol, clamp, clamp, 100)
    if not newcurve: return False
    curve_id = rhutil.coerceguid(curve_id, True)
    if scriptcontext.doc.Objects.Replace(curve_id, newcurve):
        scriptcontext.doc.Views.Redraw()
        return True
    return False


def FitCurve(curve_id, degree=3, distance_tolerance=-1, angle_tolerance=-1):
    """Reduces number of curve control points while maintaining the curve's same
    general shape. Use this function for replacing curves with many control
    points. For more information, see the Rhino help for the FitCrv command.
    Parameters:
      curve_id (guid): Identifier of the curve object
      degree (number, optional): The curve degree, which must be greater than 1.
                     The default is 3.
      distance_tolerance (number, optional): The fitting tolerance. If distance_tolerance
          is not specified or <= 0.0, the document absolute tolerance is used.
      angle_tolerance (number, optional): The kink smoothing tolerance in degrees. If
          angle_tolerance is 0.0, all kinks are smoothed. If angle_tolerance
          is > 0.0, kinks smaller than angle_tolerance are smoothed. If
          angle_tolerance is not specified or < 0.0, the document angle
          tolerance is used for the kink smoothing.
    Returns:
      guid: The identifier of the new object
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as rs
      oldCurve = rs.GetObject("Select curve to fit", rs.filter.curve)
      if oldCurve:
          newCurve = rs.FitCurve(oldCurve)
          if newCurve: rs.DeleteObject(oldCurve)
    See Also:
      
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if distance_tolerance is None or distance_tolerance<0:
        distance_tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    if angle_tolerance is None or angle_tolerance<0:
        angle_tolerance = scriptcontext.doc.ModelAngleToleranceRadians
    nc = curve.Fit(degree, distance_tolerance, angle_tolerance)
    if nc:
        rhobj = rhutil.coercerhinoobject(curve_id)
        rc = None
        if rhobj:
            rc = scriptcontext.doc.Objects.AddCurve(nc, rhobj.Attributes)
        else:
            rc = scriptcontext.doc.Objects.AddCurve(nc)
        if rc==System.Guid.Empty: raise Exception("Unable to add curve to document")
        scriptcontext.doc.Views.Redraw()
        return rc
    return scriptcontext.errorhandler()


def InsertCurveKnot(curve_id, parameter, symmetrical=False ):
    """Inserts a knot into a curve object
    Parameters:
      curve_id (guid): identifier of the curve object
      parameter (number): parameter on the curve
      symmetrical (bool, optional): if True, then knots are added on both sides of
          the center of the curve
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select curve for knot insertion", rs.filter.curve)
      if obj:
          point = rs.GetPointOnCurve(obj, "Point on curve to add knot")
          if point:
              parameter = rs.CurveClosestPoint(obj, point)
              rs.InsertCurveKnot( obj, parameter )
    See Also:
      CurveKnotCount
      CurveKnots
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if not curve.Domain.IncludesParameter(parameter): return False
    nc = curve.ToNurbsCurve()
    if not nc: return False
    rc, t = curve.GetNurbsFormParameterFromCurveParameter(parameter)
    if rc:
        rc = nc.Knots.InsertKnot(t,1)
        if rc and symmetrical:
            domain = nc.Domain
            t_sym = domain.T1 - t + domain.T0
            if abs(t_sym)>Rhino.RhinoMath.SqrtEpsilon:
                rc = nc.Knots.InsertKnot(t_sym,1)
        if rc:
            curve_id = rhutil.coerceguid(curve_id)
            rc = scriptcontext.doc.Objects.Replace(curve_id, nc)
            if rc: scriptcontext.doc.Views.Redraw()
    return rc


def IsArc(curve_id, segment_index=-1):
    """Verifies an object is an open arc curve
    Parameters:
      curve_id (guid): Identifier of the curve object
      segment_index (number): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select an arc")
      if rs.IsArc(obj):
          print("The object is an arc.")
      else:
          print("The object is not an arc.")
    See Also:
      AddArc3Pt
      ArcAngle
      ArcCenterPoint
      ArcMidPoint
      ArcRadius
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    return curve.IsArc() and not curve.IsClosed


def IsCircle(curve_id, tolerance=None):
    """Verifies an object is a circle curve
    Parameters:
      curve_id (guid): Identifier of the curve object
      tolerance (number, optional) If the curve is not a circle, then the tolerance used
        to determine whether or not the NURBS form of the curve has the
        properties of a circle. If omitted, Rhino's internal zero tolerance is used
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a circle")
      if rs.IsCircle(obj):
          print("The object is a circle.")
      else:
          print("The object is not a circle.")
    See Also:
      AddCircle
      AddCircle3Pt
      CircleCenterPoint
      CircleCircumference
      CircleRadius
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if tolerance is None or tolerance < 0:
        tolerance = Rhino.RhinoMath.ZeroTolerance
    return curve.IsCircle(tolerance)


def IsCurve(object_id):
    """Verifies an object is a curve
    Parameters:
      object_id (guid): the object's identifier
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      object = rs.GetObject("Select a curve")
      if rs.IsCurve(object):
          print("The object is a curve.")
      else:
          print("The object is not a curve.")
    See Also:
      IsCurveClosed
      IsCurveLinear
      IsCurvePeriodic
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(object_id)
    return curve is not None


def IsCurveClosable(curve_id, tolerance=None):
    """Decide if it makes sense to close off the curve by moving the end point
    to the start point based on start-end gap size and length of curve as
    approximated by chord defined by 6 points
    Parameters:
      curve_id (guid): identifier of the curve object
      tolerance[opt] = maximum allowable distance between start point and end
        point. If omitted, the document's current absolute tolerance is used
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      crv = rs.GetObject("Select curve", rs.filter.curve)
      if not rs.IsCurveClosed(crv) and rs.IsCurveClosable(crv):
          rs.CloseCurve( crv, 0.1 )
    See Also:
      CloseCurve
      IsCurveClosed
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if tolerance is None: tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    return curve.IsClosable(tolerance)


def IsCurveClosed(object_id):
    """Verifies an object is a closed curve object
    Parameters:
      object_id (guid): the object's identifier
    Returns:
      bool: True if successful otherwise False.  None on error
    Example:
      import rhinoscriptsyntax as rs
      object = rs.GetObject("Select a curve")
      if rs.IsCurve(object):
          if rs.IsCurveClosed(oObject):
              print("The object is a closed curve.")
          else:
              print("The object is not a closed curve.")
      else:
          print("The object is not a curve.")
    See Also:
      IsCurve
      IsCurveLinear
      IsCurvePeriodic
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(object_id)
    return None if not curve else curve.IsClosed


def IsCurveInPlane(object_id, plane=None):
    """Test a curve to see if it lies in a specific plane
    Parameters:
      object_id (guid): the object's identifier
      plane (plane, optional): plane to test. If omitted, the active construction plane is used
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj) and rs.IsCurvePlanar(obj):
          if rs.IsCurveInPlane(obj):
              print("The curve lies in the current cplane.")
          else:
              print("The curve does not lie in the current cplane.")
      else:
          print("The object is not a planar curve.")
    See Also:
      IsCurve
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(object_id, -1, True)
    if not plane:
        plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
    else:
        plane = rhutil.coerceplane(plane, True)
    return curve.IsInPlane(plane, scriptcontext.doc.ModelAbsoluteTolerance)


def IsCurveLinear(object_id, segment_index=-1):
    """Verifies an object is a linear curve
    Parameters:
      curve_id (guid):identifier of the curve object
      segment_index (number): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      id = rs.GetObject("Select a curve")
      if rs.IsCurve(id):
          if rs.IsCurveLinear(id):
              print("The object is a linear curve.")
          else:
              print("The object is not a linear curve.")
      else:
          print("The object is not a curve.")
    See Also:
      IsCurve
      IsCurveClosed
      IsCurvePeriodic
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(object_id, segment_index, True)
    return curve.IsLinear()


def IsCurvePeriodic(curve_id, segment_index=-1):
    """Verifies an object is a periodic curve object
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          if rs.IsCurvePeriodic(obj):
              print("The object is a periodic curve.")
          else:
              print("The object is not a periodic curve.")
      else:
          print("The object is not a curve.")
    See Also:
      IsCurve
      IsCurveClosed
      IsCurveLinear
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    return curve.IsPeriodic


def IsCurvePlanar(curve_id, segment_index=-1):
    """Verifies an object is a planar curve
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          if rs.IsCurvePlanar(obj):
              print("The object is a planar curve.")
          else:
              print("The object is not a planar curve.")
      else:
          print("The object is not a curve.")
    See Also:
      IsCurve
      IsCurveClosed
      IsCurveLinear
      IsCurvePeriodic
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    return curve.IsPlanar(tol)


def IsCurveRational(curve_id, segment_index=-1):
    """Verifies an object is a rational NURBS curve
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          if rs.IsCurveRational(obj):
              print("The object is a rational NURBS curve.")
          else:
              print("The object is not a rational NURBS curve.")
      else:
          print("The object is not a curve.")
    See Also:
      IsCurve
      IsCurveClosed
      IsCurveLinear
      IsCurvePeriodic
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    if isinstance(curve, Rhino.Geometry.NurbsCurve): return curve.IsRational
    return False


def IsEllipse(object_id, segment_index=-1):
    """Verifies an object is an elliptical-shaped curve
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select an ellipse")
      if rs.IsEllipse(obj):
          print("The object is an ellipse.")
      else:
          print("The object is not an ellipse.")
    See Also:
      EllipseCenterPoint
      EllipseQuadPoints
    """
    curve = rhutil.coercecurve(object_id, segment_index, True)
    return curve.IsEllipse()


def IsLine(object_id, segment_index=-1):
    """Verifies an object is a line curve
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a line")
      if rs.IsLine(obj):
          print("The object is a line.")
      else:
          print("The object is not a line.")
    See Also:
      AddLine
    """
    curve = rhutil.coercecurve(object_id, segment_index, True)
    if isinstance(curve, Rhino.Geometry.LineCurve): return True
    rc, polyline = curve.TryGetPolyline()
    if rc and polyline.Count==2: return True
    return False


def IsPointOnCurve(object_id, point, segment_index=-1):
    """Verifies that a point is on a curve
    Parameters:
      curve_id (guid): identifier of the curve object
      point (point): the test point
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve")
      if rs.IsCurve(obj):
          point = rs.GetPoint("Pick a test point")
          if point:
              if rs.IsPointOnCurve(obj, point):
                  print("The point is on the curve")
              else:
                  print("The point is not on the curve")
    See Also:
      IsCurve
    """
    curve = rhutil.coercecurve(object_id, segment_index, True)
    point = rhutil.coerce3dpoint(point, True)
    rc, t = curve.ClosestPoint(point, Rhino.RhinoMath.SqrtEpsilon)
    return rc


def IsPolyCurve(object_id, segment_index=-1):
    """Verifies an object is a PolyCurve curve
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional) the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a polycurve")
      if rs.IsPolyCurve(obj):
          print("The object is a polycurve.")
      else:
          print("The object is not a polycurve.")
    See Also:
      PolyCurveCount
    """
    curve = rhutil.coercecurve(object_id, segment_index, True)
    return isinstance(curve, Rhino.Geometry.PolyCurve)


def IsPolyline( object_id, segment_index=-1 ):
    """Verifies an object is a Polyline curve object
    Parameters:
      curve_id (guid): identifier of the curve object
      segment_index (number, optional): the curve segment index if `curve_id` identifies a polycurve
    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a polyline")
      if rs.IsPolyline(obj):
          print("The object is a polyline.")
      else:
          print("The object is not a polyline.")
    See Also:
      IsPolyline
      PolylineVertices
    """
    curve = rhutil.coercecurve(object_id, segment_index, True)
    return isinstance(curve, Rhino.Geometry.PolylineCurve)


def JoinCurves(object_ids, delete_input=False, tolerance=None):
    """Joins multiple curves together to form one or more curves or polycurves
    Parameters:
      object_ids (guid): list of multiple curves
      delete_input (bool, optional): delete input objects after joining
      tolerance (number, optional): join tolerance. If omitted, 2.1 * document absolute
          tolerance is used
    Returns:
      list(guid, ...): Object id representing the new curves
    Example:
      import rhinoscriptsyntax as rs
      objs = rs.GetObjects("Select curves to join", rs.filter.curve)
      if objs: rs.JoinCurves(objs)
    See Also:
      ExplodeCurves
      IsCurve
      IsCurveClosed
    """
    if len(object_ids)<2: raise ValueError("object_ids must contain at least 2 items")
    curves = [rhutil.coercecurve(id, -1, True) for id in object_ids]
    if tolerance is None:
        tolerance = 2.1 * scriptcontext.doc.ModelAbsoluteTolerance
    newcurves = Rhino.Geometry.Curve.JoinCurves(curves, tolerance)
    rc = []
    if newcurves:
        rc = [scriptcontext.doc.Objects.AddCurve(crv) for crv in newcurves]
    if rc and delete_input:
        for id in object_ids:
            id = rhutil.coerceguid(id, True)
            scriptcontext.doc.Objects.Delete(id, False)
    scriptcontext.doc.Views.Redraw()
    return rc


def LineFitFromPoints(points):
    """Returns a line that was fit through an array of 3D points
    Parameters:
      points ([point, point, ...]): a list of at least two 3D points
    Returns:
      line: line on success
    Example:
      import rhinoscriptsyntax as rs
      points = rs.GetPoints()
      if points and len(points)>1:
          line=rs.LineFitFromPoints(points)
          if line: rs.AddLine(line.From, line.To)
    See Also:
      AddLine
      CurveEndPoint
      CurveStartPoint
    """
    points = rhutil.coerce3dpointlist(points, True)
    rc, line = Rhino.Geometry.Line.TryFitLineToPoints(points)
    if rc: return line
    return scriptcontext.errorhandler()


def MakeCurveNonPeriodic(curve_id, delete_input=False):
    """Makes a periodic curve non-periodic. Non-periodic curves can develop
    kinks when deformed
    Parameters:
      curve_id (guid): identifier of the curve object
      delete_input (bool): delete the input curve. If omitted, the input curve will not be deleted.
    Returns:
      guid: id of the new or modified curve if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve", rs.filter.curve)
      if rs.IsCurvePeriodic(curve): rs.MakeCurveNonPeriodic( curve )
    See Also:
      IsCurvePeriodic
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if not curve.IsPeriodic: return scriptcontext.errorhandler()
    nc = curve.ToNurbsCurve()
    if nc is None: return scriptcontext.errorhandler()
    nc.Knots.ClampEnd( Rhino.Geometry.CurveEnd.Both )
    rc = None
    if delete_input:
        if type(curve_id) is Rhino.DocObjects.ObjRef: pass
        else: curve_id = rhutil.coerceguid(curve_id)
        if curve_id:
            rc = scriptcontext.doc.Objects.Replace(curve_id, nc)
            if not rc: return scriptcontext.errorhandler()
            rc = rhutil.coerceguid(curve_id)
    else:
        attrs = None
        if type(scriptcontext.doc) is Rhino.RhinoDoc:
            rhobj = rhutil.coercerhinoobject(curve_id)
            if rhobj: attrs = rhobj.Attributes
        rc = scriptcontext.doc.Objects.AddCurve(nc, attrs)
        if rc==System.Guid.Empty: return scriptcontext.errorhandler()
    scriptcontext.doc.Views.Redraw()
    return rc


def MeanCurve(curve0, curve1, tolerance=None):
    """Creates an average curve from two curves
    Parameters:
      curve0, curve1 (guid): identifiers of two curves
      tolerance (number, optional): angle tolerance used to match kinks between curves
    Returns:
      guid: id of the new or modified curve if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      curve0 = rs.GetObject("Select the first curve", rs.filter.curve)
      curve1 = rs.GetObject("Select the second curve", rs.filter.curve)
      rs.MeanCurve( curve0, curve1 )
    See Also:
      UnitAngleTolerance
    """
    curve0 = rhutil.coercecurve(curve0, -1, True)
    curve1 = rhutil.coercecurve(curve1, -1, True)
    if tolerance is None: tolerance=Rhino.RhinoMath.UnsetValue
    crv = Rhino.Geometry.Curve.CreateMeanCurve(curve0,curve1,tolerance)
    if crv:
        rc = scriptcontext.doc.Objects.AddCurve(crv)
        scriptcontext.doc.Views.Redraw()
        return rc


def MeshPolyline(polyline_id):
    """Creates a polygon mesh object based on a closed polyline curve object.
    The created mesh object is added to the document
    Parameters:
      polyline_id (guid): identifier of the polyline curve object
    Returns:
      guid: identifier of the new mesh object
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      polyline = rs.GetObject("Select a polyline", rs.filter.curve)
      if polyline:
          if rs.IsPolyline(polyline) and rs.IsCurveClosed(polyline):
              rs.MeshPolyline( polyline )
    See Also:
      IsCurveClosed
      IsPolyline
    """
    curve = rhutil.coercecurve(polyline_id, -1, True)
    ispolyline, polyline = curve.TryGetPolyline()
    if not ispolyline: return scriptcontext.errorhandler()
    mesh = Rhino.Geometry.Mesh.CreateFromClosedPolyline(polyline)
    if not mesh: return scriptcontext.errorhandler()
    rc = scriptcontext.doc.Objects.AddMesh(mesh)
    scriptcontext.doc.Views.Redraw()
    return rc


def OffsetCurve(object_id, direction, distance, normal=None, style=1):
    """Offsets a curve by a distance. The offset curve will be added to Rhino
    Parameters:
      object_id (guid): identifier of a curve object
      direction (point): point describing direction of the offset
      distance (number): distance of the offset
      normal (vector, optional): normal of the plane in which the offset will occur.
          If omitted, the normal of the active construction plane will be used
      style (number, optional): the corner style. If omitted, the style is sharp.
                                0 = None
                                1 = Sharp
                                2 = Round
                                3 = Smooth
                                4 = Chamfer
    Returns:
      list(guid, ...): list of ids for the new curves on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a curve", rs.filter.curve)
      if rs.IsCurve(obj):
          rs.OffsetCurve( obj, [0,0,0], 1.0 )
    See Also:
      OffsetCurveOnSurface
      OffsetSurface
    """
    curve = rhutil.coercecurve(object_id, -1, True)
    direction = rhutil.coerce3dpoint(direction, True)
    if normal:
        normal = rhutil.coerce3dvector(normal, True)
    else:
        normal = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane().Normal
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    style = System.Enum.ToObject(Rhino.Geometry.CurveOffsetCornerStyle, style)
    curves = curve.Offset(direction, normal, distance, tolerance, style)
    if curves is None: return scriptcontext.errorhandler()
    rc = [scriptcontext.doc.Objects.AddCurve(curve) for curve in curves]
    scriptcontext.doc.Views.Redraw()
    return rc


def OffsetCurveOnSurface(curve_id, surface_id, distance_or_parameter):
    """Offset a curve on a surface. The source curve must lie on the surface.
    The offset curve or curves will be added to Rhino
    Parameters:
      curve_id, surface_id (guid): curve and surface identifiers
      distance_or_parameter (number|tuple(number, number)): If a single number is passed, then this is the
        distance of the offset. Based on the curve's direction, a positive value
        will offset to the left and a negative value will offset to the right.
        If a tuple of two values is passed, this is interpreted as the surface
        U,V parameter that the curve will be offset through
    Returns:
      list(guid, ...): identifiers of the new curves if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      def TestOffset():
          curve = rs.GetObject("Select curve on a surface", rs.filter.curve)
          if curve is None: return False
          surface = rs.GetObject("Select base surface", rs.filter.surface)
          if surface is None: return False
          point = rs.GetPointOnSurface( surface, "Through point" )
          if point is None: return False
          parameter = rs.SurfaceClosestPoint(surface, point)
          rc = rs.OffsetCurveOnSurface( curve, surface, parameter )
          return rc is not None
       
      TestOffset()
    See Also:
      OffsetCurve
      OffsetSurface
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    surface = rhutil.coercesurface(surface_id, True)
    x = None
    if type(distance_or_parameter) is list or type(distance_or_parameter) is tuple:
        x = Rhino.Geometry.Point2d( distance_or_parameter[0], distance_or_parameter[1] )
    else:
        x = float(distance_or_parameter)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    curves = curve.OffsetOnSurface(surface, x, tol)
    if curves is None: return scriptcontext.errorhandler()
    curves = [curve.ExtendOnSurface(Rhino.Geometry.CurveEnd.Both, surface) for curve in curves]
    rc = [scriptcontext.doc.Objects.AddCurve(curve) for curve in curves]
    if rc: scriptcontext.doc.Views.Redraw()
    return rc


def PlanarClosedCurveContainment(curve_a, curve_b, plane=None, tolerance=None):
    """Determines the relationship between the regions bounded by two coplanar
    simple closed curves
    Parameters:
      curve_a, curve_b (guid): identifiers of two planar, closed curves
      plane (plane, optional): test plane. If omitted, the currently active construction
        plane is used
      tolerance (number, optional): if omitted, the document absolute tolerance is used
    Returns:
      number: a number identifying the relationship if successful
        0 = the regions bounded by the curves are disjoint
        1 = the two curves intersect
        2 = the region bounded by curve_a is inside of curve_b
        3 = the region bounded by curve_b is inside of curve_a
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      curve1 = rs.GetObject("Select first curve", rs.filter.curve )
      curve2 = rs.GetObject("Select second curve", rs.filter.curve )
      if rs.IsCurvePlanar(curve1) and rs.IsCurvePlanar(curve2):
          if rs.IsCurveClosed(curve1) and rs.IsCurveClosed(curve2):
              if rs.IsCurveInPlane(curve1) and rs.IsCurveInPlane(curve2):
                  result = rs.PlanarClosedCurveContainment(curve1, curve2)
                  if result==0: print("The regions bounded by the curves are disjoint.")
                  elif result==1: print("The two curves intersect..")
                  elif result==2: print("The region bounded by Curve1 is inside of Curve2.")
                  else: print("The region bounded by Curve2 is inside of Curve1.")
    See Also:
      PlanarCurveCollision
      PointInPlanarClosedCurve
    """
    curve_a = rhutil.coercecurve(curve_a, -1, True)
    curve_b = rhutil.coercecurve(curve_b, -1, True)
    if tolerance is None or tolerance<=0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    if plane:
        plane = rhutil.coerceplane(plane)
    else:
        plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
    rc = Rhino.Geometry.Curve.PlanarClosedCurveRelationship(curve_a, curve_b, plane, tolerance)
    return int(rc)


def PlanarCurveCollision(curve_a, curve_b, plane=None, tolerance=None):
    """Determines if two coplanar curves intersect
    Parameters:
      curve_a, curve_b (guid): identifiers of two planar curves
      plane (plane, optional): test plane. If omitted, the currently active construction
        plane is used
      tolerance (number, optional): if omitted, the document absolute tolerance is used
    Returns:
      bool: True if the curves intersect; otherwise False
    Example:
      import rhinoscriptsyntax as rs
      curve1 = rs.GetObject("Select first curve")
      curve2 = rs.GetObject("Select second curve")
      if( rs.IsCurvePlanar(curve1) and rs.IsCurvePlanar(curve2) and rs.IsCurveInPlane(curve1) and rs.IsCurveInPlane(curve2) ):
          if rs.PlanarCurveCollision(curve1, curve2):
              print("The coplanar curves intersect.")
          else:
              print("The coplanar curves do not intersect.")
    See Also:
      CurveCurveIntersection
      PlanarClosedCurveContainment
      PointInPlanarClosedCurve
    """
    curve_a = rhutil.coercecurve(curve_a, -1, True)
    curve_b = rhutil.coercecurve(curve_b, -1, True)
    if tolerance is None or tolerance<=0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    if plane:
        plane = rhutil.coerceplane(plane)
    else:
        plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
    return Rhino.Geometry.Curve.PlanarCurveCollision(curve_a, curve_b, plane, tolerance)


def PointInPlanarClosedCurve(point, curve, plane=None, tolerance=None):
    """Determines if a point is inside of a closed curve, on a closed curve, or
    outside of a closed curve
    Parameters:
      point (point|guid): text point
      curve (guid): identifier of a curve object
      plane (plane, optional): plane containing the closed curve and point. If omitted,
          the currently active construction plane is used
      tolerance (number, optional) it omitted, the document abosulte tolerance is used
    Returns:
      number: number identifying the result if successful
              0 = point is outside of the curve
              1 = point is inside of the curve
              2 = point in on the curve
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a planar, closed curve", rs.filter.curve)
      if rs.IsCurveClosed(curve) and rs.IsCurvePlanar(curve):
          point = rs.GetPoint("Pick a point")
          if point:
              result = rs.PointInPlanarClosedCurve(point, curve)
              if result==0: print("The point is outside of the closed curve.")
              elif result==1: print("The point is inside of the closed curve.")
              else: print("The point is on the closed curve.")
    See Also:
      PlanarClosedCurveContainment
      PlanarCurveCollision
    """
    point = rhutil.coerce3dpoint(point, True)
    curve = rhutil.coercecurve(curve, -1, True)
    if tolerance is None or tolerance<=0:
        tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    if plane:
        plane = rhutil.coerceplane(plane)
    else:
        plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
    rc = curve.Contains(point, plane, tolerance)
    if rc==Rhino.Geometry.PointContainment.Unset: raise Exception("Curve.Contains returned Unset")
    if rc==Rhino.Geometry.PointContainment.Outside: return 0
    if rc==Rhino.Geometry.PointContainment.Inside: return 1
    return 2


def PolyCurveCount(curve_id, segment_index=-1):
    """Returns the number of curve segments that make up a polycurve
    Parameters:
      curve_id (guid): the object's identifier
      segment_index (number, optional): if `curve_id` identifies a polycurve object, then `segment_index` identifies the curve segment of the polycurve to query.
    Returns:
      number: the number of curve segments in a polycurve if successful
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a polycurve")
      if rs.IsPolyCurve(obj):
          count = rs.PolyCurveCount(obj)
          if count: print("The polycurve contains {} curves".format(count))
    See Also:
      IsPolyCurve
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    if isinstance(curve, Rhino.Geometry.PolyCurve): return curve.SegmentCount
    raise ValueError("curve_id does not reference a polycurve")


def PolylineVertices(curve_id, segment_index=-1):
    """Returns the vertices of a polyline curve on success
    Parameters:
      curve_id (guid): the object's identifier
      segment_index (number, optional): if curve_id identifies a polycurve object, then segment_index identifies the curve segment of the polycurve to query.
    Returns:
      list(point, ...): an list of Point3d vertex points if successful
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a polyline")
      if rs.IsPolyline(obj):
          points = rs.PolylineVertices(obj)
          if points:
              for point in points: rs.AddPoint(point)
    See Also:
      AddPolyline
      IsPolyline
    """
    curve = rhutil.coercecurve(curve_id, segment_index, True)
    rc, polyline = curve.TryGetPolyline()
    if rc: return [pt for pt in polyline]
    raise ValueError("curve_id does not reference a polyline")


def ProjectCurveToMesh(curve_ids, mesh_ids, direction):
    """Projects one or more curves onto one or more surfaces or meshes
    Parameters:
      curve_ids ([guid, ...]): identifiers of curves to project
      mesh_ids ([guid, ...]): identifiers of meshes to project onto
      direction (vector): projection direction
    Returns:
      list(guid, ...): list of identifiers for the resulting curves.
    Example:
      import rhinoscriptsyntax as rs
      mesh = rs.GetObject("Select mesh to project onto", rs.filter.mesh)
      curve= rs.GetObject("Select curve to project", rs.filter.curve)
      #Project down...
      results = rs.ProjectCurveToMesh(curve, mesh, (0,0,-1))
    See Also:
      ProjectCurveToSurface
      ProjectPointToMesh
      ProjectPointToSurface
    """
    curve_ids = rhutil.coerceguidlist(curve_ids)
    mesh_ids = rhutil.coerceguidlist(mesh_ids)
    direction = rhutil.coerce3dvector(direction, True)
    curves = [rhutil.coercecurve(id, -1, True) for id in curve_ids]
    meshes = [rhutil.coercemesh(id, True) for id in mesh_ids]
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    newcurves = Rhino.Geometry.Curve.ProjectToMesh(curves, meshes, direction, tolerance)
    ids = [scriptcontext.doc.Objects.AddCurve(curve) for curve in newcurves]
    if ids: scriptcontext.doc.Views.Redraw()
    return ids


def ProjectCurveToSurface(curve_ids, surface_ids, direction):
    """Projects one or more curves onto one or more surfaces or polysurfaces
    Parameters:
      curve_ids ([guid, ...]): identifiers of curves to project
      surface_ids ([guid, ...]): identifiers of surfaces to project onto
      direction (vector): projection direction
    Returns:
      list(guid, ...): list of identifiers
    Example:
      import rhinoscriptsyntax as rs
      surface = rs.GetObject("Select surface to project onto", rs.filter.surface)
      curve = rs.GetObject("Select curve to project", rs.filter.curve)
      # Project down...
      results = rs.ProjectCurveToSurface(curve, surface, (0,0,-1))
    See Also:
      ProjectCurveToMesh
      ProjectPointToMesh
      ProjectPointToSurface
    """
    curve_ids = rhutil.coerceguidlist(curve_ids)
    surface_ids = rhutil.coerceguidlist(surface_ids)
    direction = rhutil.coerce3dvector(direction, True)
    curves = [rhutil.coercecurve(id, -1, True) for id in curve_ids]
    breps = [rhutil.coercebrep(id, True) for id in surface_ids]
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    newcurves = Rhino.Geometry.Curve.ProjectToBrep(curves, breps, direction, tolerance)
    ids = [scriptcontext.doc.Objects.AddCurve(curve) for curve in newcurves]
    if ids: scriptcontext.doc.Views.Redraw()
    return ids


def RebuildCurve(curve_id, degree=3, point_count=10):
    """Rebuilds a curve to a given degree and control point count. For more
    information, see the Rhino help for the Rebuild command.
    Parameters:
      curve_id (guid): identifier of the curve object
      degree (number, optional): new degree (must be greater than 0)
      point_count (number, optional) new point count, which must be bigger than degree.
    Returns:
      bool: True of False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select curve to rebuild", rs.filter.curve)
      if curve: rs.RebuildCurve(curve, 3, 10)
    See Also:
      RebuildSurface
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if degree<1: raise ValueError("degree must be greater than 0")
    newcurve = curve.Rebuild(point_count, degree, False)
    if not newcurve: return False
    scriptcontext.doc.Objects.Replace(curve_id, newcurve)
    scriptcontext.doc.Views.Redraw()
    return True


def RemoveCurveKnot(curve, parameter):
    """Deletes a knot from a curve object.
    Parameters:
      curve (guid): The reference of the source object
      parameter (number): The parameter on the curve. Note, if the parameter is not equal to one
                      of the existing knots, then the knot closest to the specified parameter
                      will be removed.
    Returns:
      bool: True of False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs

      crv_info = rs.GetCurveObject("Select curve near knot to be removed")
      if crv_info:
          crv_id = crv_info[0]
          crv_param = crv_info[4]
          rs.RemoveCurveKnot(crv_id, crv_param)
    See Also:
      RemoveSurfaceKnot
    """
    curve_inst = rhutil.coercecurve(curve, -1, True)
    success, n_param = curve_inst.GetCurveParameterFromNurbsFormParameter(parameter)
    if not success: return False
    n_curve = curve_inst.ToNurbsCurve()
    if not n_curve: return False
    success = n_curve.Knots.RemoveKnotAt(n_param)
    if not success: return False
    scriptcontext.doc.Objects.Replace(curve, n_curve)
    scriptcontext.doc.Views.Redraw()
    return True


def ReverseCurve(curve_id):
    """Reverses the direction of a curve object. Same as Rhino's Dir command
    Parameters:
      curve_id (guid): identifier of the curve object
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve to reverse")
      if rs.IsCurve(curve): rs.ReverseCurve(curve)
    See Also:
      CurveDirectionsMatch
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if curve.Reverse():
        curve_id = rhutil.coerceguid(curve_id, True)
        scriptcontext.doc.Objects.Replace(curve_id, curve)
        return True
    return False


def SimplifyCurve(curve_id, flags=0):
    """Replace a curve with a geometrically equivalent polycurve.
    
    The polycurve will have the following properties:
     - All the polycurve segments are lines, polylines, arcs, or NURBS curves.
     - The NURBS curves segments do not have fully multiple interior knots.
     - Rational NURBS curves do not have constant weights.
     - Any segment for which IsCurveLinear or IsArc is True is a line, polyline segment, or an arc.
     - Adjacent co-linear or co-circular segments are combined.
     - Segments that meet with G1-continuity have there ends tuned up so that they meet with G1-continuity to within machine precision.
     - If the polycurve is a polyline, a polyline will be created


    Parameters:
      curve_id (guid): the object's identifier
      flags (number, optional): the simplification methods to use. By default, all methods are used (flags = 0)
        Value Description
        0     Use all methods.
        1     Do not split NURBS curves at fully multiple knots.
        2     Do not replace segments with IsCurveLinear = True with line curves.
        4     Do not replace segments with IsArc = True with arc curves.
        8     Do not replace rational NURBS curves with constant denominator with an equivalent non-rational NURBS curve.
        16    Do not adjust curves at G1-joins.
        32    Do not merge adjacent co-linear lines or co-circular arcs or combine consecutive line segments into a polyline.

    Returns:
      bool: True or False
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve to simplify", rs.filter.curve)
      if curve: rs.SimplifyCurve(curve)
    See Also:
      IsArc
      IsCurveLinear
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    _flags = Rhino.Geometry.CurveSimplifyOptions.All
    if( flags&1 ==1 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.SplitAtFullyMultipleKnots)
    if( flags&2 ==2 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.RebuildLines)
    if( flags&4 ==4 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.RebuildArcs)
    if( flags&8 ==8 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.RebuildRationals)
    if( flags&16==16 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.AdjustG1)
    if( flags&32==32 ): _flags &= (~Rhino.Geometry.CurveSimplifyOptions.Merge)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    ang_tol = scriptcontext.doc.ModelAngleToleranceRadians
    newcurve = curve.Simplify(_flags, tol, ang_tol)
    if newcurve:
        curve_id = rhutil.coerceguid(curve_id, True)
        scriptcontext.doc.Objects.Replace(curve_id, newcurve)
        scriptcontext.doc.Views.Redraw()
        return True
    return False


def SplitCurve(curve_id, parameter, delete_input=True):
    """Splits, or divides, a curve at a specified parameter. The parameter must
    be in the interior of the curve's domain
    Parameters:
      curve_id (guid): the curve to split
      parameter ({number, ...]) one or more parameters to split the curve at
      delete_input (bool, optional): delete the input curve
    Returns:
      list(guid, ....): list of new curves on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve to split", rs.filter.curve)
      if rs.IsCurve(curve):
          domain = rs.CurveDomain(curve)
          parameter = domain[1] / 2.0
          rs.SplitCurve( curve, parameter )
    See Also:
      TrimCurve
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    newcurves = curve.Split(parameter)
    if newcurves is None: return scriptcontext.errorhandler()
    att = None
    rhobj = rhutil.coercerhinoobject(curve_id)
    if rhobj: att = rhobj.Attributes
    rc = [scriptcontext.doc.Objects.AddCurve(crv, att) for crv in newcurves]
    if rc and delete_input:
        id = rhutil.coerceguid(curve_id, True)
        scriptcontext.doc.Objects.Delete(id, True)
    scriptcontext.doc.Views.Redraw()
    return rc


def TrimCurve(curve_id, interval, delete_input=True):
    """Trims a curve by removing portions of the curve outside a specified interval
    Parameters:
      curve_id (guid):the curve to trim
      interval ([number, number]): two numbers identifying the interval to keep. Portions of
        the curve before domain[0] and after domain[1] will be removed. If the
        input curve is open, the interval must be increasing. If the input
        curve is closed and the interval is decreasing, then the portion of
        the curve across the start and end of the curve is returned
      delete_input (bool): delete the input curve. If omitted the input curve is deleted.
    Returns:
      list(guid, ...): identifier of the new curve on success
      None: on failure
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select a curve to trim", rs.filter.curve)
      if rs.IsCurve(curve):
          domain = rs.CurveDomain(curve)
          domain[1] /= 2.0
          rs.TrimCurve( curve, domain )
    See Also:
      SplitCurve
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    if interval[0]==interval[1]: raise ValueError("interval values are equal")
    newcurve = curve.Trim(interval[0], interval[1])
    if not newcurve: return scriptcontext.errorhandler()
    att = None
    rhobj = rhutil.coercerhinoobject(curve_id)
    if rhobj: att = rhobj.Attributes
    rc = scriptcontext.doc.Objects.AddCurve(newcurve, att)
    if delete_input:
        id = rhutil.coerceguid(curve_id, True)
        scriptcontext.doc.Objects.Delete(id, True)
    scriptcontext.doc.Views.Redraw()
    return rc


def ChangeCurveDegree(object_id, degree):
    """Changes the degree of a curve object. For more information see the Rhino help file for the ChangeDegree command.
      Parameters:
        object_id (guid): the object's identifier.
        degree (number): the new degree.
      Returns:
        bool: True of False indicating success or failure.
        None: on failure
      Example:
    
      See Also:
        IsCurve
        CurveDegree
    """ 
    curve = rhutil.coercerhinoobject(object_id)
    if not curve: return None
    if not isinstance(curve, Rhino.DocObjects.CurveObject): return None

    curve = curve.CurveGeometry
    if not isinstance(curve, Rhino.Geometry.NurbsCurve):
        curve = curve.ToNurbsCurve()

    max_nurbs_degree = 11
    if degree < 1 or degree > max_nurbs_degree or curve.Degree == degree:
        return None

    r = False
    if curve.IncreaseDegree(degree):
        r = scriptcontext.doc.Objects.Replace(object_id, curve)
    return r


def AddTweenCurves(from_curve_id, to_curve_id, number_of_curves = 1, method = 0, sample_number = 10):
    """Creates curves between two open or closed input curves.
    Parameters:
      from_curve_id (guid): identifier of the first curve object.
      to_curve_id (guid): identifier of the second curve object.
      number_of_curves (number): The number of curves to create. The default is 1.
      method (number): The method for refining the output curves, where:
        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.
        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.
        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.
      sample_number (number): The number of samples points to use if method is 2. The default is 10.
    Returns:
      list(guid, ...): The identifiers of the new tween objects if successful, None on error.
    Example:
      import rhinoscriptsyntax as rs
      curveA = rs.GetObject("Select first curve", rs.filter.curve)
      curveB = rs.GetObject("Select second curve", rs.filter.curve)
      arrResult = rs.AddTweenCurves(curveA, curveB, 6, 2, 30)
    """
    curve0 = rhutil.coercecurve(from_curve_id, -1, True)
    curve1 = rhutil.coercecurve(to_curve_id, -1, True)
    out_curves = 0
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    if method == 0:
        out_curves = Rhino.Geometry.Curve.CreateTweenCurves(curve0, curve1, number_of_curves, tolerance)
    elif method == 1:
        out_curves = Rhino.Geometry.Curve.CreateTweenCurvesWithMatching(curve0, curve1, number_of_curves, tolerance)
    elif method == 2:
        out_curves = Rhino.Geometry.Curve.CreateTweenCurvesWithSampling(curve0, curve1, number_of_curves, sample_number, tolerance)
    else: raise ValueError("method must be 0, 1, or 2")
    curves = None
    if out_curves:
        curves = []
        for curve in out_curves:
            if curve and curve.IsValid:
                rc = scriptcontext.doc.Objects.AddCurve(curve)
            curve.Dispose()
            if rc==System.Guid.Empty: raise Exception("unable to add curve to document")
            curves.append(rc)
        scriptcontext.doc.Views.Redraw()
    return curves

```
Page 7/7FirstPrevNextLast