#
tokens: 43366/50000 1/82 files (page 7/8)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 7 of 8. Use http://codebase.md/jingcheng-chen/rhinomcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .github
│   └── workflows
│       ├── mcp-server-publish.yml
│       └── rhino-plugin-publish.yml
├── .gitignore
├── assets
│   ├── claude_enable_instruction.jpg
│   ├── cursor_enable_instruction.jpg
│   ├── cursor_usage_instruction.jpg
│   ├── demo1.jpg
│   ├── demo2.jpg
│   ├── rhino_plugin_instruction.jpg
│   └── rhinomcp_logo.svg
├── demo_chats
│   ├── create_6x6x6_boxes.txt
│   └── create_rhinoceros_lego_blocks.txt
├── LICENSE
├── README.md
├── rhino_mcp_plugin
│   ├── .gitignore
│   ├── Commands
│   │   ├── MCPStartCommand.cs
│   │   ├── MCPStopCommand.cs
│   │   └── MCPVersionCommand.cs
│   ├── EmbeddedResources
│   │   └── plugin-utility.ico
│   ├── Functions
│   │   ├── _utils.cs
│   │   ├── CreateLayer.cs
│   │   ├── CreateObject.cs
│   │   ├── CreateObjects.cs
│   │   ├── DeleteLayer.cs
│   │   ├── DeleteObject.cs
│   │   ├── ExecuteRhinoscript.cs
│   │   ├── GetDocumentInfo.cs
│   │   ├── GetObjectInfo.cs
│   │   ├── GetOrSetCurrentLayer.cs
│   │   ├── GetSelectedObjectsInfo.cs
│   │   ├── ModifyObject.cs
│   │   ├── ModifyObjects.cs
│   │   └── SelectObjects.cs
│   ├── manifest.yml
│   ├── Properties
│   │   ├── AssemblyInfo.cs
│   │   └── launchSettings.json
│   ├── rhinomcp.csproj
│   ├── rhinomcp.sln
│   ├── RhinoMCPPlugin.cs
│   ├── RhinoMCPServer.cs
│   ├── RhinoMCPServerController.cs
│   └── Serializers
│       └── Serializer.cs
└── rhino_mcp_server
    ├── .gitignore
    ├── dev.sh
    ├── main.py
    ├── pyproject.toml
    ├── README.md
    ├── src
    │   └── rhinomcp
    │       ├── __init__.py
    │       ├── prompts
    │       │   └── assert_general_strategy.py
    │       ├── server.py
    │       ├── static
    │       │   └── rhinoscriptsyntax.py
    │       └── tools
    │           ├── create_layer.py
    │           ├── create_object.py
    │           ├── create_objects.py
    │           ├── delete_layer.py
    │           ├── delete_object.py
    │           ├── execute_rhinoscript_python_code.py
    │           ├── get_document_info.py
    │           ├── get_object_info.py
    │           ├── get_or_set_current_layer.py
    │           ├── get_rhinoscript_python_code_guide.py
    │           ├── get_rhinoscript_python_function_names.py
    │           ├── get_selected_objects_info.py
    │           ├── modify_object.py
    │           ├── modify_objects.py
    │           └── select_objects.py
    ├── static
    │   ├── application.py
    │   ├── block.py
    │   ├── compat.py
    │   ├── curve.py
    │   ├── dimension.py
    │   ├── document.py
    │   ├── geometry.py
    │   ├── grips.py
    │   ├── group.py
    │   ├── hatch.py
    │   ├── layer.py
    │   ├── light.py
    │   ├── line.py
    │   ├── linetype.py
    │   ├── material.py
    │   ├── mesh.py
    │   ├── object.py
    │   ├── plane.py
    │   ├── pointvector.py
    │   ├── selection.py
    │   ├── surface.py
    │   ├── toolbar.py
    │   ├── transformation.py
    │   ├── userdata.py
    │   ├── userinterface.py
    │   ├── utility.py
    │   └── view.py
    └── uv.lock
```

# Files

--------------------------------------------------------------------------------
/rhino_mcp_server/static/surface.py:
--------------------------------------------------------------------------------

```python
   1 | import math
   2 | 
   3 | import System
   4 | from System.Collections.Generic import List
   5 | 
   6 | import Rhino
   7 | 
   8 | import scriptcontext
   9 | 
  10 | import rhinocompat as compat
  11 | from rhinoscript import utility as rhutil
  12 | from rhinoscript import object as rhobject
  13 | 
  14 | 
  15 | def AddBox(corners):
  16 |     """Adds a box shaped polysurface to the document
  17 |     Parameters:
  18 |       corners ([point, point, point ,point, point, point ,point,point]) 8 points that define the corners of the box. Points need to
  19 |         be in counter-clockwise order starting with the bottom rectangle of the box
  20 |     Returns:
  21 |       guid: identifier of the new object on success
  22 |     Example:
  23 |       import rhinoscriptsyntax as rs
  24 |       box = rs.GetBox()
  25 |       if box: rs.AddBox(box)
  26 |     See Also:
  27 |       AddCone
  28 |       AddCylinder
  29 |       AddSphere
  30 |       AddTorus
  31 |     """
  32 |     box = rhutil.coerce3dpointlist(corners, True)
  33 |     brep = Rhino.Geometry.Brep.CreateFromBox(box)
  34 |     if not brep: raise ValueError("unable to create brep from box")
  35 |     rc = scriptcontext.doc.Objects.AddBrep(brep)
  36 |     if rc==System.Guid.Empty: raise Exception("unable to add brep to document")
  37 |     scriptcontext.doc.Views.Redraw()
  38 |     return rc
  39 | 
  40 | 
  41 | def AddCone(base, height, radius, cap=True):
  42 |     """Adds a cone shaped polysurface to the document
  43 |     Parameters:
  44 |       base (point|plane): 3D origin point of the cone or a plane with an apex at the origin
  45 |           and normal along the plane's z-axis
  46 |       height (point|number): 3D height point of the cone if base is a 3D point. The height
  47 |           point defines the height and direction of the cone. If base is a
  48 |           plane, height is a numeric value
  49 |       radius (number): the radius at the base of the cone
  50 |       cap (bool, optional): cap base of the cone
  51 |     Returns:
  52 |       guid: identifier of the new object on success
  53 |     Example:
  54 |       import rhinoscriptsyntax as rs
  55 |       radius = 5.0
  56 |       base = rs.GetPoint("Base of cone")
  57 |       if base:
  58 |           height = rs.GetPoint("Height of cone", base)
  59 |           if height: rs.AddCone(base, height, radius)
  60 |     See Also:
  61 |       AddBox
  62 |       AddCylinder
  63 |       AddSphere
  64 |       AddTorus
  65 |     """
  66 |     plane = None
  67 |     height_point = rhutil.coerce3dpoint(height)
  68 |     if height_point is None:
  69 |         plane = rhutil.coerceplane(base, True)
  70 |     else:
  71 |         base_point = rhutil.coerce3dpoint(base, True)
  72 |         normal = base_point - height_point
  73 |         height = normal.Length
  74 |         plane = Rhino.Geometry.Plane(height_point, normal)
  75 |     cone = Rhino.Geometry.Cone(plane, height, radius)
  76 |     brep = Rhino.Geometry.Brep.CreateFromCone(cone, cap)
  77 |     rc = scriptcontext.doc.Objects.AddBrep(brep)
  78 |     scriptcontext.doc.Views.Redraw()
  79 |     return rc
  80 | 
  81 | 
  82 | def AddCutPlane(object_ids, start_point, end_point, normal=None):
  83 |     """Adds a planar surface through objects at a designated location. For more
  84 |     information, see the Rhino help file for the CutPlane command
  85 |     Parameters:
  86 |       objects_ids ([guid, ...]): identifiers of objects that the cutting plane will
  87 |           pass through
  88 |       start_point, end_point (line): line that defines the cutting plane
  89 |       normal (vector, optional): vector that will be contained in the returned planar
  90 |           surface. In the case of Rhino's CutPlane command, this is the
  91 |           normal to, or Z axis of, the active view's construction plane.
  92 |           If omitted, the world Z axis is used
  93 |     Returns:
  94 |       guid: identifier of new object on success
  95 |       None: on error
  96 |     Example:
  97 |       import rhinoscriptsyntax as rs
  98 |       objs = rs.GetObjects("Select objects for cut plane")
  99 |       if objs:
 100 |           point0 = rs.GetPoint("Start of cut plane")
 101 |           if point0:
 102 |               point1 = rs.GetPoint("End of cut plane", point0)
 103 |               if point1: rs.AddCutPlane( objs, point0, point1 )
 104 |     See Also:
 105 |       AddPlaneSurface
 106 |     """
 107 |     objects = []
 108 |     for id in object_ids:
 109 |         rhobj = rhutil.coercerhinoobject(id, True, True)
 110 |         objects.append(rhobj)
 111 | 
 112 |     rc, bbox = Rhino.DocObjects.RhinoObject.GetTightBoundingBox(objects)
 113 |     if not bbox.IsValid:
 114 |         return scriptcontext.errorhandler()
 115 | 
 116 |     bbox_min = bbox.Min
 117 |     bbox_max = bbox.Max
 118 |     for i in range(0, 3):
 119 |         if (System.Math.Abs(bbox_min[i] - bbox_max[i]) < Rhino.RhinoMath.SqrtEpsilon):
 120 |             bbox_min[i] = bbox_min[i] - 1.0
 121 |             bbox_max[i] = bbox_max[i] + 1.0
 122 | 
 123 |     v = bbox_max - bbox_min
 124 |     v = v * 1.1
 125 |     p = bbox_min + v
 126 |     bbox_min = bbox_max - v
 127 |     bbox_max = p
 128 |     bbox = Rhino.Geometry.BoundingBox(bbox_min, bbox_max)
 129 | 
 130 |     start_point = rhutil.coerce3dpoint(start_point, True)
 131 |     end_point = rhutil.coerce3dpoint(end_point, True)
 132 |     line = Rhino.Geometry.Line(start_point, end_point)
 133 |     if normal:
 134 |         normal = rhutil.coerce3dvector(normal, True)
 135 |     else:
 136 |         normal = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane().Normal
 137 | 
 138 |     surface = Rhino.Geometry.PlaneSurface.CreateThroughBox(line, normal, bbox)
 139 |     if surface is None: return scriptcontext.errorhandler()
 140 |     id = scriptcontext.doc.Objects.AddSurface(surface)
 141 |     if id==System.Guid.Empty: return scriptcontext.errorhandler()
 142 |     scriptcontext.doc.Views.Redraw()
 143 |     return id
 144 | 
 145 | 
 146 | def AddCylinder(base, height, radius, cap=True):
 147 |     """Adds a cylinder-shaped polysurface to the document
 148 |     Parameters:
 149 |       base (point|plane): The 3D base point of the cylinder or the base plane of the cylinder
 150 |       height (point|number): if base is a point, then height is a 3D height point of the
 151 |         cylinder. The height point defines the height and direction of the
 152 |         cylinder. If base is a plane, then height is the numeric height value
 153 |         of the cylinder
 154 |       radius (number): radius of the cylinder
 155 |       cap (bool, optional): cap the cylinder
 156 |     Returns:
 157 |       guid: identifier of new object if successful
 158 |       None: on error
 159 |     Example:
 160 |       import rhinoscriptsyntax as rs
 161 |       radius = 5.0
 162 |       base = rs.GetPoint("Base of cylinder")
 163 |       if base:
 164 |           height = rs.GetPoint("Height of cylinder", base)
 165 |           if height: rs.AddCylinder( base, height, radius )
 166 |     See Also:
 167 |       AddBox
 168 |       AddCone
 169 |       AddSphere
 170 |       AddTorus
 171 |     """
 172 |     cylinder=None
 173 |     height_point = rhutil.coerce3dpoint(height)
 174 |     if height_point:
 175 |         #base must be a point
 176 |         base = rhutil.coerce3dpoint(base, True)
 177 |         normal = height_point-base
 178 |         plane = Rhino.Geometry.Plane(base, normal)
 179 |         height = normal.Length
 180 |         circle = Rhino.Geometry.Circle(plane, radius)
 181 |         cylinder = Rhino.Geometry.Cylinder(circle, height)
 182 |     else:
 183 |         #base must be a plane
 184 |         if type(base) is Rhino.Geometry.Point3d: base = [base.X, base.Y, base.Z]
 185 |         base = rhutil.coerceplane(base, True)
 186 |         circle = Rhino.Geometry.Circle(base, radius)
 187 |         cylinder = Rhino.Geometry.Cylinder(circle, height)
 188 |     brep = cylinder.ToBrep(cap, cap)
 189 |     id = scriptcontext.doc.Objects.AddBrep(brep)
 190 |     if id==System.Guid.Empty: return scriptcontext.errorhandler()
 191 |     scriptcontext.doc.Views.Redraw()
 192 |     return id
 193 | 
 194 | 
 195 | def AddEdgeSrf(curve_ids):
 196 |     """Creates a surface from 2, 3, or 4 edge curves
 197 |     Parameters:
 198 |       curve_ids ([guid, ...]): list or tuple of curves
 199 |     Returns:
 200 |       guid: identifier of new object if successful
 201 |       None: on error
 202 |     Example:
 203 |       import rhinoscriptsyntax as rs
 204 |       curves = rs.GetObjects("Select 2, 3, or 4 curves", rs.filter.curve)
 205 |       if curves and len(curves)>1 ): rs.AddEdgeSrf(curves)
 206 |     See Also:
 207 |       AddPlanarSrf
 208 |       AddSrfControlPtGrid
 209 |       AddSrfPt
 210 |       AddSrfPtGrid
 211 |     """
 212 |     curves = [rhutil.coercecurve(id, -1, True) for id in curve_ids]
 213 |     brep = Rhino.Geometry.Brep.CreateEdgeSurface(curves)
 214 |     if brep is None: return scriptcontext.errorhandler()
 215 |     id = scriptcontext.doc.Objects.AddBrep(brep)
 216 |     if id==System.Guid.Empty: return scriptcontext.errorhandler()
 217 |     scriptcontext.doc.Views.Redraw()
 218 |     return id
 219 | 
 220 | 
 221 | def AddNetworkSrf(curves, continuity=1, edge_tolerance=0, interior_tolerance=0, angle_tolerance=0):
 222 |     """Creates a surface from a network of crossing curves
 223 |     Parameters:
 224 |       curves ([guid, ...]): curves from which to create the surface
 225 |       continuity (number, optional): how the edges match the input geometry
 226 |                  0 = loose
 227 |                  1 = position
 228 |                  2 = tangency
 229 |                  3 = curvature
 230 |     Returns:
 231 |       guid: identifier of new object if successful
 232 |     Example:
 233 |       import rhinoscriptsyntax as  rs
 234 |       curve_ids = rs.GetObjects("Select  curves in network", 4, True, True)
 235 |       if len(curve_ids) > 0:
 236 |           rs.AddNetworkSrf(curve_ids)
 237 |     See Also:
 238 |       
 239 |     """
 240 |     curves = [rhutil.coercecurve(curve, -1, True) for curve in curves]
 241 |     surf, err = Rhino.Geometry.NurbsSurface.CreateNetworkSurface(curves, continuity, edge_tolerance, interior_tolerance, angle_tolerance)
 242 |     if surf:
 243 |         rc = scriptcontext.doc.Objects.AddSurface(surf)
 244 |         scriptcontext.doc.Views.Redraw()
 245 |         return rc
 246 | 
 247 | 
 248 | def AddNurbsSurface(point_count, points, knots_u, knots_v, degree, weights=None):
 249 |     """Adds a NURBS surface object to the document
 250 |     Parameters:
 251 |       point_count ([number, number]) number of control points in the u and v direction
 252 |       points ({point, ...]): list of 3D points
 253 |       knots_u ([number, ...]): knot values for the surface in the u direction.
 254 |                 Must contain point_count[0]+degree[0]-1 elements
 255 |       knots_v ([number, ...]): knot values for the surface in the v direction.
 256 |                 Must contain point_count[1]+degree[1]-1 elements
 257 |       degree ([number, number]): degree of the surface in the u and v directions.
 258 |       weights [(number, ...]): weight values for the surface. The number of elements in
 259 |         weights must equal the number of elements in points. Values must be
 260 |         greater than zero.
 261 |     Returns:
 262 |       guid: identifier of new object if successful
 263 |       None on error
 264 |     Example:
 265 |       import rhinoscriptsyntax as rs
 266 |       obj = rs.GetObject("Pick a surface", rs.filter.surface)
 267 |       if obj:
 268 |           point_count = rs.SurfacePointCount(obj)
 269 |           points = rs.SurfacePoints(obj)
 270 |           knots = rs.SurfaceKnots(obj)
 271 |           degree = rs.SurfaceDegree(obj)
 272 |           if rs.IsSurfaceRational(obj):
 273 |               weights = rs.SurfaceWeights(obj)
 274 |               obj = rs.AddNurbsSurface(point_count, points, knots[0], knots[1], degree, weights)
 275 |           else:
 276 |               obj = rs.AddNurbsSurface(point_count, points, knots[0], knots[1], degree)
 277 |           if obj: rs.SelectObject(obj)
 278 |     See Also:
 279 |       IsSurfaceRational
 280 |       SurfaceDegree
 281 |       SurfaceKnotCount
 282 |       SurfaceKnots
 283 |       SurfacePointCount
 284 |       SurfacePoints
 285 |       SurfaceWeights
 286 |     """
 287 |     if len(points)<(point_count[0]*point_count[1]):
 288 |         return scriptcontext.errorhandler()
 289 |     ns = Rhino.Geometry.NurbsSurface.Create(3, weights!=None, degree[0]+1, degree[1]+1, point_count[0], point_count[1])
 290 |     #add the points and weights
 291 |     controlpoints = ns.Points
 292 |     index = 0
 293 |     for i in range(point_count[0]):
 294 |         for j in range(point_count[1]):
 295 |             if weights:
 296 |                 cp = Rhino.Geometry.ControlPoint(points[index], weights[index])
 297 |                 controlpoints.SetControlPoint(i,j,cp)
 298 |             else:
 299 |                 cp = Rhino.Geometry.ControlPoint(points[index])
 300 |                 controlpoints.SetControlPoint(i,j,cp)
 301 |             index += 1
 302 |     #add the knots
 303 |     for i in range(ns.KnotsU.Count): ns.KnotsU[i] = knots_u[i]
 304 |     for i in range(ns.KnotsV.Count): ns.KnotsV[i] = knots_v[i]
 305 |     if not ns.IsValid: return scriptcontext.errorhandler()
 306 |     id = scriptcontext.doc.Objects.AddSurface(ns)
 307 |     if id==System.Guid.Empty: return scriptcontext.errorhandler()
 308 |     scriptcontext.doc.Views.Redraw()
 309 |     return id
 310 | 
 311 | 
 312 | def AddPatch(object_ids, uv_spans_tuple_OR_surface_object_id, tolerance=None, trim=True, point_spacing=0.1, flexibility=1.0, surface_pull=1.0, fix_edges=False):
 313 |     """Fits a surface through curve, point, point cloud, and mesh objects.
 314 |     Parameters:
 315 |       object_ids ({guid, ...]): a list of object identifiers that indicate the objects to use for the patch fitting.
 316 |           Acceptable object types include curves, points, point clouds, and meshes.
 317 |       uv_spans_tuple_OR_surface_object_id ([number, number]|guid):  the U and V direction span counts for the automatically generated surface OR
 318 |           The identifier of the starting surface.  It is best if you create a starting surface that is similar in shape 
 319 |           to the surface you are trying to create.
 320 |       tolerance (number, optional): The tolerance used by input analysis functions. If omitted, Rhino's document absolute tolerance is used.
 321 |       trim (bool, optional): Try to find an outside curve and trims the surface to it.  The default value is True.
 322 |       point_spacing (number, optional): The basic distance between points sampled from input curves.  The default value is 0.1.
 323 |       flexibility (number, optional): Determines the behavior of the surface in areas where its not otherwise controlled by the input.
 324 |           Lower numbers make the surface behave more like a stiff material, higher, more like a flexible material.  
 325 |           That is, each span is made to more closely match the spans adjacent to it if there is no input geometry 
 326 |           mapping to that area of the surface when the flexibility value is low.  The scale is logarithmic.  
 327 |           For example, numbers around 0.001 or 0.1 make the patch pretty stiff and numbers around 10 or 100 
 328 |           make the surface flexible.  The default value is 1.0.
 329 |       surface_pull (number, optional): Similar to stiffness, but applies to the starting surface. The bigger the pull, the closer
 330 |           the resulting surface shape will be to the starting surface.  The default value is 1.0.
 331 |       fix_edges (bool, optional): Clamps the edges of the starting surface in place. This option is useful if you are using a
 332 |           curve or points for deforming an existing surface, and you do not want the edges of the starting surface 
 333 |           to move.  The default if False.
 334 |     Returns:
 335 |       guid: Identifier of the new surface object if successful.
 336 |       None: on error.
 337 |     Example:
 338 |     See Also:
 339 |     """
 340 |     # System.Collections.List instead of Python list because IronPython is
 341 |     # having problems converting a list to an IEnumerable<GeometryBase> which
 342 |     # is the 1st argument for Brep.CreatePatch
 343 |     geometry = List[Rhino.Geometry.GeometryBase]()
 344 |     u_span = 10
 345 |     v_span = 10
 346 |     rc = None
 347 |     id = rhutil.coerceguid(object_ids, False)
 348 |     if id: object_ids = [id]
 349 |     for object_id in object_ids:
 350 |         rhobj = rhutil.coercerhinoobject(object_id, False, False)
 351 |         if not rhobj: return None
 352 |         geometry.Add( rhobj.Geometry )
 353 |     if not geometry: return None
 354 |     
 355 |     surface = None
 356 |     if uv_spans_tuple_OR_surface_object_id:
 357 |       if type(uv_spans_tuple_OR_surface_object_id) is tuple:
 358 |         u_span = uv_spans_tuple_OR_surface_object_id[0]
 359 |         v_span = uv_spans_tuple_OR_surface_object_id[1]
 360 |       else:
 361 |         surface = rhutil.coercesurface(uv_spans_tuple_OR_surface_object_id, False)
 362 | 
 363 |     if not tolerance: tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 364 |     b = System.Array.CreateInstance(bool, 4)
 365 |     for i in range(4): b[i] = fix_edges
 366 |     brep = Rhino.Geometry.Brep.CreatePatch(geometry, surface, u_span, v_span, trim, False, point_spacing, flexibility, surface_pull, b, tolerance)
 367 |     if brep:
 368 |       rc = scriptcontext.doc.Objects.AddBrep(brep)
 369 |       scriptcontext.doc.Views.Redraw()
 370 |     return rc
 371 | 
 372 | 
 373 | def AddPipe(curve_id, parameters, radii, blend_type=0, cap=0, fit=False):
 374 |     """Creates a single walled surface with a circular profile around a curve
 375 |     Parameters:
 376 |       curve_id (guid): identifier of rail curve
 377 |       parameters, radii ([number, ...]): list of radius values at normalized curve parameters
 378 |       blend_type (number, optional): 0(local) or 1(global)
 379 |       cap (number, optional): 0(none), 1(flat), 2(round)
 380 |       fit (bool, optional): attempt to fit a single surface
 381 |     Returns:
 382 |       list(guid, ...): identifiers of new objects created
 383 |     Example:
 384 |       import rhinoscriptsyntax as rs
 385 |       curve = rs.GetObject("Select curve to create pipe around", rs.filter.curve, True)
 386 |       if curve:
 387 |           domain = rs.CurveDomain(curve)
 388 |           rs.AddPipe(curve, 0, 4)
 389 |     See Also:
 390 |       
 391 |     """
 392 |     rail = rhutil.coercecurve(curve_id, -1, True)
 393 |     abs_tol = scriptcontext.doc.ModelAbsoluteTolerance
 394 |     ang_tol = scriptcontext.doc.ModelAngleToleranceRadians
 395 |     if type(parameters) is int or type(parameters) is float: parameters = [parameters]
 396 |     if type(radii) is int or type(radii) is float: radii = [radii]
 397 |     parameters = compat.ITERATOR2LIST(map(float,parameters))
 398 |     radii = compat.ITERATOR2LIST(map(float,radii))
 399 |     cap = System.Enum.ToObject(Rhino.Geometry.PipeCapMode, cap)
 400 |     breps = Rhino.Geometry.Brep.CreatePipe(rail, parameters, radii, blend_type==0, cap, fit, abs_tol, ang_tol)
 401 |     rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in breps]
 402 |     scriptcontext.doc.Views.Redraw()
 403 |     return rc
 404 | 
 405 | 
 406 | def AddPlanarSrf(object_ids):
 407 |     """Creates one or more surfaces from planar curves
 408 |     Parameters:
 409 |       object_ids ({guid, ...]): curves to use for creating planar surfaces
 410 |     Returns:
 411 |       list(guid, ...): identifiers of surfaces created on success
 412 |       None: on error
 413 |     Example:
 414 |       import rhinoscriptsyntax as rs
 415 |       objs = rs.GetObjects("Select planar curves to build surface", rs.filter.curve)
 416 |       if objs: rs.AddPlanarSrf(objs)
 417 |     See Also:
 418 |       AddEdgeSrf
 419 |       AddSrfControlPtGrid
 420 |       AddSrfPt
 421 |       AddSrfPtGrid
 422 |     """
 423 |     id = rhutil.coerceguid(object_ids, False)
 424 |     if id: object_ids = [id]
 425 |     curves = [rhutil.coercecurve(id,-1,True) for id in object_ids]
 426 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 427 |     breps = Rhino.Geometry.Brep.CreatePlanarBreps(curves, tolerance)
 428 |     if breps:
 429 |         rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in breps]
 430 |         scriptcontext.doc.Views.Redraw()
 431 |         return rc
 432 | 
 433 | 
 434 | def AddPlaneSurface(plane, u_dir, v_dir):
 435 |     """Create a plane surface and add it to the document.
 436 |     Parameters:
 437 |       plane (plane): The plane.
 438 |       u_dir (number): The magnitude in the U direction.
 439 |       v_dir (number): The magnitude in the V direction.
 440 |     Returns:
 441 |       guid: The identifier of the new object if successful.
 442 |       None: if not successful, or on error.
 443 |     Example:
 444 |       import rhinoscriptsyntax as rs
 445 |       rs.AddPlaneSurface( rs.WorldXYPlane(), 5.0, 3.0 )
 446 |     See Also:
 447 |       AddCutPlane
 448 |       AddEdgeSrf
 449 |       AddSrfControlPtGrid
 450 |       AddSrfPt
 451 |       AddSrfPtGrid
 452 |       IsPlaneSurface
 453 |     """
 454 |     plane = rhutil.coerceplane(plane, True)
 455 |     u_interval = Rhino.Geometry.Interval(0, u_dir)
 456 |     v_interval = Rhino.Geometry.Interval(0, v_dir)
 457 |     plane_surface = Rhino.Geometry.PlaneSurface(plane, u_interval, v_interval) 
 458 |     if plane_surface is None: return scriptcontext.errorhandler()
 459 |     rc = scriptcontext.doc.Objects.AddSurface(plane_surface)
 460 |     if rc==System.Guid.Empty: return scriptcontext.errorhandler()
 461 |     scriptcontext.doc.Views.Redraw()
 462 |     return rc
 463 | 
 464 | 
 465 | def AddLoftSrf(object_ids, start=None, end=None, loft_type=0, simplify_method=0, value=0, closed=False):
 466 |     """Adds a surface created by lofting curves to the document.
 467 |     - no curve sorting performed. pass in curves in the order you want them sorted
 468 |     - directions of open curves not adjusted. Use CurveDirectionsMatch and
 469 |       ReverseCurve to adjust the directions of open curves
 470 |     - seams of closed curves are not adjusted. Use CurveSeam to adjust the seam
 471 |       of closed curves
 472 |     Parameters:
 473 |       object_ids ({guid, guid, ...]): ordered list of the curves to loft through
 474 |       start (point, optional): starting point of the loft
 475 |       end (point, optional): ending point of the loft
 476 |       loft_type (number, optional): type of loft. Possible options are:
 477 |         0 = Normal. Uses chord-length parameterization in the loft direction
 478 |         1 = Loose. The surface is allowed to move away from the original curves
 479 |             to make a smoother surface. The surface control points are created
 480 |             at the same locations as the control points of the loft input curves.
 481 |         2 = Straight. The sections between the curves are straight. This is
 482 |             also known as a ruled surface.
 483 |         3 = Tight. The surface sticks closely to the original curves. Uses square
 484 |             root of chord-length parameterization in the loft direction
 485 |         4 = Developable. Creates a separate developable surface or polysurface
 486 |             from each pair of curves.
 487 |       simplify_method (number, optional): Possible options are:
 488 |         0 = None. Does not simplify.
 489 |         1 = Rebuild. Rebuilds the shape curves before lofting. modified by `value` below
 490 |         2 = Refit. Refits the shape curves to a specified tolerance. modified by `value` below
 491 |       value (number, optional): Additional value based on the specified `simplify_method`:
 492 |         Simplify  -   Description
 493 |         Rebuild(1) - then value is the number of control point used to rebuild
 494 |         Rebuild(1) - is specified and this argument is omitted, then curves will be
 495 |                      rebuilt using 10 control points.
 496 |         Refit(2) - then value is the tolerance used to rebuild.
 497 |         Refit(2) - is specified and this argument is omitted, then the document's
 498 |                      absolute tolerance us used for refitting.
 499 |       closed (bool, optional): close the loft back to the first curve
 500 |     Returns:
 501 |       list(guid, ...):Array containing the identifiers of the new surface objects if successful
 502 |       None: on error
 503 |     Example:
 504 |       import rhinoscriptsyntax as rs
 505 |       objs = rs.GetObjects("Pick curves to loft", rs.filter.curve)
 506 |       if objs: rs.AddLoftSrf(objs)
 507 |     See Also:
 508 |       CurveDirectionsMatch
 509 |       CurveSeam
 510 |       ReverseCurve
 511 |     """
 512 |     if loft_type<0 or loft_type>5: raise ValueError("loft_type must be 0-4")
 513 |     if simplify_method<0 or simplify_method>2: raise ValueError("simplify_method must be 0-2")
 514 | 
 515 |     # get set of curves from object_ids
 516 |     curves = [rhutil.coercecurve(id,-1,True) for id in object_ids]
 517 |     if len(curves)<2: return scriptcontext.errorhandler()
 518 |     if start is None: start = Rhino.Geometry.Point3d.Unset
 519 |     if end is None: end = Rhino.Geometry.Point3d.Unset
 520 |     start = rhutil.coerce3dpoint(start, True)
 521 |     end = rhutil.coerce3dpoint(end, True)
 522 |     
 523 |     lt = Rhino.Geometry.LoftType.Normal
 524 |     if loft_type==1: lt = Rhino.Geometry.LoftType.Loose
 525 |     elif loft_type==2: lt = Rhino.Geometry.LoftType.Straight
 526 |     elif loft_type==3: lt = Rhino.Geometry.LoftType.Tight
 527 |     elif loft_type==4: lt = Rhino.Geometry.LoftType.Developable
 528 | 
 529 |     breps = None
 530 |     if simplify_method==0:
 531 |         breps = Rhino.Geometry.Brep.CreateFromLoft(curves, start, end, lt, closed)
 532 |     elif simplify_method==1:
 533 |         value = abs(value)
 534 |         rebuild_count = int(value)
 535 |         breps = Rhino.Geometry.Brep.CreateFromLoftRebuild(curves, start, end, lt, closed, rebuild_count)
 536 |     elif simplify_method==2:
 537 |         refit = abs(value)
 538 |         if refit==0: refit = scriptcontext.doc.ModelAbsoluteTolerance
 539 |         breps = Rhino.Geometry.Brep.CreateFromLoftRefit(curves, start, end, lt, closed, refit)
 540 |     if not breps: return scriptcontext.errorhandler()
 541 | 
 542 |     idlist = []
 543 |     for brep in breps:
 544 |         id = scriptcontext.doc.Objects.AddBrep(brep)
 545 |         if id!=System.Guid.Empty: idlist.append(id)
 546 |     if idlist: scriptcontext.doc.Views.Redraw()
 547 |     return idlist
 548 | 
 549 | 
 550 | def AddRevSrf(curve_id, axis, start_angle=0.0, end_angle=360.0):
 551 |     """Create a surface by revolving a curve around an axis
 552 |     Parameters:
 553 |       curve_id (guid): identifier of profile curve
 554 |       axis (line): line for the rail revolve axis
 555 |       start_angle, end_angle (number, optional): start and end angles of revolve
 556 |     Returns:
 557 |       guid: identifier of new object if successful
 558 |       None: on error
 559 |     Example:
 560 |       import rhinoscriptsyntax as rs
 561 |       curve = rs.AddLine((5,0,0), (10,0,10))
 562 |       rs.AddRevSrf( curve, ((0,0,0), (0,0,1)) )
 563 |     See Also:
 564 |       
 565 |     """
 566 |     curve = rhutil.coercecurve(curve_id, -1, True)
 567 |     axis = rhutil.coerceline(axis, True)
 568 |     start_angle = math.radians(start_angle)
 569 |     end_angle = math.radians(end_angle)
 570 |     srf = Rhino.Geometry.RevSurface.Create(curve, axis, start_angle, end_angle)
 571 |     if not srf: return scriptcontext.errorhandler()
 572 |     ns = srf.ToNurbsSurface()
 573 |     if not ns: return scriptcontext.errorhandler()
 574 |     rc = scriptcontext.doc.Objects.AddSurface(ns)
 575 |     scriptcontext.doc.Views.Redraw()
 576 |     return rc
 577 | 
 578 | 
 579 | def AddSphere(center_or_plane, radius):
 580 |     """Add a spherical surface to the document
 581 |     Parameters:
 582 |       center_or_plane (point|plane): center point of the sphere. If a plane is input,
 583 |         the origin of the plane will be the center of the sphere
 584 |       radius (number): radius of the sphere in the current model units
 585 |     Returns:
 586 |       guid: identifier of the new object on success
 587 |       None: on error
 588 |     Example:
 589 |       import rhinoscriptsyntax as rs
 590 |       radius = 2
 591 |       center = rs.GetPoint("Center of sphere")
 592 |       if center: rs.AddSphere(center, radius)
 593 |     See Also:
 594 |       AddBox
 595 |       AddCone
 596 |       AddCylinder
 597 |       AddTorus
 598 |     """
 599 |     c_or_p = rhutil.coerce3dpoint(center_or_plane)
 600 |     if c_or_p is None:
 601 |         c_or_p = rhutil.coerceplane(center_or_plane)
 602 |     if c_or_p is None: return None
 603 |     sphere = Rhino.Geometry.Sphere(c_or_p, radius)
 604 |     rc = scriptcontext.doc.Objects.AddSphere(sphere)
 605 |     if rc==System.Guid.Empty: return scriptcontext.errorhandler()
 606 |     scriptcontext.doc.Views.Redraw()
 607 |     return rc
 608 | 
 609 | 
 610 | def AddSrfContourCrvs(object_id, points_or_plane, interval=None):
 611 |     """Adds a spaced series of planar curves resulting from the intersection of
 612 |     defined cutting planes through a surface or polysurface. For more
 613 |     information, see Rhino help for details on the Contour command
 614 |     Parameters:
 615 |       object_id (guid): object identifier to contour
 616 |       points_or_plane ([point,point]|plane): either a list/tuple of two points or a plane
 617 |         if two points, they define the start and end points of a center line
 618 |         if a plane, the plane defines the cutting plane
 619 |       interval (number, optional): distance between contour curves.
 620 |     Returns:
 621 |       guid: ids of new contour curves on success
 622 |       None: on error
 623 |     Example:
 624 |       import rhinoscriptsyntax as rs
 625 |       obj = rs.GetObject("Select object", rs.filter.surface + rs.filter.polysurface)
 626 |       startpoint = rs.GetPoint("Base point of center line")
 627 |       endpoint = rs.GetPoint("Endpoint of center line", startpoint)
 628 |       rs.AddSrfContourCrvs( obj, (startpoint, endpoint) )
 629 |     See Also:
 630 |       CurveContourPoints
 631 |     """
 632 |     brep = rhutil.coercebrep(object_id)
 633 |     plane = rhutil.coerceplane(points_or_plane)
 634 |     curves = None
 635 |     if plane:
 636 |         curves = Rhino.Geometry.Brep.CreateContourCurves(brep, plane)
 637 |     else:
 638 |         start = rhutil.coerce3dpoint(points_or_plane[0], True)
 639 |         end = rhutil.coerce3dpoint(points_or_plane[1], True)
 640 |         if not interval:
 641 |             bbox = brep.GetBoundingBox(True)
 642 |             v = bbox.Max - bbox.Min
 643 |             interval = v.Length / 50.0
 644 |         curves = Rhino.Geometry.Brep.CreateContourCurves(brep, start, end, interval)
 645 |     rc = []
 646 |     for crv in curves:
 647 |         id = scriptcontext.doc.Objects.AddCurve(crv)
 648 |         if id!=System.Guid.Empty: rc.append(id)
 649 |     scriptcontext.doc.Views.Redraw()
 650 |     return rc
 651 | 
 652 | 
 653 | def AddSrfControlPtGrid(count, points, degree=(3,3)):
 654 |     """Creates a surface from a grid of points
 655 |     Parameters:
 656 |       count ([number, number])tuple of two numbers defining number of points in the u,v directions
 657 |       points ([point, ...]): list of 3D points
 658 |       degree ([number, number]): two numbers defining degree of the surface in the u,v directions
 659 |     Returns:
 660 |       guid: The identifier of the new object if successful.
 661 |       None: if not successful, or on error.
 662 |     Example:
 663 |     See Also:
 664 |     """
 665 |     points = rhutil.coerce3dpointlist(points, True)
 666 |     surf = Rhino.Geometry.NurbsSurface.CreateFromPoints(points, count[0], count[1], degree[0], degree[1])
 667 |     if not surf: return scriptcontext.errorhandler()
 668 |     id = scriptcontext.doc.Objects.AddSurface(surf)
 669 |     if id!=System.Guid.Empty:
 670 |         scriptcontext.doc.Views.Redraw()
 671 |         return id
 672 | 
 673 | 
 674 | def AddSrfPt(points):
 675 |     """Creates a new surface from either 3 or 4 corner points.
 676 |     Parameters:
 677 |       points ([point, point, point, point]): list of either 3 or 4 corner points
 678 |     Returns:
 679 |       guid: The identifier of the new object if successful.
 680 |       None: if not successful, or on error.
 681 |     Example:
 682 |       import rhinoscriptsyntax as rs
 683 |       points = rs.GetPoints(True, message1="Pick 3 or 4 corner points")
 684 |       if points: rs.AddSrfPt(points)
 685 |     See Also:
 686 |       AddEdgeSrf
 687 |       AddSrfControlPtGrid
 688 |       AddSrfPtGrid
 689 |     """
 690 |     points = rhutil.coerce3dpointlist(points, True)
 691 |     surface=None
 692 |     if len(points)==3:
 693 |         surface = Rhino.Geometry.NurbsSurface.CreateFromCorners(points[0], points[1], points[2])
 694 |     elif len(points)==4:
 695 |         surface = Rhino.Geometry.NurbsSurface.CreateFromCorners(points[0], points[1], points[2], points[3])
 696 |     if surface is None: return scriptcontext.errorhandler()
 697 |     rc = scriptcontext.doc.Objects.AddSurface(surface)
 698 |     if rc==System.Guid.Empty: return scriptcontext.errorhandler()
 699 |     scriptcontext.doc.Views.Redraw()
 700 |     return rc
 701 | 
 702 | 
 703 | def AddSrfPtGrid(count, points, degree=(3,3), closed=(False,False)):
 704 |     """Creates a surface from a grid of points
 705 |     Parameters:
 706 |       count ([number, number}): tuple of two numbers defining number of points in the u,v directions
 707 |       points ([point, ...]): list of 3D points
 708 |       degree ([number, number], optional): two numbers defining degree of the surface in the u,v directions
 709 |       closed ([bool, bool], optional): two booleans defining if the surface is closed in the u,v directions
 710 |     Returns:
 711 |       guid: The identifier of the new object if successful.
 712 |       None: if not successful, or on error.
 713 |     Example:
 714 |     See Also:
 715 |     """
 716 |     points = rhutil.coerce3dpointlist(points, True)
 717 |     surf = Rhino.Geometry.NurbsSurface.CreateThroughPoints(points, count[0], count[1], degree[0], degree[1], closed[0], closed[1])
 718 |     if not surf: return scriptcontext.errorhandler()
 719 |     id = scriptcontext.doc.Objects.AddSurface(surf)
 720 |     if id!=System.Guid.Empty:
 721 |         scriptcontext.doc.Views.Redraw()
 722 |         return id
 723 | 
 724 | 
 725 | def AddSweep1(rail, shapes, closed=False):
 726 |     """Adds a surface created through profile curves that define the surface
 727 |     shape and one curve that defines a surface edge.
 728 |     Parameters:
 729 |       rail (guid): identifier of the rail curve
 730 |       shapes ([guid, ...]): one or more cross section shape curves
 731 |       closed (bool, optional): If True, then create a closed surface
 732 |     Returns:
 733 |       list(guid, ...): of new surface objects if successful
 734 |       None: if not successful, or on error
 735 |     Example:
 736 |       import rhinoscriptsyntax as rs
 737 |       rail = rs.GetObject("Select rail curve", rs.filter.curve)
 738 |       if rail:
 739 |           shapes = rs.GetObjects("Select cross-section curves", rs.filter.curve)
 740 |           if shapes: rs.AddSweep1( rail, shapes )
 741 |     See Also:
 742 |       AddSweep2
 743 |       CurveDirectionsMatch
 744 |       ReverseCurve
 745 |     """
 746 |     rail = rhutil.coercecurve(rail, -1, True)
 747 |     shapes = [rhutil.coercecurve(shape, -1, True) for shape in shapes]
 748 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 749 |     breps = Rhino.Geometry.Brep.CreateFromSweep(rail, shapes, closed, tolerance)
 750 |     if not breps: return scriptcontext.errorhandler()
 751 |     rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in breps]
 752 |     scriptcontext.doc.Views.Redraw()
 753 |     return rc
 754 | 
 755 | 
 756 | def AddSweep2(rails, shapes, closed=False):
 757 |     """Adds a surface created through profile curves that define the surface
 758 |     shape and two curves that defines a surface edge.
 759 |     Parameters:
 760 |       rails ([guid, guid]): identifiers of the two rail curve
 761 |       shapes ([guid, ...]): one or more cross section shape curves
 762 |       closed (bool, optional): If True, then create a closed surface
 763 |     Returns:
 764 |       list(guid, ...): of new surface objects if successful
 765 |       None: if not successful, or on error
 766 |     Example:
 767 |       import rhinoscriptsyntax as rs
 768 |       rails = rs.GetObjects("Select two rail curve", rs.filter.curve)
 769 |       if rails and len(rails)==2:
 770 |           shapes = rs.GetObjects("Select cross-section curves", rs.filter.curve)
 771 |           if shapes: rs.AddSweep2(rails, shapes)
 772 |     See Also:
 773 |       AddSweep1
 774 |       CurveDirectionsMatch
 775 |       ReverseCurve
 776 |     """
 777 |     rail1 = rhutil.coercecurve(rails[0], -1, True)
 778 |     rail2 = rhutil.coercecurve(rails[1], -1, True)
 779 |     shapes = [rhutil.coercecurve(shape, -1, True) for shape in shapes]
 780 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 781 |     breps = Rhino.Geometry.Brep.CreateFromSweep(rail1, rail2, shapes, closed, tolerance)
 782 |     if not breps: return scriptcontext.errorhandler()
 783 |     rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in breps]
 784 |     scriptcontext.doc.Views.Redraw()
 785 |     return rc
 786 | 
 787 | 
 788 | def AddRailRevSrf(profile, rail, axis, scale_height=False):
 789 |     """Adds a surface created through profile curves that define the surface
 790 |     shape and two curves that defines a surface edge.
 791 |     Parameters:
 792 |       profile (guid): identifier of the profile curve
 793 |       rail (guid): identifier of the rail curve
 794 |       axis ([point, point]): A list of two 3-D points identifying the start point and end point of the rail revolve axis, or a Line
 795 |       scale_height (bool, optional): If True, surface will be locally scaled. Defaults to False
 796 |     Returns:
 797 |       guid: identifier of the new object if successful
 798 |       None: if not successful, or on error
 799 |     Example:
 800 |       import rhinoscriptsyntax as rs
 801 |       profile = rs.GetObject("Select a profile", rs.filter.curve)
 802 |       if profile:
 803 |           rail = rs.GetObject("Select a rail", rs.filter.curve)
 804 |           if rail:
 805 |               rs.AddRailRevSrf(profile, rail, ((0,0,0),(0,0,1)))
 806 |     See Also:
 807 |       AddSweep1
 808 |       CurveDirectionsMatch
 809 |       ReverseCurve
 810 |     """
 811 |     profile_inst = rhutil.coercecurve(profile, -1, True)
 812 |     rail_inst = rhutil.coercecurve(rail, -1, True)
 813 |     axis_start = rhutil.coerce3dpoint(axis[0], True)
 814 |     axis_end = rhutil.coerce3dpoint(axis[1], True)
 815 | 
 816 |     line = Rhino.Geometry.Line(axis_start, axis_end)
 817 |     surface = Rhino.Geometry.NurbsSurface.CreateRailRevolvedSurface(profile_inst, rail_inst, line, scale_height)
 818 | 
 819 |     if not surface: return scriptcontext.errorhandler()
 820 |     rc = scriptcontext.doc.Objects.AddSurface(surface)
 821 |     scriptcontext.doc.Views.Redraw()
 822 |     return rc
 823 | 
 824 | 
 825 | def AddTorus(base, major_radius, minor_radius, direction=None):
 826 |     """Adds a torus shaped revolved surface to the document
 827 |     Parameters:
 828 |       base (point): 3D origin point of the torus or the base plane of the torus
 829 |       major_radius, minor_radius (number): the two radii of the torus
 830 |       directions (point):  A point that defines the direction of the torus when base is a point.
 831 |         If omitted, a torus that is parallel to the world XY plane is created
 832 |     Returns:
 833 |       guid: The identifier of the new object if successful.
 834 |       None: if not successful, or on error.
 835 |     Example:
 836 |       import rhinoscriptsyntax as rs
 837 |       major_radius = 5.0
 838 |       minor_radius = major_radius - 2.0
 839 |       base = rs.GetPoint("Base of torus")
 840 |       if base:
 841 |           direction = rs.GetPoint("Direction of torus", base)
 842 |           if direction:
 843 |               rs.AddTorus( base, major_radius, minor_radius, direction )
 844 |     See Also:
 845 |       AddBox
 846 |       AddCone
 847 |       AddCylinder
 848 |       AddSphere
 849 |     """
 850 |     baseplane = None
 851 |     basepoint = rhutil.coerce3dpoint(base)
 852 |     if basepoint is None:
 853 |         baseplane = rhutil.coerceplane(base, True)
 854 |         if direction!=None: return scriptcontext.errorhandler()
 855 |     if baseplane is None:
 856 |         direction = rhutil.coerce3dpoint(direction, False)
 857 |         if direction: direction = direction-basepoint
 858 |         else: direction = Rhino.Geometry.Vector3d.ZAxis
 859 |         baseplane = Rhino.Geometry.Plane(basepoint, direction)
 860 |     torus = Rhino.Geometry.Torus(baseplane, major_radius, minor_radius)
 861 |     revsurf = torus.ToRevSurface()
 862 |     rc = scriptcontext.doc.Objects.AddSurface(revsurf)
 863 |     scriptcontext.doc.Views.Redraw()
 864 |     return rc
 865 | 
 866 | 
 867 | def BooleanDifference(input0, input1, delete_input=True):
 868 |     """Performs a boolean difference operation on two sets of input surfaces
 869 |     and polysurfaces. For more details, see the BooleanDifference command in
 870 |     the Rhino help file
 871 |     Parameters:
 872 |         input0 ([guid, ...]): list of surfaces to subtract from
 873 |         input1 ([guid, ...]): list of surfaces to be subtracted
 874 |         delete_input (bool, optional): delete all input objects
 875 |     Returns:
 876 |         list(guid, ...): of identifiers of newly created objects on success
 877 |         None: on error
 878 |     Example:
 879 |       import rhinoscriptsyntax as rs
 880 |       filter = rs.filter.surface | rs.filter.polysurface
 881 |       input0 = rs.GetObjects("Select first set of surfaces or polysurfaces", filter)
 882 |       if input0:
 883 |           input1 = rs.GetObjects("Select second set of surfaces or polysurfaces", filter)
 884 |           if input1: rs.BooleanDifference(input0, input1)
 885 |     See Also:
 886 |       BooleanIntersection
 887 |       BooleanUnion
 888 |     """
 889 |     if type(input0) is list or type(input0) is tuple: pass
 890 |     else: input0 = [input0]
 891 |     
 892 |     if type(input1) is list or type(input1) is tuple: pass
 893 |     else: input1 = [input1]
 894 | 
 895 |     breps0 = [rhutil.coercebrep(id, True) for id in input0]
 896 |     breps1 = [rhutil.coercebrep(id, True) for id in input1]
 897 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 898 |     newbreps = Rhino.Geometry.Brep.CreateBooleanDifference(breps0, breps1, tolerance)
 899 |     if newbreps is None: return scriptcontext.errorhandler()
 900 |     
 901 |     rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in newbreps]
 902 |     if delete_input:
 903 |         for id in input0: scriptcontext.doc.Objects.Delete(id, True)
 904 |         for id in input1: scriptcontext.doc.Objects.Delete(id, True)
 905 |     scriptcontext.doc.Views.Redraw()
 906 |     return rc
 907 | 
 908 | 
 909 | def BooleanIntersection(input0, input1, delete_input=True):
 910 |     """Performs a boolean intersection operation on two sets of input surfaces
 911 |     and polysurfaces. For more details, see the BooleanIntersection command in
 912 |     the Rhino help file
 913 |     Parameters:
 914 |         input0 ([guid, ...]): list of surfaces
 915 |         input1 ([guid, ...]): list of surfaces
 916 |         delete_input (bool, optional): delete all input objects
 917 |     Returns:
 918 |         list(guid, ...): of identifiers of newly created objects on success
 919 |         None: on error
 920 |     Example:
 921 |       import rhinoscriptsyntax as rs
 922 |       input0 = rs.GetObjects("Select first set of surfaces or polysurfaces", rs.filter.surface | rs.filter.polysurface)
 923 |       if input0:
 924 |           input1 = rs.GetObjects("Select second set of surfaces or polysurfaces", rs.filter.surface | rs.filter.polysurface)
 925 |           if input1: rs.BooleanIntersection( input0, input1 )
 926 |     See Also:
 927 |       BooleanDifference
 928 |       BooleanUnion
 929 |     """
 930 |     if type(input0) is list or type(input0) is tuple: pass
 931 |     else: input0 = [input0]
 932 |     
 933 |     if type(input1) is list or type(input1) is tuple: pass
 934 |     else: input1 = [input1]
 935 | 
 936 |     breps0 = [rhutil.coercebrep(id, True) for id in input0]
 937 |     breps1 = [rhutil.coercebrep(id, True) for id in input1]
 938 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 939 |     newbreps = Rhino.Geometry.Brep.CreateBooleanIntersection(breps0, breps1, tolerance)
 940 |     if newbreps is None: return scriptcontext.errorhandler()
 941 |     rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in newbreps]
 942 |     if delete_input:
 943 |         for id in input0: scriptcontext.doc.Objects.Delete(id, True)
 944 |         for id in input1: scriptcontext.doc.Objects.Delete(id, True)
 945 |     scriptcontext.doc.Views.Redraw()
 946 |     return rc
 947 | 
 948 | 
 949 | def BooleanUnion(input, delete_input=True):
 950 |     """Performs a boolean union operation on a set of input surfaces and
 951 |     polysurfaces. For more details, see the BooleanUnion command in the
 952 |     Rhino help file
 953 |     Parameters:
 954 |         input ([guid, ...]): list of surfaces to union
 955 |         delete_input (bool, optional):  delete all input objects
 956 |     Returns:
 957 |         list(guid, ...): of identifiers of newly created objects on success
 958 |         None on error
 959 |     Example:
 960 |       import rhinoscriptsyntax as rs
 961 |       input = rs.GetObjects("Select surfaces or polysurfaces to union", rs.filter.surface | rs.filter.polysurface)
 962 |       if input and len(input)>1: rs.BooleanUnion(input)
 963 |     See Also:
 964 |       BooleanDifference
 965 |       BooleanUnion
 966 |     """
 967 |     if len(input)<2: return scriptcontext.errorhandler()
 968 |     breps = [rhutil.coercebrep(id, True) for id in input]
 969 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 970 |     newbreps = Rhino.Geometry.Brep.CreateBooleanUnion(breps, tolerance)
 971 |     if newbreps is None: return scriptcontext.errorhandler()
 972 |     
 973 |     rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in newbreps]
 974 |     if delete_input:
 975 |         for id in input: scriptcontext.doc.Objects.Delete(id, True)
 976 |     scriptcontext.doc.Views.Redraw()
 977 |     return rc
 978 | 
 979 | 
 980 | def BrepClosestPoint(object_id, point):
 981 |     """Returns the point on a surface or polysurface that is closest to a test
 982 |     point. This function works on both untrimmed and trimmed surfaces.
 983 |     Parameters:
 984 |       object_id (guid): The object's identifier.
 985 |       point (point): The test, or sampling point.
 986 |     Returns:
 987 |       tuple(point, [number, number], [number, number], vector): of closest point information if successful. The list will
 988 |       contain the following information:
 989 |       Element     Type             Description
 990 |          0        Point3d          The 3-D point at the parameter value of the 
 991 |                                    closest point.
 992 |          1        (U, V)           Parameter values of closest point. Note, V 
 993 |                                    is 0 if the component index type is brep_edge
 994 |                                    or brep_vertex. 
 995 |          2        (type, index)    The type and index of the brep component that
 996 |                                    contains the closest point. Possible types are
 997 |                                    brep_face, brep_edge or brep_vertex.
 998 |          3        Vector3d         The normal to the brep_face, or the tangent
 999 |                                    to the brep_edge.  
1000 |       None: if not successful, or on error.
1001 |     Example:
1002 |       import rhinoscriptsyntax as rs
1003 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
1004 |       if obj:
1005 |           point = rs.GetPoint("Pick a test point")
1006 |           if point:
1007 |               arrCP = rs.BrepClosestPoint(obj, point)
1008 |               if arrCP:
1009 |                   rs.AddPoint(point)
1010 |                   rs.AddPoint( arrCP[0] )
1011 |     See Also:
1012 |       EvaluateSurface
1013 |       IsSurface
1014 |       SurfaceClosestPoint
1015 |     """
1016 |     brep = rhutil.coercebrep(object_id, True)
1017 |     point = rhutil.coerce3dpoint(point, True)
1018 |     rc = brep.ClosestPoint(point, 0.0)
1019 |     if rc[0]:
1020 |         type = int(rc[2].ComponentIndexType)
1021 |         index = rc[2].Index
1022 |         return rc[1], (rc[3], rc[4]), (type, index), rc[5]
1023 | 
1024 | 
1025 | def CapPlanarHoles(surface_id):
1026 |     """Caps planar holes in a surface or polysurface
1027 |     Parameters:
1028 |       surface_id (guid): The identifier of the surface or polysurface to cap.
1029 |     Returns:
1030 |       bool: True or False indicating success or failure
1031 |     Example:
1032 |       import rhinoscriptsyntax as rs
1033 |       surface = rs.GetObject("Select surface or polysurface to cap", rs.filter.surface | rs.filter.polysurface)
1034 |       if surface: rs.CapPlanarHoles( surface )
1035 |     See Also:
1036 |       ExtrudeCurve
1037 |       ExtrudeCurvePoint
1038 |       ExtrudeCurveStraight
1039 |       ExtrudeSurface
1040 |     """
1041 |     brep = rhutil.coercebrep(surface_id, True)
1042 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1043 |     newbrep = brep.CapPlanarHoles(tolerance)
1044 |     if newbrep:
1045 |         if newbrep.SolidOrientation == Rhino.Geometry.BrepSolidOrientation.Inward:
1046 |             newbrep.Flip()
1047 |         surface_id = rhutil.coerceguid(surface_id)
1048 |         if surface_id and scriptcontext.doc.Objects.Replace(surface_id, newbrep):
1049 |             scriptcontext.doc.Views.Redraw()
1050 |             return True
1051 |     return False
1052 | 
1053 | 
1054 | def DuplicateEdgeCurves(object_id, select=False):
1055 |     """Duplicates the edge curves of a surface or polysurface. For more
1056 |     information, see the Rhino help file for information on the DupEdge
1057 |     command.
1058 |     Parameters:
1059 |       object_id (guid): The identifier of the surface or polysurface object.
1060 |       select (bool, optional):  Select the duplicated edge curves. The default is not
1061 |       to select (False).
1062 |     Returns:
1063 |       list(guid, ..): identifying the newly created curve objects if successful.
1064 |       None: if not successful, or on error.
1065 |     Example:
1066 |       import rhinoscriptsyntax as rs
1067 |       obj = rs.GetObject("Select surface or polysurface", rs.filter.surface | rs.filter.polysurface)
1068 |       if obj:
1069 |           rs.DuplicateEdgeCurves( obj, True )
1070 |           rs.DeleteObject( obj )
1071 |     See Also:
1072 |       IsPolysurface
1073 |       IsSurface
1074 |     """
1075 |     brep = rhutil.coercebrep(object_id, True)
1076 |     out_curves = brep.DuplicateEdgeCurves()
1077 |     curves = []
1078 |     for curve in out_curves:
1079 |         if curve.IsValid:
1080 |             rc = scriptcontext.doc.Objects.AddCurve(curve)
1081 |             curve.Dispose()
1082 |             if rc==System.Guid.Empty: return None
1083 |             curves.append(rc)
1084 |             if select: 
1085 |                 rhobject = rhutil.coercerhinoobject(rc)
1086 |                 rhobject.Select(True)
1087 |     if curves: scriptcontext.doc.Views.Redraw()
1088 |     return curves
1089 | 
1090 | 
1091 | def DuplicateSurfaceBorder(surface_id, type=0):
1092 |     """Create curves that duplicate a surface or polysurface border
1093 |     Parameters:
1094 |       surface_id (guid): identifier of a surface
1095 |       type (number, optional): the border curves to return
1096 |          0=both exterior and interior,
1097 |          1=exterior
1098 |          2=interior
1099 |     Returns:
1100 |       list(guid, ...): list of curve ids on success
1101 |       None: on error
1102 |     Example:
1103 |       import rhinoscriptsyntax as rs
1104 |       surface = rs.GetObject("Select surface or polysurface", rs.filter.surface | rs.filter.polysurface)
1105 |       if surface: rs.DuplicateSurfaceBorder( surface )
1106 |     See Also:
1107 |       DuplicateEdgeCurves
1108 |       DuplicateMeshBorder
1109 |     """
1110 |     brep = rhutil.coercebrep(surface_id, True)
1111 |     inner = type==0 or type==2
1112 |     outer = type==0 or type==1
1113 |     curves = brep.DuplicateNakedEdgeCurves(outer, inner)
1114 |     if curves is None: return scriptcontext.errorhandler()
1115 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance * 2.1
1116 |     curves = Rhino.Geometry.Curve.JoinCurves(curves, tolerance)
1117 |     if curves is None: return scriptcontext.errorhandler()
1118 |     rc = [scriptcontext.doc.Objects.AddCurve(c) for c in curves]
1119 |     scriptcontext.doc.Views.Redraw()
1120 |     return rc
1121 | 
1122 | 
1123 | def EvaluateSurface(surface_id, u, v):
1124 |     """Evaluates a surface at a U,V parameter
1125 |     Parameters:
1126 |       surface_id (guid): the object's identifier.
1127 |       u, v ({number, number]): u, v parameters to evaluate.
1128 |     Returns:
1129 |       point: a 3-D point if successful
1130 |       None: if not successful
1131 |     Example:
1132 |       import rhinoscriptsyntax as rs
1133 |       objectId = rs.GetObject("Select a surface")
1134 |       if rs.IsSurface(objectId):
1135 |           domainU = rs.SurfaceDomain(objectId, 0)
1136 |           domainV = rs.SurfaceDomain(objectId, 1)
1137 |           u = domainU[1]/2.0
1138 |           v = domainV[1]/2.0
1139 |           point = rs.EvaluateSurface(objectId, u, v)
1140 |           rs.AddPoint( point )
1141 |     See Also:
1142 |       IsSurface
1143 |       SurfaceClosestPoint
1144 |     """
1145 |     surface = rhutil.coercesurface(surface_id, True)
1146 |     rc = surface.PointAt(u,v)
1147 |     if rc.IsValid: return rc
1148 |     return scriptcontext.errorhandler()
1149 | 
1150 | 
1151 | def ExtendSurface(surface_id, parameter, length, smooth=True):
1152 |     """Lengthens an untrimmed surface object
1153 |     Parameters:
1154 |       surface_id (guid): identifier of a surface
1155 |       parameter ([number, number}): tuple of two values definfing the U,V parameter to evaluate.
1156 |         The surface edge closest to the U,V parameter will be the edge that is
1157 |         extended
1158 |       length (number): amount to extend to surface
1159 |       smooth (bool, optional): If True, the surface is extended smoothly curving from the
1160 |         edge. If False, the surface is extended in a straight line from the edge
1161 |     Returns:
1162 |       bool: True or False indicating success or failure
1163 |     Example:
1164 |       import rhinoscriptsyntax as rs
1165 |       pick = rs.GetObjectEx("Select surface to extend", rs.filter.surface)
1166 |       if pick:
1167 |           parameter = rs.SurfaceClosestPoint(pick[0], pick[3])
1168 |           rs.ExtendSurface(pick[0], parameter, 5.0)
1169 |     See Also:
1170 |       IsSurface
1171 |     """
1172 |     surface = rhutil.coercesurface(surface_id, True)
1173 |     edge = surface.ClosestSide(parameter[0], parameter[1])
1174 |     newsrf = surface.Extend(edge, length, smooth)
1175 |     if newsrf:
1176 |         surface_id = rhutil.coerceguid(surface_id)
1177 |         if surface_id: scriptcontext.doc.Objects.Replace(surface_id, newsrf)
1178 |         scriptcontext.doc.Views.Redraw()
1179 |     return newsrf is not None
1180 | 
1181 | 
1182 | def ExplodePolysurfaces(object_ids, delete_input=False):
1183 |     """Explodes, or unjoins, one or more polysurface objects. Polysurfaces
1184 |     will be exploded into separate surfaces
1185 |     Parameters:
1186 |       object_ids ([guid, ...]): identifiers of polysurfaces to explode
1187 |       delete_input 9bool, optional): delete input objects after exploding
1188 |     Returns:
1189 |       list(guid, ...): of identifiers of exploded pieces on success
1190 |     Example:
1191 |       import rhinoscriptsyntax as rs
1192 |       obj = rs.GetObject("Select polysurface to explode", rs.filter.polysurface)
1193 |       if rs.IsPolysurface(obj):
1194 |           rs.ExplodePolysurfaces( obj )
1195 |     See Also:
1196 |       IsPolysurface
1197 |       IsSurface
1198 |     """
1199 |     id = rhutil.coerceguid(object_ids, False)
1200 |     if id: object_ids = [id]
1201 |     ids = []
1202 |     for id in object_ids:
1203 |         brep = rhutil.coercebrep(id, True)
1204 |         if brep.Faces.Count>1:
1205 |             for i in range(brep.Faces.Count):
1206 |                 copyface = brep.Faces[i].DuplicateFace(False)
1207 |                 face_id = scriptcontext.doc.Objects.AddBrep(copyface)
1208 |                 if face_id!=System.Guid.Empty: ids.append(face_id)
1209 |             if delete_input: scriptcontext.doc.Objects.Delete(id, True)
1210 |     scriptcontext.doc.Views.Redraw()
1211 |     return ids
1212 | 
1213 | 
1214 | def ExtractIsoCurve(surface_id, parameter, direction):
1215 |     """Extracts isoparametric curves from a surface
1216 |     Parameters:
1217 |       surface_id (guid): identifier of a surface
1218 |       parameter ([number, number]): u,v parameter of the surface to evaluate
1219 |       direction (number): Direction to evaluate
1220 |         0 = u
1221 |         1 = v
1222 |         2 = both
1223 |     Returns:
1224 |       list(guid, ...): of curve ids on success
1225 |       None: on error
1226 |     Example:
1227 |       import rhinoscriptsyntax as rs
1228 |       obj = rs.GetObject("Select surface for isocurve extraction", rs.filter.surface)
1229 |       point = rs.GetPointOnSurface(obj, "Select location for extraction")
1230 |       parameter = rs.SurfaceClosestPoint(obj, point)
1231 |       rs.ExtractIsoCurve( obj, parameter, 2 )
1232 |     See Also:
1233 |       IsSurface
1234 |     """
1235 |     surface = rhutil.coercesurface(surface_id, True)
1236 |     ids = []
1237 |     if direction==0 or direction==2:
1238 |         curves = None
1239 |         if type(surface) is Rhino.Geometry.BrepFace:
1240 |             curves = surface.TrimAwareIsoCurve(0, parameter[1])
1241 |         else:
1242 |             curves = [surface.IsoCurve(0,parameter[1])]
1243 |         if curves:
1244 |             for curve in curves:
1245 |                 id = scriptcontext.doc.Objects.AddCurve(curve)
1246 |                 if id!=System.Guid.Empty: ids.append(id)
1247 |     if direction==1 or direction==2:
1248 |         curves = None
1249 |         if type(surface) is Rhino.Geometry.BrepFace:
1250 |             curves = surface.TrimAwareIsoCurve(1, parameter[0])
1251 |         else:
1252 |             curves = [surface.IsoCurve(1,parameter[0])]
1253 |         if curves:
1254 |             for curve in curves:
1255 |                 id = scriptcontext.doc.Objects.AddCurve(curve)
1256 |                 if id!=System.Guid.Empty: ids.append(id)
1257 |     scriptcontext.doc.Views.Redraw()
1258 |     return ids
1259 | 
1260 | 
1261 | def ExtractSurface(object_id, face_indices, copy=False):
1262 |     """Separates or copies a surface or a copy of a surface from a polysurface
1263 |     Parameters:
1264 |       object_id (guid): polysurface identifier
1265 |       face_indices (number, ...): one or more numbers representing faces
1266 |       copy (bool, optional): If True the faces are copied. If False, the faces are extracted
1267 |     Returns:
1268 |       list(guid, ...): identifiers of extracted surface objects on success
1269 |     Example:
1270 |       import rhinoscriptsyntax as rs
1271 |       obj = rs.GetObject("Select polysurface", rs.filter.polysurface, True)
1272 |       if obj: rs.ExtractSurface(obj, 0)
1273 |     See Also:
1274 |       BrepClosestPoint
1275 |       IsSurface
1276 |       IsPolysurface
1277 |     """
1278 |     brep = rhutil.coercebrep(object_id, True)
1279 |     if hasattr(face_indices, "__getitem__"): pass
1280 |     else: face_indices = [face_indices]
1281 |     rc = []
1282 |     face_indices = sorted(face_indices, reverse=True)
1283 |     for index in face_indices:
1284 |         face = brep.Faces[index]
1285 |         newbrep = face.DuplicateFace(True)
1286 |         id = scriptcontext.doc.Objects.AddBrep(newbrep)
1287 |         rc.append(id)
1288 |     if not copy:
1289 |         for index in face_indices: brep.Faces.RemoveAt(index)
1290 |         id = rhutil.coerceguid(object_id)
1291 |         scriptcontext.doc.Objects.Replace(id, brep)
1292 |     scriptcontext.doc.Views.Redraw()
1293 |     return rc
1294 | 
1295 | 
1296 | def ExtrudeCurve(curve_id, path_id):
1297 |     """Creates a surface by extruding a curve along a path
1298 |     Parameters:
1299 |       curve_id (guid): identifier of the curve to extrude
1300 |       path_id (guid): identifier of the path curve
1301 |     Returns:
1302 |       guid: identifier of new surface on success
1303 |       None: on error
1304 |     Example:
1305 |       import rhinoscriptsyntax as rs
1306 |       curve = rs.AddCircle(rs.WorldXYPlane(), 5)
1307 |       path = rs.AddLine([5,0,0], [10,0,10])
1308 |       rs.ExtrudeCurve( curve, path )
1309 |     See Also:
1310 |       ExtrudeCurvePoint
1311 |       ExtrudeCurveStraight
1312 |       ExtrudeSurface
1313 |     """
1314 |     curve1 = rhutil.coercecurve(curve_id, -1, True)
1315 |     curve2 = rhutil.coercecurve(path_id, -1, True)
1316 |     srf = Rhino.Geometry.SumSurface.Create(curve1, curve2)
1317 |     rc = scriptcontext.doc.Objects.AddSurface(srf)
1318 |     if rc==System.Guid.Empty: return scriptcontext.errorhandler()
1319 |     scriptcontext.doc.Views.Redraw()
1320 |     return rc
1321 | 
1322 | 
1323 | def ExtrudeCurvePoint(curve_id, point):
1324 |     """Creates a surface by extruding a curve to a point
1325 |     Parameters:
1326 |       curve_id (guid): identifier of the curve to extrude
1327 |       point (point): 3D point
1328 |     Returns:
1329 |       guid: identifier of new surface on success
1330 |       None: on error
1331 |     Example:
1332 |       import rhinoscriptsyntax as rs
1333 |       curve = rs.AddCircle(rs.WorldXYPlane(), 5)
1334 |       point = (0,0,10)
1335 |       rs.ExtrudeCurvePoint( curve, point )
1336 |     See Also:
1337 |       ExtrudeCurve
1338 |       ExtrudeCurveStraight
1339 |       ExtrudeSurface
1340 |     """
1341 |     curve = rhutil.coercecurve(curve_id, -1, True)
1342 |     point = rhutil.coerce3dpoint(point, True)
1343 |     srf = Rhino.Geometry.Surface.CreateExtrusionToPoint(curve, point)
1344 |     rc = scriptcontext.doc.Objects.AddSurface(srf)
1345 |     if rc==System.Guid.Empty: return scriptcontext.errorhandler()
1346 |     scriptcontext.doc.Views.Redraw()
1347 |     return rc
1348 | 
1349 | 
1350 | def ExtrudeCurveStraight(curve_id, start_point, end_point):
1351 |     """Create surface by extruding a curve along two points that define a line
1352 |     Parameters:
1353 |       curve_id (guid): identifier of the curve to extrude
1354 |       start_point, end_point (point): 3D points that specify distance and direction
1355 |     Returns:
1356 |       guid: identifier of new surface on success
1357 |       None: on error
1358 |     Example:
1359 |       import rhinoscriptsyntax as rs
1360 |       curve = rs.AddCircle(rs.WorldXYPlane(), 5)
1361 |       rs.ExtrudeCurveStraight( curve, (0,0,0), (0, 10, 10) )
1362 |     See Also:
1363 |       ExtrudeCurve
1364 |       ExtrudeCurvePoint
1365 |       ExtrudeSurface
1366 |     """
1367 |     curve = rhutil.coercecurve(curve_id, -1, True)
1368 |     start_point = rhutil.coerce3dpoint(start_point, True)
1369 |     end_point = rhutil.coerce3dpoint(end_point, True)
1370 |     vec = end_point - start_point
1371 |     srf = Rhino.Geometry.Surface.CreateExtrusion(curve, vec)
1372 |     rc = scriptcontext.doc.Objects.AddSurface(srf)
1373 |     if rc==System.Guid.Empty: return scriptcontext.errorhandler()
1374 |     scriptcontext.doc.Views.Redraw()
1375 |     return rc
1376 | 
1377 | 
1378 | def ExtrudeSurface(surface, curve, cap=True):
1379 |     """Create surface by extruding along a path curve
1380 |     Parameters:
1381 |       surface (guid): identifier of the surface to extrude
1382 |       curve (guid): identifier of the path curve
1383 |       cap (bool, optional): extrusion is capped at both ends
1384 |     Returns:
1385 |       guid: identifier of new surface on success
1386 |     Example:
1387 |       import rhinoscriptsyntax as rs
1388 |       surface = rs.AddSrfPt([(0,0,0), (5,0,0), (5,5,0), (0,5,0)])
1389 |       curve = rs.AddLine((5,0,0), (10,0,10))
1390 |       rs.ExtrudeSurface(surface, curve)
1391 |     See Also:
1392 |       ExtrudeCurve
1393 |       ExtrudeCurvePoint
1394 |       ExtrudeCurveStraight
1395 |     """
1396 |     brep = rhutil.coercebrep(surface, True)
1397 |     curve = rhutil.coercecurve(curve, -1, True)
1398 |     newbrep = brep.Faces[0].CreateExtrusion(curve, cap)
1399 |     if newbrep:
1400 |         rc = scriptcontext.doc.Objects.AddBrep(newbrep)
1401 |         scriptcontext.doc.Views.Redraw()
1402 |         return rc
1403 | 
1404 | 
1405 | def FilletSurfaces(surface0, surface1, radius, uvparam0=None, uvparam1=None):
1406 |     """Create constant radius rolling ball fillets between two surfaces. Note,
1407 |     this function does not trim the original surfaces of the fillets
1408 |     Parameters:
1409 |       surface0, surface1 (guid): identifiers of first and second surface
1410 |       radius (number): a positive fillet radius
1411 |       uvparam0 ([number, number], optional): a u,v surface parameter of surface0 near where the fillet
1412 |         is expected to hit the surface
1413 |       uvparam1([number, number], optional): same as uvparam0, but for surface1
1414 |     Returns:
1415 |       guid: ids of surfaces created on success
1416 |       None: on error
1417 |     Example:
1418 |       import rhinoscriptsyntax as rs
1419 |       surface0 = rs.GetObject("First surface", rs.filter.surface)
1420 |       surface1 = rs.GetObject("Second surface", rs.filter.surface)
1421 |       rs.FilletSurfaces(surface0, surface1, 2.0)
1422 |     See Also:
1423 |       IsSurface
1424 |     """
1425 |     surface0 = rhutil.coercesurface(surface0, True)
1426 |     surface1 = rhutil.coercesurface(surface1, True)
1427 |     if uvparam0 is not None and uvparam1 is not None:   #SR9 error: "Could not convert None to a Point2d"
1428 |         uvparam0 = rhutil.coerce2dpoint(uvparam0, True)
1429 |         uvparam1 = rhutil.coerce2dpoint(uvparam1, True)
1430 |     surfaces = None
1431 |     tol = scriptcontext.doc.ModelAbsoluteTolerance
1432 |     if uvparam0 and uvparam1:
1433 |         surfaces = Rhino.Geometry.Surface.CreateRollingBallFillet(surface0, uvparam0, surface1, uvparam1, radius, tol)
1434 |     else:
1435 |         surfaces = Rhino.Geometry.Surface.CreateRollingBallFillet(surface0, surface1, radius, tol)
1436 |     if not surfaces: return scriptcontext.errorhandler()
1437 |     rc = []
1438 |     for surf in surfaces:
1439 |         rc.append( scriptcontext.doc.Objects.AddSurface(surf) )
1440 |     scriptcontext.doc.Views.Redraw()
1441 |     return rc
1442 | 
1443 | 
1444 | def FlipSurface(surface_id, flip=None):
1445 |     """Returns or changes the normal direction of a surface. This feature can
1446 |     also be found in Rhino's Dir command
1447 |     Parameters:
1448 |       surface_id (guid): identifier of a surface object
1449 |       flip (bool, optional) new normal orientation, either flipped(True) or not flipped (False).
1450 |     Returns:
1451 |       vector: if flipped is not specified, the current normal orientation
1452 |       vector: if flipped is specified, the previous normal orientation
1453 |       None: on error
1454 |     Example:
1455 |       import rhinoscriptsyntax as rs
1456 |       surf = rs.GetObject("Select object", rs.filter.surface)
1457 |       if surf:
1458 |           flip = rs.FlipSurface(surf)
1459 |           if flip: rs.FlipSurface(surf, False)
1460 |     See Also:
1461 |       IsSurface
1462 |     """
1463 |     brep = rhutil.coercebrep(surface_id, True)
1464 |     if brep.Faces.Count>1: return scriptcontext.errorhandler()
1465 |     face = brep.Faces[0]
1466 |     old_reverse = face.OrientationIsReversed
1467 |     if flip!=None and brep.IsSolid==False and old_reverse!=flip:
1468 |         brep.Flip()
1469 |         surface_id = rhutil.coerceguid(surface_id)
1470 |         if surface_id: scriptcontext.doc.Objects.Replace(surface_id, brep)
1471 |         scriptcontext.doc.Views.Redraw()
1472 |     return old_reverse
1473 | 
1474 | 
1475 | def IntersectBreps(brep1, brep2, tolerance=None):
1476 |     """Intersects a brep object with another brep object. Note, unlike the
1477 |     SurfaceSurfaceIntersection function this function works on trimmed surfaces.
1478 |     Parameters:
1479 |       brep1 (guid): identifier of first brep object
1480 |       brep2 (guid): identifier of second brep object
1481 |       tolerance (number): Distance tolerance at segment midpoints. If omitted,
1482 |                   the current absolute tolerance is used.
1483 |     Returns:
1484 |       list(guid, ...): identifying the newly created intersection curve and point objects if successful.
1485 |       None: if not successful, or on error.
1486 |     Example:
1487 |       import rhinoscriptsyntax as rs
1488 |       brep1 = rs.GetObject("Select the first brep", rs.filter.surface | rs.filter.polysurface)
1489 |       if brep1:
1490 |           brep2 = rs.GetObject("Select the second", rs.filter.surface | rs.filter.polysurface)
1491 |           if brep2: rs.IntersectBreps( brep1, brep2)
1492 |     See Also:
1493 |       
1494 |     """
1495 |     brep1 = rhutil.coercebrep(brep1, True)
1496 |     brep2 = rhutil.coercebrep(brep2, True)
1497 |     if tolerance is None or tolerance < 0.0:
1498 |         tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1499 |     rc = Rhino.Geometry.Intersect.Intersection.BrepBrep(brep1, brep2, tolerance)
1500 |     if not rc[0]: return None
1501 |     out_curves = rc[1]
1502 |     out_points = rc[2]
1503 |     merged_curves = Rhino.Geometry.Curve.JoinCurves(out_curves, 2.1 * tolerance)
1504 |     
1505 |     ids = []
1506 |     if merged_curves:
1507 |         for curve in merged_curves:
1508 |             if curve.IsValid:
1509 |                 rc = scriptcontext.doc.Objects.AddCurve(curve)
1510 |                 curve.Dispose()
1511 |                 if rc==System.Guid.Empty: return scriptcontext.errorhandler()
1512 |                 ids.append(rc)
1513 |     else:
1514 |         for curve in out_curves:
1515 |             if curve.IsValid:
1516 |                 rc = scriptcontext.doc.Objects.AddCurve(curve)
1517 |                 curve.Dispose()
1518 |                 if rc==System.Guid.Empty: return scriptcontext.errorhandler()
1519 |                 ids.append(rc)
1520 |     for point in out_points:
1521 |         rc = scriptcontext.doc.Objects.AddPoint(point)
1522 |         if rc==System.Guid.Empty: return scriptcontext.errorhandler()
1523 |         ids.append(rc)
1524 |     if ids:
1525 |         scriptcontext.doc.Views.Redraw()
1526 |         return ids
1527 | 
1528 | 
1529 | def IntersectSpheres(sphere_plane0, sphere_radius0, sphere_plane1, sphere_radius1):
1530 |     """Calculates intersections of two spheres
1531 |     Parameters:
1532 |       sphere_plane0 (plane): an equatorial plane of the first sphere. The origin of the
1533 |         plane will be the center point of the sphere
1534 |       sphere_radius0 (number): radius of the first sphere
1535 |       sphere_plane1 (plane): plane for second sphere
1536 |       sphere_radius1 (number): radius for second sphere
1537 |     Returns:
1538 |       list(number, point, number): of intersection results
1539 |         [0] = type of intersection (0=point, 1=circle, 2=spheres are identical)
1540 |         [1] = Point of intersection or plane of circle intersection
1541 |         [2] = radius of circle if circle intersection
1542 |       None: on error
1543 |     Example:
1544 |       import rhinoscriptsyntax as rs
1545 |       plane0 = rs.WorldXYPlane()
1546 |       plane1 = rs.MovePlane(plane0, (10,0,0))
1547 |       radius = 10
1548 |       results = rs.IntersectSpheres(plane0, radius, plane1, radius)
1549 |       if results:
1550 |           if results[0] == 0: rs.AddPoint(results[1])
1551 |           else: rs.AddCircle( results[1], results[2])
1552 |     See Also:
1553 |       IntersectBreps
1554 |       IntersectPlanes
1555 |     """
1556 |     plane0 = rhutil.coerceplane(sphere_plane0, True)
1557 |     plane1 = rhutil.coerceplane(sphere_plane1, True)
1558 |     sphere0 = Rhino.Geometry.Sphere(plane0, sphere_radius0)
1559 |     sphere1 = Rhino.Geometry.Sphere(plane1, sphere_radius1)
1560 |     rc, circle = Rhino.Geometry.Intersect.Intersection.SphereSphere(sphere0, sphere1)
1561 |     if rc==Rhino.Geometry.Intersect.SphereSphereIntersection.Point:
1562 |         return [0, circle.Center]
1563 |     if rc==Rhino.Geometry.Intersect.SphereSphereIntersection.Circle:
1564 |         return [1, circle.Plane, circle.Radius]
1565 |     if rc==Rhino.Geometry.Intersect.SphereSphereIntersection.Overlap:
1566 |         return [2]
1567 |     return scriptcontext.errorhandler()
1568 | 
1569 | 
1570 | def IsBrep(object_id):
1571 |     """Verifies an object is a Brep, or a boundary representation model, object.
1572 |     Parameters:
1573 |       object_id (guid): The object's identifier.
1574 |     Returns:
1575 |       bool: True if successful, otherwise False.
1576 |       None: on error.
1577 |     Example:
1578 |       import rhinoscriptsyntax as rs
1579 |       obj = rs.GetObject("Select a Brep")
1580 |       if rs.IsBrep(obj):
1581 |           print("The object is a Brep.")
1582 |       else:
1583 |           print("The object is not a Brep.")
1584 |     See Also:
1585 |       IsPolysurface
1586 |       IsPolysurfaceClosed
1587 |       IsSurface
1588 |     """
1589 |     return rhutil.coercebrep(object_id)!=None
1590 | 
1591 | 
1592 | def IsCone(object_id):
1593 |     """Determines if a surface is a portion of a cone
1594 |     Parameters:
1595 |       object_id (guid): the surface object's identifier
1596 |     Returns:
1597 |       bool: True if successful, otherwise False
1598 |     Example:
1599 |       import rhinoscriptsyntax as rs
1600 |       surface = rs.GetObject("Select a surface", rs.filter.surface)
1601 |       if surface:
1602 |           if rs.IsCone(surface):
1603 |               print("The surface is a portion of a cone.")
1604 |           else:
1605 |               print("The surface is not a portion of a cone.")
1606 |     See Also:
1607 |       IsCylinder
1608 |       IsSphere
1609 |       IsSurface
1610 |       IsTorus
1611 |     """
1612 |     surface = rhutil.coercesurface(object_id, True)
1613 |     return surface.IsCone()
1614 | 
1615 | 
1616 | def IsCylinder(object_id):
1617 |     """Determines if a surface is a portion of a cone
1618 |     Parameters:
1619 |       object_id (guid): the cylinder object's identifier
1620 |     Returns:
1621 |       bool: True if successful, otherwise False
1622 |     Example:
1623 |       import rhinoscriptsyntax as rs
1624 |       surface = rs.GetObject("Select a surface", rs.filter.surface)
1625 |       if surface:
1626 |           if rs.IsCylinder(surface):
1627 |               print("The surface is a portion of a cylinder.")
1628 |           else:
1629 |               print("The surface is not a portion of a cylinder.")
1630 |     See Also:
1631 |       IsCone
1632 |       IsSphere
1633 |       IsSurface
1634 |       IsTorus
1635 |     """
1636 |     surface = rhutil.coercesurface(object_id, True)
1637 |     return surface.IsCylinder()
1638 | 
1639 | 
1640 | def IsPlaneSurface(object_id):
1641 |     """Verifies an object is a plane surface. Plane surfaces can be created by
1642 |     the Plane command. Note, a plane surface is not a planar NURBS surface
1643 |     Parameters:
1644 |       object_id (guid): the object's identifier
1645 |     Returns:
1646 |       bool: True if successful, otherwise False
1647 |     Example:
1648 |       import rhinoscriptsyntax as rs
1649 |       surface = rs.GetObject("Select surface to trim", rs.filter.surface)
1650 |       if surface and rs.IsPlaneSurface(surface):
1651 |           print("got a plane surface")
1652 |       else:
1653 |           print("not a plane surface")
1654 |     See Also:
1655 |       IsBrep
1656 |       IsPolysurface
1657 |       IsSurface
1658 |     """
1659 |     face = rhutil.coercesurface(object_id, True)
1660 |     if type(face) is Rhino.Geometry.BrepFace and face.IsSurface:
1661 |         return type(face.UnderlyingSurface()) is Rhino.Geometry.PlaneSurface
1662 |     return False
1663 |     
1664 | 
1665 | def IsPointInSurface(object_id, point, strictly_in=False, tolerance=None):
1666 |     """Verifies that a point is inside a closed surface or polysurface
1667 |     Parameters:
1668 |       object_id (guid): the object's identifier
1669 |       point (point): The test, or sampling point
1670 |       strictly_in (bool, optional): If true, the test point must be inside by at least tolerance
1671 |       tolerance (number, optional): distance tolerance used for intersection and determining
1672 |         strict inclusion. If omitted, Rhino's internal tolerance is used
1673 |     Returns:
1674 |       bool: True if successful, otherwise False
1675 |     Example:
1676 |       import rhinoscriptsyntax as rs
1677 |       obj = rs.GetObject("Select a polysurface", rs.filter.polysurface)
1678 |       if rs.IsPolysurfaceClosed(obj):
1679 |           point = rs.GetPoint("Pick a test point")
1680 |           if point:
1681 |               if rs.IsPointInSurface(obj, point):
1682 |                   print("The point is inside the polysurface.")
1683 |               else:
1684 |                   print("The point is not inside the polysurface.")
1685 |     See Also:
1686 |       IsPointOnSurface
1687 |     """
1688 |     object_id = rhutil.coerceguid(object_id, True)
1689 |     point = rhutil.coerce3dpoint(point, True)
1690 |     if object_id==None or point==None: return scriptcontext.errorhandler()
1691 |     obj = scriptcontext.doc.Objects.Find(object_id)
1692 |     if tolerance is None: tolerance = Rhino.RhinoMath.SqrtEpsilon
1693 |     brep = None
1694 |     if type(obj)==Rhino.DocObjects.ExtrusionObject:
1695 |         brep = obj.ExtrusionGeometry.ToBrep(False)
1696 |     elif type(obj)==Rhino.DocObjects.BrepObject:
1697 |         brep = obj.BrepGeometry
1698 |     elif hasattr(obj, "Geometry"):
1699 |         brep = obj.Geometry
1700 |     return brep.IsPointInside(point, tolerance, strictly_in)
1701 | 
1702 | 
1703 | def IsPointOnSurface(object_id, point):
1704 |     """Verifies that a point lies on a surface
1705 |     Parameters:
1706 |       object_id (guid): the object's identifier
1707 |       point (point): The test, or sampling point
1708 |     Returns:
1709 |       bool: True if successful, otherwise False
1710 |     Example:
1711 |       import rhinoscriptsyntax as rs
1712 |       surf = rs.GetObject("Select a surface")
1713 |       if rs.IsSurface(surf):
1714 |           point = rs.GetPoint("Pick a test point")
1715 |           if point:
1716 |               if rs.IsPointOnSurface(surf, point):
1717 |                   print("The point is on the surface.")
1718 |               else:
1719 |                   print("The point is not on the surface.")
1720 |     See Also:
1721 |       IsPointInSurface
1722 |     """
1723 |     surf = rhutil.coercesurface(object_id, True)
1724 |     point = rhutil.coerce3dpoint(point, True)
1725 |     rc, u, v = surf.ClosestPoint(point)
1726 |     if rc:
1727 |         srf_pt = surf.PointAt(u,v)
1728 |         if srf_pt.DistanceTo(point)>scriptcontext.doc.ModelAbsoluteTolerance:
1729 |             rc = False
1730 |         else:
1731 |             rc = surf.IsPointOnFace(u,v) != Rhino.Geometry.PointFaceRelation.Exterior
1732 |     return rc
1733 | 
1734 | 
1735 | def IsPolysurface(object_id):
1736 |     """Verifies an object is a polysurface. Polysurfaces consist of two or more
1737 |     surfaces joined together. If the polysurface fully encloses a volume, it is
1738 |     considered a solid.
1739 |     Parameters:
1740 |       object_id (guid): the object's identifier
1741 |     Returns:
1742 |       bool: True is successful, otherwise False
1743 |     Example:
1744 |       import rhinoscriptsyntax as rs
1745 |       obj = rs.GetObject("Select a polysurface")
1746 |       if rs.IsPolysurface(obj):
1747 |           print("The object is a polysurface.")
1748 |       else:
1749 |           print("The object is not a polysurface.")
1750 |     See Also:
1751 |       IsBrep
1752 |       IsPolysurfaceClosed
1753 |     """
1754 |     brep = rhutil.coercebrep(object_id)
1755 |     if brep is None: return False
1756 |     return brep.Faces.Count>1
1757 | 
1758 | 
1759 | def IsPolysurfaceClosed(object_id):
1760 |     """Verifies a polysurface object is closed. If the polysurface fully encloses
1761 |     a volume, it is considered a solid.
1762 |     Parameters:
1763 |       object_id (guid): the object's identifier
1764 |     Returns:
1765 |       bool: True is successful, otherwise False
1766 |     Example:
1767 |       import rhinoscriptsyntax as rs
1768 |       obj = rs.GetObject("Select a polysurface", rs.filter.polysurface)
1769 |       if rs.IsPolysurfaceClosed(obj):
1770 |           print("The polysurface is closed.")
1771 |       else:
1772 |           print("The polysurface is not closed.")
1773 |     See Also:
1774 |       IsBrep
1775 |       IsPolysurface
1776 |     """
1777 |     brep = rhutil.coercebrep(object_id, True)
1778 |     return brep.IsSolid
1779 | 
1780 | 
1781 | def IsSphere(object_id):
1782 |     """Determines if a surface is a portion of a sphere
1783 |     Parameters:
1784 |       object_id (guid): the object's identifier
1785 |     Returns:
1786 |       bool: True if successful, otherwise False
1787 |     Example:
1788 |       import rhinoscriptsyntax as rs
1789 |       surface = rs.GetObject("Select a surface", rs.filter.surface)
1790 |       if surface:
1791 |           if rs.IsSphere(surface):
1792 |               print("The surface is a portion of a sphere.")
1793 |           else:
1794 |               print("The surface is not a portion of a sphere.")
1795 |     See Also:
1796 |       IsCone
1797 |       IsCylinder
1798 |       IsSurface
1799 |       IsTorus
1800 |     """
1801 |     surface = rhutil.coercesurface(object_id, True)
1802 |     return surface.IsSphere()
1803 | 
1804 | 
1805 | def IsSurface(object_id):
1806 |     """Verifies an object is a surface. Brep objects with only one face are
1807 |     also considered surfaces.
1808 |     Parameters:
1809 |       object_id (guid): the object's identifier.
1810 |     Returns:
1811 |       bool: True if successful, otherwise False.
1812 |     Example:
1813 |       import rhinoscriptsyntax as rs
1814 |       objectId = rs.GetObject("Select a surface")
1815 |       if rs.IsSurface(objectId):
1816 |           print("The object is a surface.")
1817 |       else:
1818 |           print("The object is not a surface.")
1819 |     See Also:
1820 |       IsPointOnSurface
1821 |       IsSurfaceClosed
1822 |       IsSurfacePlanar
1823 |       IsSurfaceSingular
1824 |       IsSurfaceTrimmed
1825 |     """
1826 |     brep = rhutil.coercebrep(object_id)
1827 |     if brep and brep.Faces.Count==1: return True
1828 |     surface = rhutil.coercesurface(object_id)
1829 |     return (surface!=None)
1830 | 
1831 | 
1832 | def IsSurfaceClosed( surface_id, direction ):
1833 |     """Verifies a surface object is closed in the specified direction.  If the
1834 |     surface fully encloses a volume, it is considered a solid
1835 |     Parameters:
1836 |       surface_id (guid): identifier of a surface
1837 |       direction (number): 0=U direction check, 1=V direction check
1838 |     Returns:
1839 |       bool: True or False
1840 |     Example:
1841 |       import rhinoscriptsyntax as rs
1842 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
1843 |       if rs.IsSurfaceClosed(obj, 0):
1844 |           print("The surface is closed in the U direction.")
1845 |       else:
1846 |           print("The surface is not closed in the U direction.")
1847 |     See Also:
1848 |       IsSurface
1849 |       IsSurfacePlanar
1850 |       IsSurfaceSingular
1851 |       IsSurfaceTrimmed
1852 |     """
1853 |     surface = rhutil.coercesurface(surface_id, True)
1854 |     return surface.IsClosed(direction)
1855 | 
1856 | 
1857 | def IsSurfacePeriodic(surface_id, direction):
1858 |     """Verifies a surface object is periodic in the specified direction.
1859 |     Parameters:
1860 |       surface_id (guid): identifier of a surface
1861 |       direction (number): 0=U direction check, 1=V direction check
1862 |     Returns:
1863 |       bool: True or False
1864 |     Example:
1865 |       import rhinoscriptsyntax as rs
1866 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
1867 |       if rs.IsSurfacePeriodic(obj, 0):
1868 |           print("The surface is periodic in the U direction.")
1869 |       else:
1870 |           print("The surface is not periodic in the U direction.")
1871 |     See Also:
1872 |       IsSurface
1873 |       IsSurfaceClosed
1874 |       IsSurfacePlanar
1875 |       IsSurfaceSingular
1876 |       IsSurfaceTrimmed
1877 |     """
1878 |     surface = rhutil.coercesurface(surface_id, True)
1879 |     return surface.IsPeriodic(direction)
1880 | 
1881 | 
1882 | def IsSurfacePlanar(surface_id, tolerance=None):
1883 |     """Verifies a surface object is planar
1884 |     Parameters:
1885 |       surface_id (guid): identifier of a surface
1886 |       tolerance (number): tolerance used when checked. If omitted, the current absolute
1887 |         tolerance is used
1888 |     Returns:
1889 |       bool: True or False
1890 |     Example:
1891 |       import rhinoscriptsyntax as rs
1892 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
1893 |       if rs.IsSurfacePlanar(obj):
1894 |           print("The surface is planar.")
1895 |       else:
1896 |           print("The surface is not planar.")
1897 |     See Also:
1898 |       IsSurface
1899 |       IsSurfaceClosed
1900 |       IsSurfaceSingular
1901 |       IsSurfaceTrimmed
1902 |     """
1903 |     surface = rhutil.coercesurface(surface_id, True)
1904 |     if tolerance is None:
1905 |         tolerance = scriptcontext.doc.ModelAbsoluteTolerance
1906 |     return surface.IsPlanar(tolerance)
1907 | 
1908 | 
1909 | def IsSurfaceRational(surface_id):
1910 |     """Verifies a surface object is rational
1911 |     Parameters:
1912 |       surface_id (guid): the surface's identifier
1913 |     Returns:
1914 |       bool: True if successful, otherwise False
1915 |     Example:
1916 |       import rhinoscriptsyntax as rs
1917 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
1918 |       if rs.IsSurfaceRational(obj):
1919 |           print("The surface is rational.")
1920 |       else:
1921 |           print("The surface is not rational.")
1922 |     See Also:
1923 |       IsSurface
1924 |       IsSurfaceClosed
1925 |       IsSurfacePlanar
1926 |       IsSurfaceTrimmed
1927 |     """
1928 |     surface = rhutil.coercesurface(surface_id, True)
1929 |     ns = surface.ToNurbsSurface()
1930 |     if ns is None: return False
1931 |     return ns.IsRational
1932 | 
1933 | 
1934 | def IsSurfaceSingular(surface_id, direction):
1935 |     """Verifies a surface object is singular in the specified direction.
1936 |     Surfaces are considered singular if a side collapses to a point.
1937 |     Parameters:
1938 |       surface_id (guid): the surface's identifier
1939 |       direction (number):
1940 |         0=south
1941 |         1=east
1942 |         2=north
1943 |         3=west
1944 |     Returns:
1945 |       bool: True or False
1946 |     Example:
1947 |       import rhinoscriptsyntax as rs
1948 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
1949 |       if rs.IsSurfaceSingular(obj, 0):
1950 |           print("The surface is singular.")
1951 |       else:
1952 |           print("The surface is not singular.")
1953 |     See Also:
1954 |       IsSurface
1955 |       IsSurfaceClosed
1956 |       IsSurfacePlanar
1957 |       IsSurfaceTrimmed
1958 |     """
1959 |     surface = rhutil.coercesurface(surface_id, True)
1960 |     return surface.IsSingular(direction)
1961 | 
1962 | 
1963 | def IsSurfaceTrimmed(surface_id):
1964 |     """Verifies a surface object has been trimmed
1965 |     Parameters:
1966 |       surface_id (guid): the surface's identifier
1967 |     Returns:
1968 |       bool: True or False
1969 |     Example:
1970 |       import rhinoscriptsyntax as rs
1971 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
1972 |       if rs.IsSurfaceTrimmed(obj):
1973 |           print("The surface is trimmed.")
1974 |       else:
1975 |           print("The surface is not trimmed.")
1976 |     See Also:
1977 |       IsSurface
1978 |       IsSurfaceClosed
1979 |       IsSurfacePlanar
1980 |       IsSurfaceSingular
1981 |     """
1982 |     brep = rhutil.coercebrep(surface_id, True)
1983 |     return not brep.IsSurface
1984 | 
1985 | 
1986 | def IsTorus(surface_id):
1987 |     """Determines if a surface is a portion of a torus
1988 |     Parameters:
1989 |       surface_id (guid): the surface object's identifier
1990 |     Returns:
1991 |       bool: True if successful, otherwise False
1992 |     Example:
1993 |       import rhinoscriptsyntax as rs
1994 |       surface = rs.GetObject("Select a surface", rs.filter.surface)
1995 |       if surface:
1996 |           if rs.IsTorus(surface):
1997 |               print("The surface is a portion of a torus.")
1998 |           else:
1999 |               print("The surface is not a portion of a torus.")
2000 |     See Also:
2001 |       IsCone
2002 |       IsCylinder
2003 |       IsSphere
2004 |       IsSurface
2005 |     """
2006 |     surface = rhutil.coercesurface(surface_id, True)
2007 |     return surface.IsTorus()
2008 | 
2009 | 
2010 | def SurfaceSphere(surface_id):
2011 |     """Gets the sphere definition from a surface, if possible.
2012 |     Parameters:
2013 |       surface_id (guid): the identifier of the surface object
2014 |     Returns:
2015 |       (plane, number): The equatorial plane of the sphere, and its radius.
2016 |       None: on error
2017 |     Example:
2018 |       import rhinoscriptsyntax as rs
2019 |       surface = rs.GetObject("Select a surface", rs.filter.surface)
2020 |       if surface:
2021 |           result = rs.SurfaceSphere(surface)
2022 |           if result:
2023 |               print("The sphere radius is: " + str(result[1]))
2024 |     See Also:
2025 |       SurfaceCylinder
2026 |     """
2027 |     surface = rhutil.coercesurface(surface_id, True)
2028 |     tol = scriptcontext.doc.ModelAbsoluteTolerance
2029 |     is_sphere, sphere = surface.TryGetSphere(tol)
2030 |     rc = None
2031 |     if is_sphere: rc = (sphere.EquatorialPlane, sphere.Radius)
2032 |     return rc
2033 | 
2034 | 
2035 | def JoinSurfaces(object_ids, delete_input=False, return_all=False):
2036 |     """Joins two or more surface or polysurface objects together to form one
2037 |     polysurface object
2038 |     Parameters:
2039 |       object_ids ([guid, ...]) list of object identifiers
2040 |       delete_input (bool, optional): Delete the original surfaces
2041 |       return_all (bool, optional): Return all surfaces in result
2042 |     Returns:
2043 |       guid or guid list: identifier, or list of identifiers if return_all == True, of newly created object(s) on success
2044 |       None: on failure
2045 |     Example:
2046 |       import rhinoscriptsyntax as rs
2047 |       objs = rs.GetObjects("Select surfaces in order", rs.filter.surface)
2048 |       if objs and len(objs)>1: rs.JoinSurfaces(objs)
2049 |     See Also:
2050 |       ExplodePolysurfaces
2051 |       IsPolysurface
2052 |       IsPolysurfaceClosed
2053 |       IsSurface
2054 |       IsSurfaceClosed
2055 |     """
2056 |     breps = [rhutil.coercebrep(id, True) for id in object_ids]
2057 |     if len(breps)<2: return scriptcontext.errorhandler()
2058 |     tol = scriptcontext.doc.ModelAbsoluteTolerance * 2.1
2059 |     joinedbreps = Rhino.Geometry.Brep.JoinBreps(breps, tol)
2060 |     if joinedbreps is None or (len(joinedbreps)!=1 and return_all == False):
2061 |         return scriptcontext.errorhandler()
2062 |     rc = []
2063 |     for brep in joinedbreps:
2064 |         id = scriptcontext.doc.Objects.AddBrep(brep)
2065 |         if id==System.Guid.Empty: return scriptcontext.errorhandler()
2066 |         rc.append(id)
2067 |     if delete_input:
2068 |         for id in object_ids:
2069 |             id = rhutil.coerceguid(id)
2070 |             scriptcontext.doc.Objects.Delete(id, True)
2071 |     scriptcontext.doc.Views.Redraw()
2072 |     return rc if return_all else rc[0]
2073 | 
2074 | 
2075 | def MakeSurfacePeriodic(surface_id, direction, delete_input=False):
2076 |     """Makes an existing surface a periodic NURBS surface
2077 |     Parameters:
2078 |       surface_id (guid): the surface's identifier
2079 |       direction (number): The direction to make periodic, either 0=U or 1=V
2080 |       delete_input (bool, optional): delete the input surface
2081 |     Returns:
2082 |       guid: if delete_input is False, identifier of the new surface
2083 |       guid: if delete_input is True, identifier of the modifier surface
2084 |       None: on error
2085 |     Example:
2086 |       import rhinoscriptsyntax as  rs
2087 |       obj = rs.GetObject("Select  a surface", rs.filter.surface)
2088 |       if not rs.IsSurfacePeriodic(obj,  0):
2089 |           rs.MakeSurfacePeriodic(obj,  0)
2090 |     See Also:
2091 |       IsSurfacePeriodic
2092 |     """
2093 |     surface = rhutil.coercesurface(surface_id, True)
2094 |     newsurf = Rhino.Geometry.Surface.CreatePeriodicSurface(surface, direction)
2095 |     if newsurf is None: return scriptcontext.errorhandler()
2096 |     id = rhutil.coerceguid(surface_id)
2097 |     if delete_input:
2098 |         scriptcontext.doc.Objects.Replace(id, newsurf)
2099 |     else:
2100 |         id = scriptcontext.doc.Objects.AddSurface(newsurf)
2101 |     scriptcontext.doc.Views.Redraw()
2102 |     return id
2103 | 
2104 | 
2105 | def OffsetSurface(surface_id, distance, tolerance=None, both_sides=False, create_solid=False):
2106 |     """Offsets a trimmed or untrimmed surface by a distance. The offset surface
2107 |     will be added to Rhino.
2108 |     Parameters:
2109 |       surface_id (guid): the surface's identifier
2110 |       distance (number): the distance to offset
2111 |       tolerance (number, optional): The offset tolerance. Use 0.0 to make a loose offset. Otherwise, the
2112 |         document's absolute tolerance is usually sufficient.
2113 |       both_sides (bool, optional): Offset to both sides of the input surface
2114 |       create_solid (bool, optional): Make a solid object
2115 |     Returns:
2116 |       guid: identifier of the new object if successful
2117 |       None: on error
2118 |     Example:
2119 |       import rhinoscriptsyntax as rs
2120 |       surface = rs.GetObject("Select a surface", rs.filter.surface)
2121 |       if rs.IsSurface(surface):
2122 |           rs.OffsetSurface( surface, 10.0 )
2123 |     See Also:
2124 |       OffsetCurve
2125 |     """
2126 |     brep = rhutil.coercebrep(surface_id, True)
2127 |     face = None
2128 |     if (1 == brep.Faces.Count): face = brep.Faces[0]
2129 |     if face is None: return scriptcontext.errorhandler()
2130 |     if tolerance is None: tolerance = scriptcontext.doc.ModelAbsoluteTolerance
2131 |     newbrep = Rhino.Geometry.Brep.CreateFromOffsetFace(face, distance, tolerance, both_sides, create_solid)
2132 |     if newbrep is None: return scriptcontext.errorhandler()
2133 |     rc = scriptcontext.doc.Objects.AddBrep(newbrep)
2134 |     if rc==System.Guid.Empty: return scriptcontext.errorhandler()
2135 |     scriptcontext.doc.Views.Redraw()
2136 |     return rc
2137 | 
2138 | 
2139 | def PullCurve(surface, curve, delete_input=False):
2140 |     """Pulls a curve object to a surface object
2141 |     Parameters:
2142 |       surface (guid): the surface's identifier
2143 |       curve (guid): the curve's identifier
2144 |       delete_input (bool, optional) should the input items be deleted
2145 |     Returns:
2146 |       list(guid, ...): of new curves if successful
2147 |       None: on error
2148 |     Example:
2149 |       import rhinoscriptsyntax as rs
2150 |       curve = rs.GetObject("Select curve to pull", rs.filter.curve )
2151 |       surface = rs.GetObject("Select surface that pulls", rs.filter.surface )
2152 |       rs.PullCurve(surface, curve)
2153 |     See Also:
2154 |       IsSurface
2155 |     """
2156 |     crvobj = rhutil.coercerhinoobject(curve, True, True)
2157 |     brep = rhutil.coercebrep(surface, True)
2158 |     curve = rhutil.coercecurve(curve, -1, True)
2159 |     tol = scriptcontext.doc.ModelAbsoluteTolerance
2160 |     curves = Rhino.Geometry.Curve.PullToBrepFace(curve, brep.Faces[0], tol)
2161 |     rc = [scriptcontext.doc.Objects.AddCurve(curve) for curve in curves]
2162 |     if rc:
2163 |         if delete_input and crvobj:
2164 |             scriptcontext.doc.Objects.Delete(crvobj, True)
2165 |         scriptcontext.doc.Views.Redraw()
2166 |         return rc
2167 | 
2168 | 
2169 | def RebuildSurface(object_id, degree=(3,3), pointcount=(10,10)):
2170 |     """Rebuilds a surface to a given degree and control point count. For more
2171 |     information see the Rhino help file for the Rebuild command
2172 |     Parameters:
2173 |       object_id (guid): the surface's identifier
2174 |       degree ([number, number], optional): two numbers that identify surface degree in both U and V directions
2175 |       pointcount ([number, number], optional): two numbers that identify the surface point count in both the U and V directions
2176 |     Returns:
2177 |       bool: True of False indicating success or failure
2178 |     Example:
2179 |     See Also:
2180 |     """
2181 |     surface = rhutil.coercesurface(object_id, True)
2182 |     newsurf = surface.Rebuild( degree[0], degree[1], pointcount[0], pointcount[1] )
2183 |     if newsurf is None: return False
2184 |     object_id = rhutil.coerceguid(object_id)
2185 |     rc = scriptcontext.doc.Objects.Replace(object_id, newsurf)
2186 |     if rc: scriptcontext.doc.Views.Redraw()
2187 |     return rc
2188 | 
2189 | 
2190 | def RemoveSurfaceKnot(surface, uv_parameter, v_direction):
2191 |     """Deletes a knot from a surface object.
2192 |     Parameters:
2193 |       surface (guid): The reference of the surface object
2194 |       uv_parameter (list(number, number)): An indexable item containing a U,V parameter on the surface. List, tuples and UVIntervals will work.
2195 |         Note, if the parameter is not equal to one of the existing knots, then the knot closest to the specified parameter will be removed.
2196 |       v_direction (bool): if True, or 1, the V direction will be addressed. If False, or 0, the U direction.
2197 |     Returns:
2198 |       bool: True of False indicating success or failure
2199 |     Example:
2200 |       import rhinoscriptsyntax as rs
2201 | 
2202 |       srf_info = rs.GetSurfaceObject()
2203 |       if srf_info:
2204 |           srf_id = srf_info[0]
2205 |           srf_param = srf_info[4]
2206 |           rs.RemoveSurfaceKnot(srf_id, srf_param, 1)
2207 |     See Also:
2208 |       RemoveSurfaceKnot
2209 |     """
2210 |     srf_inst = rhutil.coercesurface(surface, True)
2211 |     u_param = uv_parameter[0]
2212 |     v_param = uv_parameter[1]
2213 |     success, n_u_param, n_v_param = srf_inst.GetSurfaceParameterFromNurbsFormParameter(u_param, v_param)
2214 |     if not success: return False
2215 |     n_srf = srf_inst.ToNurbsSurface()
2216 |     if not n_srf: return False
2217 |     knots = n_srf.KnotsV if v_direction else n_srf.KnotsU
2218 |     success = knots.RemoveKnotsAt(n_u_param, n_v_param)
2219 |     if not success: return False
2220 |     scriptcontext.doc.Objects.Replace(surface, n_srf)
2221 |     scriptcontext.doc.Views.Redraw()
2222 |     return True
2223 | 
2224 | 
2225 | def ReverseSurface(surface_id, direction):
2226 |     """Reverses U or V directions of a surface, or swaps (transposes) U and V
2227 |     directions.
2228 |     Parameters:
2229 |       surface_id (guid): identifier of a surface object
2230 |       direction (number): as a bit coded flag to swap
2231 |             1 = reverse U
2232 |             2 = reverse V
2233 |             4 = transpose U and V (values can be combined)
2234 |     Returns:
2235 |       bool: indicating success or failure
2236 |       None: on error
2237 |     Example:
2238 |       import rhinoscriptsyntax as rs
2239 |       obj = rs.GetObject("Select a surface to reverse")
2240 |       if rs.IsSurface(obj):
2241 |           rs.ReverseSurface( obj, 1 )
2242 |     See Also:
2243 |       FlipSurface
2244 |       IsSurface
2245 |     """
2246 |     brep = rhutil.coercebrep(surface_id, True)
2247 |     if not brep.Faces.Count==1: return scriptcontext.errorhandler()
2248 |     face = brep.Faces[0]
2249 |     if direction & 1:
2250 |         face.Reverse(0, True)
2251 |     if direction & 2:
2252 |         face.Reverse(1, True)
2253 |     if direction & 4:
2254 |         face.Transpose(True)
2255 |     scriptcontext.doc.Objects.Replace(surface_id, brep)
2256 |     scriptcontext.doc.Views.Redraw()
2257 |     return True
2258 | 
2259 | 
2260 | def ShootRay(surface_ids, start_point, direction, reflections=10):
2261 |     """Shoots a ray at a collection of surfaces
2262 |     Parameters:
2263 |       surface_ids ([guid, ...]): one of more surface identifiers
2264 |       start_point (point): starting point of the ray
2265 |       direction (vector):  vector identifying the direction of the ray
2266 |       reflections (number, optional): the maximum number of times the ray will be reflected
2267 |     Returns:
2268 |       list(point, ...): of reflection points on success
2269 |       None: on error
2270 |     Example:
2271 |       import rhinoscriptsyntax as rs
2272 |       def TestRayShooter():
2273 |           corners = []
2274 |           corners.append((0,0,0))
2275 |           corners.append((10,0,0))
2276 |           corners.append((10,10,0))
2277 |           corners.append((0,10,0))
2278 |           corners.append((0,0,10))
2279 |           corners.append((10,0,10))
2280 |           corners.append((10,10,10))
2281 |           corners.append((0,10,10))
2282 |           box = rs.AddBox(corners)
2283 |           dir = 10,7.5,7
2284 |           reflections = rs.ShootRay(box, (0,0,0), dir)
2285 |           rs.AddPolyline( reflections )
2286 |           rs.AddPoints( reflections )
2287 |       TestRayShooter()
2288 |     See Also:
2289 |       IsPolysurface
2290 |       IsSurface
2291 |     """
2292 |     start_point = rhutil.coerce3dpoint(start_point, True)
2293 |     direction = rhutil.coerce3dvector(direction, True)
2294 |     id = rhutil.coerceguid(surface_ids, False)
2295 |     if id: surface_ids = [id]
2296 |     ray = Rhino.Geometry.Ray3d(start_point, direction)
2297 |     breps = []
2298 |     for id in surface_ids:
2299 |         brep = rhutil.coercebrep(id)
2300 |         if brep: breps.append(brep)
2301 |         else:
2302 |             surface = rhutil.coercesurface(id, True)
2303 |             breps.append(surface)
2304 |     if not breps: return scriptcontext.errorhandler()
2305 |     points = Rhino.Geometry.Intersect.Intersection.RayShoot(ray, breps, reflections)
2306 |     if points:
2307 |         rc = []
2308 |         rc.append(start_point)
2309 |         rc = rc + list(points)
2310 |         return rc
2311 |     return scriptcontext.errorhandler()
2312 | 
2313 | 
2314 | def ShortPath(surface_id, start_point, end_point):
2315 |     """Creates the shortest possible curve(geodesic) between two points on a
2316 |     surface. For more details, see the ShortPath command in Rhino help
2317 |     Parameters:
2318 |       surface_id (guid): identifier of a surface
2319 |       start_point, end_point (point): start/end points of the short curve
2320 |     Returns:
2321 |       guid: identifier of the new surface on success
2322 |       None: on error
2323 |     Example:
2324 |       import rhinoscriptsyntax as rs
2325 |       surface = rs.GetObject("Select surface for short path", rs.filter.surface + rs.filter.surface)
2326 |       if surface:
2327 |           start = rs.GetPointOnSurface(surface, "First point")
2328 |           end = rs.GetPointOnSurface(surface, "Second point")
2329 |           rs.ShortPath(surface, start, end)
2330 |     See Also:
2331 |       EvaluateSurface
2332 |       SurfaceClosestPoint
2333 |     """
2334 |     surface = rhutil.coercesurface(surface_id, True)
2335 |     start = rhutil.coerce3dpoint(start_point, True)
2336 |     end = rhutil.coerce3dpoint(end_point, True)
2337 |     rc_start, u_start, v_start = surface.ClosestPoint(start)
2338 |     rc_end, u_end, v_end = surface.ClosestPoint(end)
2339 |     if not rc_start or not rc_end: return scriptcontext.errorhandler()
2340 |     start = Rhino.Geometry.Point2d(u_start, v_start)
2341 |     end = Rhino.Geometry.Point2d(u_end, v_end)
2342 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
2343 |     curve = surface.ShortPath(start, end, tolerance)
2344 |     if curve is None: return scriptcontext.errorhandler()
2345 |     id = scriptcontext.doc.Objects.AddCurve(curve)
2346 |     if id==System.Guid.Empty: return scriptcontext.errorhandler()
2347 |     scriptcontext.doc.Views.Redraw()
2348 |     return id
2349 | 
2350 | 
2351 | def ShrinkTrimmedSurface(object_id, create_copy=False):
2352 |     """Shrinks the underlying untrimmed surfaces near to the trimming
2353 |     boundaries. See the ShrinkTrimmedSrf command in the Rhino help.
2354 |     Parameters:
2355 |       object_id (guid): the surface's identifier
2356 |       create_copy (bool, optional): If True, the original surface is not deleted
2357 |     Returns:
2358 |       bool: If create_copy is False, True or False indicating success or failure
2359 |       bool: If create_copy is True, the identifier of the new surface
2360 |       None: on error
2361 |     Example:
2362 |       import rhinoscriptsyntax as rs
2363 |       filter = rs.filter.surface | rs.filter.polysurface
2364 |       surface = rs.GetObject("Select surface or polysurface to shrink", filter )
2365 |       if surface: rs.ShrinkTrimmedSurface( surface )
2366 |     See Also:
2367 |       IsSurfaceTrimmed
2368 |     """
2369 |     brep = rhutil.coercebrep(object_id, True)
2370 |     if not brep.Faces.ShrinkFaces(): return scriptcontext.errorhandler()
2371 |     rc = None
2372 |     object_id = rhutil.coerceguid(object_id)
2373 |     if create_copy:
2374 |         oldobj = scriptcontext.doc.Objects.Find(object_id)
2375 |         attr = oldobj.Attributes
2376 |         rc = scriptcontext.doc.Objects.AddBrep(brep, attr)
2377 |     else:
2378 |         rc = scriptcontext.doc.Objects.Replace(object_id, brep)
2379 |     scriptcontext.doc.Views.Redraw()
2380 |     return rc
2381 | 
2382 | 
2383 | def __GetMassProperties(object_id, area):
2384 |     surface = rhutil.coercebrep(object_id)
2385 |     if surface is None:
2386 |         surface = rhutil.coercesurface(object_id)
2387 |         if surface is None: return None
2388 |     if area==True: return Rhino.Geometry.AreaMassProperties.Compute(surface)
2389 |     if not surface.IsSolid: return None
2390 |     return Rhino.Geometry.VolumeMassProperties.Compute(surface)
2391 | 
2392 | 
2393 | def SplitBrep(brep_id, cutter_id, delete_input=False):
2394 |     """Splits a brep
2395 |     Parameters:
2396 |       brep (guid): identifier of the brep to split
2397 |       cutter (guid): identifier of the brep to split with
2398 |     Returns:
2399 |       list(guid, ...): identifiers of split pieces on success
2400 |       None: on error
2401 |     Example:
2402 |       import rhinoscriptsyntax as rs
2403 |       filter = rs.filter.surface + rs.filter.polysurface
2404 |       brep = rs.GetObject("Select brep to split", filter)
2405 |       cutter = rs.GetObject("Select cutting brep", filter)
2406 |       rs.SplitBrep ( brep, cutter )
2407 |     See Also:
2408 |       IsBrep
2409 |     """
2410 |     brep = rhutil.coercebrep(brep_id, True)
2411 |     cutter = rhutil.coercebrep(cutter_id, True)
2412 |     tol = scriptcontext.doc.ModelAbsoluteTolerance
2413 |     pieces = brep.Split(cutter, tol)
2414 |     if not pieces: return scriptcontext.errorhandler()
2415 |     if delete_input:
2416 |         brep_id = rhutil.coerceguid(brep_id)
2417 |         scriptcontext.doc.Objects.Delete(brep_id, True)
2418 |     rc = [scriptcontext.doc.Objects.AddBrep(piece) for piece in pieces]
2419 |     scriptcontext.doc.Views.Redraw()
2420 |     return rc
2421 | 
2422 | 
2423 | def SurfaceArea(object_id):
2424 |     """Calculate the area of a surface or polysurface object. The results are
2425 |     based on the current drawing units
2426 |     Parameters:
2427 |       object_id (guid): the surface's identifier
2428 |     Returns:
2429 |       list(number, number): of area information on success (area, absolute error bound)
2430 |       None: on error
2431 |     Example:
2432 |       import rhinoscriptsyntax as rs
2433 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
2434 |       if obj:
2435 |           massprop = rs.SurfaceArea( obj )
2436 |           if massprop:
2437 |               print("The surface area is: {}".format(massprop[0]))
2438 |     See Also:
2439 |       SurfaceAreaCentroid
2440 |       SurfaceAreaMoments
2441 |     """
2442 |     amp = __GetMassProperties(object_id, True)
2443 |     if amp: return amp.Area, amp.AreaError
2444 | 
2445 | 
2446 | def SurfaceAreaCentroid(object_id):
2447 |     """Calculates the area centroid of a surface or polysurface
2448 |     Parameters:
2449 |       object_id (guid): the surface's identifier
2450 |     Returns:
2451 |       list(point, tuple(number, number, number)): Area centroid information (Area Centroid, Error bound in X, Y, Z)
2452 |       None: on error
2453 |     Example:
2454 |       import rhinoscriptsyntax as rs
2455 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
2456 |       if obj:
2457 |           massprop = rs.SurfaceAreaCentroid(obj)
2458 |           if massprop: rs.AddPoint( massprop[0] )
2459 |     See Also:
2460 |       SurfaceArea
2461 |       SurfaceAreaMoments
2462 |     """
2463 |     amp = __GetMassProperties(object_id, True)
2464 |     if amp is None: return scriptcontext.errorhandler()
2465 |     return amp.Centroid, amp.CentroidError
2466 | 
2467 | 
2468 | def __AreaMomentsHelper(surface_id, area):
2469 |     mp = __GetMassProperties(surface_id, area)
2470 |     if mp is None: return scriptcontext.errorhandler()
2471 |     a = (mp.WorldCoordinatesFirstMoments.X, mp.WorldCoordinatesFirstMoments.Y, mp.WorldCoordinatesFirstMoments.Z)
2472 |     b = (mp.WorldCoordinatesFirstMomentsError.X, mp.WorldCoordinatesFirstMomentsError.Y, mp.WorldCoordinatesFirstMomentsError.Z)
2473 |     c = (mp.WorldCoordinatesSecondMoments.X, mp.WorldCoordinatesSecondMoments.Y, mp.WorldCoordinatesSecondMoments.Z)
2474 |     d = (mp.WorldCoordinatesSecondMomentsError.X, mp.WorldCoordinatesSecondMomentsError.Y, mp.WorldCoordinatesSecondMomentsError.Z)
2475 |     e = (mp.WorldCoordinatesProductMoments.X, mp.WorldCoordinatesProductMoments.Y, mp.WorldCoordinatesProductMoments.Z)
2476 |     f = (mp.WorldCoordinatesProductMomentsError.X, mp.WorldCoordinatesProductMomentsError.Y, mp.WorldCoordinatesProductMomentsError.Z)
2477 |     g = (mp.WorldCoordinatesMomentsOfInertia.X, mp.WorldCoordinatesMomentsOfInertia.Y, mp.WorldCoordinatesMomentsOfInertia.Z)
2478 |     h = (mp.WorldCoordinatesMomentsOfInertiaError.X, mp.WorldCoordinatesMomentsOfInertiaError.Y, mp.WorldCoordinatesMomentsOfInertiaError.Z)
2479 |     i = (mp.WorldCoordinatesRadiiOfGyration.X, mp.WorldCoordinatesRadiiOfGyration.Y, mp.WorldCoordinatesRadiiOfGyration.Z)
2480 |     j = (0,0,0) # need to add error calc to RhinoCommon
2481 |     k = (mp.CentroidCoordinatesMomentsOfInertia.X, mp.CentroidCoordinatesMomentsOfInertia.Y, mp.CentroidCoordinatesMomentsOfInertia.Z)
2482 |     l = (mp.CentroidCoordinatesMomentsOfInertiaError.X, mp.CentroidCoordinatesMomentsOfInertiaError.Y, mp.CentroidCoordinatesMomentsOfInertiaError.Z)
2483 |     m = (mp.CentroidCoordinatesRadiiOfGyration.X, mp.CentroidCoordinatesRadiiOfGyration.Y, mp.CentroidCoordinatesRadiiOfGyration.Z)
2484 |     n = (0,0,0) #need to add error calc to RhinoCommon
2485 |     return (a,b,c,d,e,f,g,h,i,j,k,l,m,n)
2486 | 
2487 | 
2488 | def SurfaceAreaMoments(surface_id):
2489 |     """Calculates area moments of inertia of a surface or polysurface object.
2490 |     See the Rhino help for "Mass Properties calculation details"
2491 |     Parameters:
2492 |       surface_id (guid): the surface's identifier
2493 |     Returns:
2494 |       list(tuple(number, number,number), ...): of moments and error bounds in tuple(X, Y, Z) - see help topic
2495 |         Index   Description
2496 |         [0]     First Moments.
2497 |         [1]     The absolute (+/-) error bound for the First Moments.
2498 |         [2]     Second Moments.
2499 |         [3]     The absolute (+/-) error bound for the Second Moments.
2500 |         [4]     Product Moments.
2501 |         [5]     The absolute (+/-) error bound for the Product Moments.
2502 |         [6]     Area Moments of Inertia about the World Coordinate Axes.
2503 |         [7]     The absolute (+/-) error bound for the Area Moments of Inertia about World Coordinate Axes.
2504 |         [8]     Area Radii of Gyration about the World Coordinate Axes.
2505 |         [9]     The absolute (+/-) error bound for the Area Radii of Gyration about World Coordinate Axes.
2506 |         [10]    Area Moments of Inertia about the Centroid Coordinate Axes.
2507 |         [11]    The absolute (+/-) error bound for the Area Moments of Inertia about the Centroid Coordinate Axes.
2508 |         [12]    Area Radii of Gyration about the Centroid Coordinate Axes.
2509 |         [13]    The absolute (+/-) error bound for the Area Radii of Gyration about the Centroid Coordinate Axes.
2510 |       None: on error
2511 |     Example:
2512 |       import rhinoscriptsyntax as rs
2513 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
2514 |       if obj:
2515 |           massprop= rs.SurfaceAreaMoments(obj)
2516 |           if massprop:
2517 |               print("Area Moments of Inertia about the World Coordinate Axes: {}".format(massprop[6]))
2518 |     See Also:
2519 |       SurfaceArea
2520 |       SurfaceAreaCentroid
2521 |     """
2522 |     return __AreaMomentsHelper(surface_id, True)
2523 | 
2524 | 
2525 | def SurfaceClosestPoint(surface_id, test_point):
2526 |     """Returns U,V parameters of point on a surface that is closest to a test point
2527 |     Parameters:
2528 |       surface_id (guid): identifier of a surface object
2529 |       test_point (point): sampling point
2530 |     Returns:
2531 |       list(number, number): The U,V parameters of the closest point on the surface if successful.
2532 |       None: on error.
2533 |     Example:
2534 |       import rhinoscriptsyntax as rs
2535 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
2536 |       if rs.IsSurface(obj):
2537 |           point = rs.GetPointOnSurface(obj, "Pick a test point")
2538 |           if point:
2539 |               param = rs.SurfaceClosestPoint(obj, point)
2540 |               if param:
2541 |                   print("Surface U parameter: {}".format(str(param[0])))
2542 |                   print("Surface V parameter: {}".format(str(param[1])))
2543 |     See Also:
2544 |       BrepClosestPoint
2545 |       EvaluateSurface
2546 |       IsSurface
2547 |     """
2548 |     surface = rhutil.coercesurface(surface_id, True)
2549 |     point = rhutil.coerce3dpoint(test_point, True)
2550 |     rc, u, v = surface.ClosestPoint(point)
2551 |     if not rc: return None
2552 |     return u,v
2553 | 
2554 | 
2555 | def SurfaceCone(surface_id):
2556 |     """Returns the definition of a surface cone
2557 |     Parameters:
2558 |       surface_id (guid): the surface's identifier
2559 |     Returns:
2560 |       tuple(plane, number, number): containing the definition of the cone if successful
2561 |         [0]   the plane of the cone. The apex of the cone is at the
2562 |               plane's origin and the axis of the cone is the plane's z-axis
2563 |         [1]   the height of the cone
2564 |         [2]   the radius of the cone
2565 |       None: on error
2566 |     Example:
2567 |       import rhinoscriptsyntax as rs
2568 |       cone = rs.AddCone(rs.WorldXYPlane(), 6, 2, False)
2569 |       if rs.IsCone(cone):
2570 |           cone_def = rs.SurfaceCone(cone)
2571 |           rs.AddCone( cone_def[0], cone_def[1], cone_def[2], False )
2572 |     See Also:
2573 |       
2574 |     """
2575 |     surface = rhutil.coercesurface(surface_id, True)
2576 |     rc, cone = surface.TryGetCone()
2577 |     if not rc: return scriptcontext.errorhandler()
2578 |     return cone.Plane, cone.Height, cone.Radius
2579 | 
2580 | 
2581 | def SurfaceCurvature(surface_id, parameter):
2582 |     """Returns the curvature of a surface at a U,V parameter. See Rhino help
2583 |     for details of surface curvature
2584 |     Parameters:
2585 |       surface_id (guid): the surface's identifier
2586 |       parameter (number, number): u,v parameter
2587 |     Returns:
2588 |       tuple(point, vector, number, number, number, number, number): of curvature information
2589 |         [0]   point at specified U,V parameter
2590 |         [1]   normal direction
2591 |         [2]   maximum principal curvature
2592 |         [3]   maximum principal curvature direction
2593 |         [4]   minimum principal curvature
2594 |         [5]   minimum principal curvature direction
2595 |         [6]   gaussian curvature
2596 |         [7]   mean curvature
2597 |       None: if not successful, or on error
2598 |     Example:
2599 |       import rhinoscriptsyntax as rs
2600 |       srf = rs.GetObject("Select a surface", rs.filter.surface)
2601 |       if rs.IsSurface(srf):
2602 |           point = rs.GetPointOnSurface(srf, "Pick a test point")
2603 |           if point:
2604 |               param = rs.SurfaceClosestPoint(srf, point)
2605 |               if param:
2606 |                   data = rs.SurfaceCurvature(srf, param)
2607 |                   if data:
2608 |                       print("Surface curvature evaluation at parameter {}:".format(param))
2609 |                       print(" 3-D Point:{}".format(data[0]))
2610 |                       print(" 3-D Normal:{}".format(data[1]))
2611 |                       print(" Maximum principal curvature: {} {}".format(data[2], data[3]))
2612 |                       print(" Minimum principal curvature: {} {}".format(data[4], data[5]))
2613 |                       print(" Gaussian curvature:{}".format(data[6]))
2614 |                       print(" Mean curvature:{}".format(data[7]))
2615 |     See Also:
2616 |       CurveCurvature
2617 |     """
2618 |     surface = rhutil.coercesurface(surface_id, True)
2619 |     if len(parameter)<2: return scriptcontext.errorhandler()
2620 |     c = surface.CurvatureAt(parameter[0], parameter[1])
2621 |     if c is None: return scriptcontext.errorhandler()
2622 |     return c.Point, c.Normal, c.Kappa(0), c.Direction(0), c.Kappa(1), c.Direction(1), c.Gaussian, c.Mean
2623 | 
2624 | 
2625 | def SurfaceCylinder(surface_id):
2626 |     """Returns the definition of a cylinder surface
2627 |     Parameters:
2628 |       surface_id (guid): the surface's identifier
2629 |     Returns:
2630 |       tuple(plane, number, number): of the cylinder plane, height, radius on success
2631 |       None: on error
2632 |     Example:
2633 |       import rhinoscriptsyntax as rs
2634 |       cylinder = rs.AddCylinder(rs.WorldXYPlane(), 6, 2, False)
2635 |       if rs.IsCylinder(cylinder):
2636 |           plane, height, radius = rs.SurfaceCylinder(cylinder)
2637 |           rs.AddCylinder(plane, height, radius, False)
2638 |     See Also:
2639 |       SurfaceSphere
2640 |     """
2641 |     surface = rhutil.coercesurface(surface_id, True)
2642 |     tol = scriptcontext.doc.ModelAbsoluteTolerance
2643 |     rc, cylinder = surface.TryGetFiniteCylinder(tol)
2644 |     if rc:
2645 |         return cylinder.BasePlane, cylinder.TotalHeight, cylinder.Radius
2646 | 
2647 | 
2648 | def SurfaceDegree(surface_id, direction=2):
2649 |     """Returns the degree of a surface object in the specified direction
2650 |     Parameters:
2651 |       surface_id (guid): the surface's identifier
2652 |       direction (number, optional): The degree U, V direction
2653 |                 0 = U
2654 |                 1 = V
2655 |                 2 = both
2656 |     Returns:
2657 |       number: Single number if `direction` = 0 or 1
2658 |       tuple(number, number): of two values if `direction` = 2
2659 |       None: on error
2660 |     Example:
2661 |       import rhinoscriptsyntax as rs
2662 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
2663 |       if rs.IsSurface(obj):
2664 |           print("Degree in U direction: {}".format(rs.SurfaceDegree(obj, 0)))
2665 |           print("Degree in V direction: {}".format(rs.SurfaceDegree(obj, 1)))
2666 |     See Also:
2667 |       IsSurface
2668 |       SurfaceDomain
2669 |     """
2670 |     surface = rhutil.coercesurface(surface_id, True)
2671 |     if direction==0 or direction==1: return surface.Degree(direction)
2672 |     if direction==2: return surface.Degree(0), surface.Degree(1)
2673 |     return scriptcontext.errorhandler()
2674 | 
2675 | 
2676 | def SurfaceDomain(surface_id, direction):
2677 |     """Returns the domain of a surface object in the specified direction.
2678 |     Parameters:
2679 |       surface_id (guid): the surface's identifier
2680 |       direction (number): domain direction 0 = U, or 1 = V
2681 |     Returns:
2682 |       list(number, number): containing the domain interval in the specified direction
2683 |       None: if not successful, or on error
2684 |     Example:
2685 |       import rhinoscriptsyntax as rs
2686 |       object = rs.GetObject("Select a surface", rs.filter.surface)
2687 |       if rs.IsSurface(object):
2688 |           domainU = rs.SurfaceDomain(object, 0)
2689 |           domainV = rs.SurfaceDomain(object, 1)
2690 |           print("Domain in U direction: {}".format(domainU))
2691 |           print("Domain in V direction: {}".format(domainV))
2692 |     See Also:
2693 |       IsSurface
2694 |       SurfaceDegree
2695 |     """
2696 |     if direction!=0 and direction!=1: return scriptcontext.errorhandler()
2697 |     surface = rhutil.coercesurface(surface_id, True)
2698 |     domain = surface.Domain(direction)
2699 |     return domain.T0, domain.T1
2700 | 
2701 | 
2702 | def SurfaceEditPoints(surface_id, return_parameters=False, return_all=True):
2703 |     """Returns the edit, or Greville points of a surface object. For each
2704 |     surface control point, there is a corresponding edit point
2705 |     Parameters:
2706 |       surface_id (guid): the surface's identifier
2707 |       return_parameters (bool, optional): If False, edit points are returned as a list of
2708 |         3D points. If True, edit points are returned as a list of U,V surface
2709 |         parameters
2710 |       return_all (bool, options): If True, all surface edit points are returned. If False,
2711 |         the function will return surface edit points based on whether or not the
2712 |         surface is closed or periodic
2713 |     Returns:
2714 |       list(point, ...): if return_parameters is False, a list of 3D points
2715 |       list((number, number), ...): if return_parameters is True, a list of U,V parameters
2716 |       None: on error
2717 |     Example:
2718 |       import rhinoscriptsyntax as rs
2719 |       obj = rs.GetObject("Select a surface")
2720 |       if rs.IsSurface(obj):
2721 |           points = rs.SurfaceEditPoints(obj)
2722 |           if points: rs.AddPointCloud(points)
2723 |     See Also:
2724 |       IsSurface
2725 |       SurfacePointCount
2726 |       SurfacePoints
2727 |     """
2728 |     surface = rhutil.coercesurface(surface_id, True)
2729 |     nurb = surface.ToNurbsSurface()
2730 |     if not nurb: return scriptcontext.errorhandler()
2731 |     ufirst = 0
2732 |     ulast = nurb.Points.CountU
2733 |     vfirst = 0
2734 |     vlast = nurb.Points.CountV
2735 |     if not return_all:
2736 |         if nurb.IsClosed(0): ulast = nurb.Points.CountU-1
2737 |         if nurb.IsPeriodic(0):
2738 |             degree = nurb.Degree(0)
2739 |             ufirst = degree/2
2740 |             ulast = nurb.Points.CountU-degree+ufirst
2741 |         if nurb.IsClosed(1): vlast = nurb.Points.CountV-1
2742 |         if nurb.IsPeriodic(1):
2743 |             degree = nurb.Degree(1)
2744 |             vfirst = degree/2
2745 |             vlast = nurb.Points.CountV-degree+vfirst
2746 |     rc = []
2747 |     for u in range(ufirst, ulast):
2748 |         for v in range(vfirst, vlast):
2749 |             pt = nurb.Points.GetGrevillePoint(u,v)
2750 |             if not return_parameters: pt = nurb.PointAt(pt.X, pt.Y)
2751 |             rc.append(pt)
2752 |     return rc
2753 | 
2754 | 
2755 | def SurfaceEvaluate(surface_id, parameter, derivative):
2756 |     """A general purpose surface evaluator
2757 |     Parameters:
2758 |       surface_id (guid): the surface's identifier
2759 |       parameter ([number, number]): u,v parameter to evaluate
2760 |       derivative (number): number of derivatives to evaluate
2761 |     Returns:
2762 |       list((point, vector, ...), ...): list length (derivative+1)*(derivative+2)/2 if successful.  The elements are as follows:
2763 |       Element  Description
2764 |       [0]      The 3-D point.
2765 |       [1]      The first derivative.
2766 |       [2]      The first derivative.
2767 |       [3]      The second derivative.
2768 |       [4]      The second derivative.
2769 |       [5]      The second derivative.
2770 |       [6]      etc...
2771 |     None: If not successful, or on error.
2772 |     Example:
2773 |       import rhinoscriptsyntax as rs
2774 |       def TestSurfaceEvaluate():
2775 |           srf = rs.GetObject("Select surface to evaluate", rs.filter.surface, True)
2776 |           if srf is None: return
2777 |           point = rs.GetPointOnSurface(srf, "Point to evaluate")
2778 |           if point is None: return
2779 |           der = rs.GetInteger("Number of derivatives to evaluate", 1, 1)
2780 |           if der is None: return
2781 |           uv = rs.SurfaceClosestPoint(srf, point)
2782 |           res = rs.SurfaceEvaluate(srf, uv, der)
2783 |           if res is None:
2784 |               print("Failed to evaluate surface.")
2785 |               return
2786 |           for i,r in enumerate(res):
2787 |               print("{} = {}".format(i, r))
2788 |       TestSurfaceEvaluate()
2789 |     See Also:
2790 |       EvaluateSurface
2791 |     """
2792 |     surface = rhutil.coercesurface(surface_id, True)
2793 |     success, point, der = surface.Evaluate(parameter[0], parameter[1], derivative)
2794 |     if not success: return scriptcontext.errorhandler()
2795 |     rc = [point]
2796 |     if der:
2797 |       for d in der: rc.append(d)
2798 |     return rc
2799 | 
2800 | 
2801 | def SurfaceFrame(surface_id, uv_parameter):
2802 |     """Returns a plane based on the normal, u, and v directions at a surface
2803 |     U,V parameter
2804 |     Parameters:
2805 |       surface_id (guid): the surface's identifier
2806 |       uv_parameter ([number, number]): u,v parameter to evaluate
2807 |     Returns:
2808 |       plane: plane on success
2809 |       None: on error
2810 |     Example:
2811 |       import rhinoscriptsyntax as rs
2812 |       surface = rs.GetSurfaceObject("Select a surface")
2813 |       if surface:
2814 |           plane = rs.SurfaceFrame(surface[0], surface[4])
2815 |           rs.ViewCPlane(None, plane)
2816 |     See Also:
2817 |       EvaluateSurface
2818 |       SurfaceClosestPoint
2819 |       SurfaceNormal
2820 |     """
2821 |     surface = rhutil.coercesurface(surface_id, True)
2822 |     rc, frame = surface.FrameAt(uv_parameter[0], uv_parameter[1])
2823 |     if rc: return frame
2824 | 
2825 | 
2826 | def SurfaceIsocurveDensity(surface_id, density=None):
2827 |     """Returns or sets the isocurve density of a surface or polysurface object.
2828 |     An isoparametric curve is a curve of constant U or V value on a surface.
2829 |     Rhino uses isocurves and surface edge curves to visualize the shape of a
2830 |     NURBS surface
2831 |     Parameters:
2832 |       surface_id (guid): the surface's identifier
2833 |       density (number, optional): the isocurve wireframe density. The possible values are
2834 |           -1: Hides the surface isocurves
2835 |            0: Display boundary and knot wires
2836 |            1: Display boundary and knot wires and one interior wire if there
2837 |               are no interior knots
2838 |          >=2: Display boundary and knot wires and (N+1) interior wires
2839 |     Returns:
2840 |       number: If density is not specified, then the current isocurve density if successful
2841 |       number: If density is specified, the the previous isocurve density if successful
2842 |       None: on error
2843 |     Example:
2844 |       import rhinoscriptsyntax as rs
2845 |       obj = rs.GetObject("Select a surface", rs.filter.surface | rs.filter.polysurface)
2846 |       if obj: rs.SurfaceIsocurveDensity( obj, 8 )
2847 |     See Also:
2848 |       IsPolysurface
2849 |       IsSurface
2850 |     """
2851 |     rhino_object = rhutil.coercerhinoobject(surface_id, True, True)
2852 |     if not isinstance(rhino_object, Rhino.DocObjects.BrepObject):
2853 |         return scriptcontext.errorhandler()
2854 |     rc = rhino_object.Attributes.WireDensity
2855 |     if density is not None:
2856 |         if density<0: density = -1
2857 |         rhino_object.Attributes.WireDensity = density
2858 |         rhino_object.CommitChanges()
2859 |         scriptcontext.doc.Views.Redraw()
2860 |     return rc
2861 | 
2862 | 
2863 | def SurfaceKnotCount(surface_id):
2864 |     """Returns the control point count of a surface
2865 |       surface_id = the surface's identifier
2866 |     Parameters:
2867 |       surface_id (guid): the surface object's identifier
2868 |     Returns:
2869 |       list(number, number): a list containing (U count, V count) on success
2870 |     Example:
2871 |       import rhinoscriptsyntax as rs
2872 |       obj = rs.GetObject("Select a surface")
2873 |       if rs.IsSurface(obj):
2874 |           count = rs.SurfaceKnotCount(obj)
2875 |           print("Knot count in U direction: {}".format(count[0]))
2876 |           print("Knot count in V direction: {}".format(count[1]))
2877 |     See Also:
2878 |       IsSurface
2879 |       SurfaceKnots
2880 |     """
2881 |     surface = rhutil.coercesurface(surface_id, True)
2882 |     ns = surface.ToNurbsSurface()
2883 |     return ns.KnotsU.Count, ns.KnotsV.Count
2884 | 
2885 | 
2886 | def SurfaceKnots(surface_id):
2887 |     """Returns the knots, or knot vector, of a surface object.
2888 |     Parameters:
2889 |       surface_id (guid): the surface's identifier
2890 |     Returns:
2891 |      list(number, number): knot values of the surface if successful. The list will
2892 |       contain the following information:
2893 |       Element   Description
2894 |         [0]     Knot vector in U direction
2895 |         [1]     Knot vector in V direction
2896 |       None: if not successful, or on error.
2897 |     Example:
2898 |       import rhinoscriptsyntax as rs
2899 |       obj = rs.GetObject("Select a surface")
2900 |       if rs.IsSurface(obj):
2901 |           knots = rs.SurfaceKnots(obj)
2902 |           if knots:
2903 |               vector = knots[0]
2904 |               print("Knot vector in U direction")
2905 |               for item in vector: print("Surface knot value: {}".format(item))
2906 |               vector = knots[1]
2907 |               print("Knot vector in V direction")
2908 |               for item in vector: print("Surface knot value: {}".format(item))
2909 |     See Also:
2910 |       IsSurface
2911 |       SurfaceKnotCount
2912 |     """
2913 |     surface = rhutil.coercesurface(surface_id, True)
2914 |     nurb_surf = surface.ToNurbsSurface()
2915 |     if nurb_surf is None: return scriptcontext.errorhandler()
2916 |     s_knots = [knot for knot in nurb_surf.KnotsU]
2917 |     t_knots = [knot for knot in nurb_surf.KnotsV]
2918 |     if not s_knots or not t_knots: return scriptcontext.errorhandler()
2919 |     return s_knots, t_knots
2920 | 
2921 | 
2922 | def SurfaceNormal(surface_id, uv_parameter):
2923 |     """Returns 3D vector that is the normal to a surface at a parameter
2924 |     Parameters:
2925 |       surface_id (guid): the surface's identifier
2926 |       uv_parameter  ([number, number]): the uv parameter to evaluate
2927 |     Returns:
2928 |       vector: Normal vector on success
2929 |     Example:
2930 |       import rhinoscriptsyntax as rs
2931 |       obj = rs.GetObject("Select a surface", rs.filter.surface)
2932 |       if obj:
2933 |           point = rs.GetPointOnSurface(obj)
2934 |           if point:
2935 |               param = rs.SurfaceClosestPoint(obj, point)
2936 |               normal = rs.SurfaceNormal(obj, param)
2937 |               rs.AddPoints( [point, point + normal] )
2938 |     See Also:
2939 |       SurfaceClosestPoint
2940 |       SurfaceDomain
2941 |     """
2942 |     surface = rhutil.coercesurface(surface_id, True)
2943 |     return surface.NormalAt(uv_parameter[0], uv_parameter[1])
2944 | 
2945 | 
2946 | def SurfaceNormalizedParameter(surface_id, parameter):
2947 |     """Converts surface parameter to a normalized surface parameter; one that
2948 |     ranges between 0.0 and 1.0 in both the U and V directions
2949 |     Parameters:
2950 |       surface_id (guid) the surface's identifier
2951 |       parameter ([number, number]): the surface parameter to convert
2952 |     Returns:
2953 |       list(number, number): normalized surface parameter if successful
2954 |       None: on error
2955 |     Example:
2956 |       import rhinoscriptsyntax as rs
2957 |       obj = rs.GetObject("Select surface")
2958 |       if rs.IsSurface(obj):
2959 |           domain_u = rs.SurfaceDomain(obj, 0)
2960 |           domain_v = rs.SurfaceDomain(obj, 1)
2961 |           parameter = (domain_u[1] + domain_u[0]) / 2.0, (domain_v[1] + domain_v[0]) / 2.0
2962 |           print("Surface parameter: {}".format(parameter))
2963 |           normalized = rs.SurfaceNormalizedParameter(obj, parameter)
2964 |           print("Normalized parameter: {}".format(normalized))
2965 |     See Also:
2966 |       SurfaceDomain
2967 |       SurfaceParameter
2968 |     """
2969 |     surface = rhutil.coercesurface(surface_id, True)
2970 |     u_domain = surface.Domain(0)
2971 |     v_domain = surface.Domain(1)
2972 |     if parameter[0]<u_domain.Min or parameter[0]>u_domain.Max:
2973 |         return scriptcontext.errorhandler()
2974 |     if parameter[1]<v_domain.Min or parameter[1]>v_domain.Max:
2975 |         return scriptcontext.errorhandler()
2976 |     u = u_domain.NormalizedParameterAt(parameter[0])
2977 |     v = v_domain.NormalizedParameterAt(parameter[1])
2978 |     return u,v
2979 | 
2980 | 
2981 | def SurfaceParameter(surface_id, parameter):
2982 |     """Converts normalized surface parameter to a surface parameter; or
2983 |     within the surface's domain
2984 |     Parameters:
2985 |       surface_id (guid): the surface's identifier
2986 |       parameter ([number, number]): the normalized parameter to convert
2987 |     Returns:
2988 |       tuple(number, number): surface parameter on success
2989 |     Example:
2990 |       import rhinoscriptsyntax as rs
2991 |       obj = rs.GetObject("Select surface")
2992 |       if obj:
2993 |           normalized = (0.5, 0.5)
2994 |           print("Normalized parameter: {}".format(normalized))
2995 |           parameter = rs.SurfaceParameter(obj, normalized)
2996 |           print("Surface parameter: {}".format(parameter))
2997 |     See Also:
2998 |       SurfaceDomain
2999 |       SurfaceNormalizedParameter
3000 |     """
3001 |     surface = rhutil.coercesurface(surface_id, True)
3002 |     x = surface.Domain(0).ParameterAt(parameter[0])
3003 |     y = surface.Domain(1).ParameterAt(parameter[1])
3004 |     return x, y
3005 | 
3006 | 
3007 | def SurfacePointCount(surface_id):
3008 |     """Returns the control point count of a surface
3009 |       surface_id = the surface's identifier
3010 |     Parameters:
3011 |       surface_id (guid): the surface object's identifier
3012 |     Returns:
3013 |       list(number, number): THe number of control points in UV direction. (U count, V count)
3014 |     Example:
3015 |       import rhinoscriptsyntax as rs
3016 |       obj = rs.GetObject("Select a surface")
3017 |       if rs.IsSurface(obj):
3018 |           count = rs.SurfacePointCount(obj)
3019 |           print("Point count in U direction: {}".format(count[0]))
3020 |           print("Point count in V direction: {}".format(count[1]))
3021 |     See Also:
3022 |       IsSurface
3023 |       SurfacePoints
3024 |     """
3025 |     surface = rhutil.coercesurface(surface_id, True)
3026 |     ns = surface.ToNurbsSurface()
3027 |     return ns.Points.CountU, ns.Points.CountV
3028 | 
3029 | 
3030 | def SurfacePoints(surface_id, return_all=True):
3031 |     """Returns the control points, or control vertices, of a surface object
3032 |     Parameters:
3033 |       surface_id (guid): the surface's identifier
3034 |       return_all (bool, optional): If True all surface edit points are returned. If False,
3035 |         the function will return surface edit points based on whether or not
3036 |         the surface is closed or periodic
3037 |     Returns:
3038 |       list(point, ...): the control points if successful
3039 |       None: on error
3040 |     Example:
3041 |       import rhinoscriptsyntax as rs
3042 |       def PrintControlPoints():
3043 |           surface = rs.GetObject("Select surface", rs.filter.surface)
3044 |           points = rs.SurfacePoints(surface)
3045 |           if points is None: return
3046 |           count = rs.SurfacePointCount(surface)
3047 |           i = 0
3048 |           for u in range(count[0]):
3049 |               for v in range(count[1]):
3050 |                   print("CV[{}".format(u, ",", v, "] = ", points[i]))
3051 |                   i += 1
3052 |       PrintControlPoints()
3053 |     See Also:
3054 |       IsSurface
3055 |       SurfacePointCount
3056 |     """
3057 |     surface = rhutil.coercesurface(surface_id, True)
3058 |     ns = surface.ToNurbsSurface()
3059 |     if ns is None: return scriptcontext.errorhandler()
3060 |     rc = []
3061 |     for u in range(ns.Points.CountU):
3062 |         for v in range(ns.Points.CountV):
3063 |             pt = ns.Points.GetControlPoint(u,v)
3064 |             rc.append(pt.Location)
3065 |     return rc
3066 | 
3067 | 
3068 | def SurfaceTorus(surface_id):
3069 |     """Returns the definition of a surface torus
3070 |     Parameters:
3071 |       surface_id (guid): the surface's identifier
3072 |     Returns:
3073 |       tuple(plane, number, number): containing the definition of the torus if successful
3074 |         [0]   the base plane of the torus
3075 |         [1]   the major radius of the torus
3076 |         [2]   the minor radius of the torus
3077 |       None: on error
3078 |     Example:
3079 |       import rhinoscriptsyntax as rs
3080 |       torus = rs.AddTorus(rs.WorldXYPlane(), 6, 2)
3081 |       if rs.IsTorus(torus):
3082 |           torus_def = rs.SurfaceTorus(torus)
3083 |           rs.AddTorus( torus_def[0], torus_def[1], torus_def[2] )
3084 |     See Also:
3085 |       
3086 |     """
3087 |     surface = rhutil.coercesurface(surface_id, True)
3088 |     rc, torus = surface.TryGetTorus()
3089 |     if rc: return torus.Plane, torus.MajorRadius, torus.MinorRadius
3090 | 
3091 | 
3092 | def SurfaceVolume(object_id):
3093 |     """Calculates volume of a closed surface or polysurface
3094 |     Parameters:
3095 |       object_id (guid): the surface's identifier
3096 |     Returns:
3097 |       list(number, tuple(X, Y, Z): volume data returned (Volume, Error bound) on success
3098 |       None: on error
3099 |     Example:
3100 |       import rhinoscriptsyntax as rs
3101 |       obj = rs.GetObject("Select a surface", rs.filter.polysurface)
3102 |       if rs.IsPolysurfaceClosed(obj):
3103 |           massprop = rs.SurfaceVolume(obj)
3104 |           if massprop:
3105 |               print("The polysurface volume is: {}".format(massprop[0]))
3106 |     See Also:
3107 |       SurfaceVolume
3108 |       SurfaceVolumeCentroid
3109 |       SurfaceVolumeMoments
3110 |     """
3111 |     vmp = __GetMassProperties(object_id, False)
3112 |     if vmp: return vmp.Volume, vmp.VolumeError
3113 | 
3114 | 
3115 | def SurfaceVolumeCentroid(object_id):
3116 |     """Calculates volume centroid of a closed surface or polysurface
3117 |     Parameters:
3118 |       object_id (guid): the surface's identifier
3119 |     Returns:
3120 |       list(point, tuple(X, Y, Z): volume data returned (Volume Centriod, Error bound) on success
3121 |       None: on error
3122 |     Example:
3123 |       import rhinoscriptsyntax as rs
3124 |       obj = rs.GetObject("Select a surface", rs.filter.polysurface)
3125 |       if rs.IsPolysurfaceClosed(obj):
3126 |           massprop= rs.SurfaceVolumeCentroid(obj)
3127 |           if massprop: rs.AddPoint( massprop[0] )
3128 |     See Also:
3129 |       SurfaceVolume
3130 |       SurfaceVolumeMoments
3131 |     """
3132 |     vmp = __GetMassProperties(object_id, False)
3133 |     if vmp: return vmp.Centroid, vmp.CentroidError
3134 | 
3135 | 
3136 | def SurfaceVolumeMoments(surface_id):
3137 |     """Calculates volume moments of inertia of a surface or polysurface object.
3138 |     For more information, see Rhino help for "Mass Properties calculation details"
3139 |     Parameters:
3140 |       surface_id (guid): the surface's identifier
3141 |     Returns:
3142 |       list(tuple(number, number,number), ...): of moments and error bounds in tuple(X, Y, Z) - see help topic
3143 |         Index   Description
3144 |         [0]     First Moments.
3145 |         [1]     The absolute (+/-) error bound for the First Moments.
3146 |         [2]     Second Moments.
3147 |         [3]     The absolute (+/-) error bound for the Second Moments.
3148 |         [4]     Product Moments.
3149 |         [5]     The absolute (+/-) error bound for the Product Moments.
3150 |         [6]     Area Moments of Inertia about the World Coordinate Axes.
3151 |         [7]     The absolute (+/-) error bound for the Area Moments of Inertia about World Coordinate Axes.
3152 |         [8]     Area Radii of Gyration about the World Coordinate Axes.
3153 |         [9]     The absolute (+/-) error bound for the Area Radii of Gyration about World Coordinate Axes.
3154 |         [10]    Area Moments of Inertia about the Centroid Coordinate Axes.
3155 |         [11]    The absolute (+/-) error bound for the Area Moments of Inertia about the Centroid Coordinate Axes.
3156 |         [12]    Area Radii of Gyration about the Centroid Coordinate Axes.
3157 |         [13]    The absolute (+/-) error bound for the Area Radii of Gyration about the Centroid Coordinate Axes.
3158 |       None: on error
3159 |     Example:
3160 |       import rhinoscriptsyntax as rs
3161 |       obj = rs.GetObject("Select a surface", rs.filter.polysurface)
3162 |       if rs.IsPolysurfaceClosed(obj):
3163 |           massprop = rs.SurfaceVolumeMoments(obj)
3164 |           if massprop:
3165 |               print("Volume Moments of Inertia about the World Coordinate Axes: {}".format(massprop[6]))
3166 |     See Also:
3167 |       SurfaceVolume
3168 |       SurfaceVolumeCentroid
3169 |     """
3170 |     return __AreaMomentsHelper(surface_id, False)
3171 | 
3172 | 
3173 | def SurfaceWeights(object_id):
3174 |     """Returns list of weight values assigned to the control points of a surface.
3175 |     The number of weights returned will be equal to the number of control points
3176 |     in the U and V directions.
3177 |     Parameters:
3178 |       object_id (guid): the surface's identifier
3179 |     Returns:
3180 |       list(number, ...): point weights.
3181 |       None: on error
3182 |     Example:
3183 |       import rhinoscriptsyntax as rs
3184 |       surf = rs.GetObject("Select a surface")
3185 |       if rs.IsSurface(surf):
3186 |           weights = rs.SurfaceWeights(surf)
3187 |           if weights:
3188 |               for w in weights:
3189 |                   print("Surface control point weight value:{}".format(w))
3190 |     See Also:
3191 |       IsSurface
3192 |       SurfacePointCount
3193 |       SurfacePoints
3194 |     """
3195 |     surface = rhutil.coercesurface(object_id, True)
3196 |     ns = surface.ToNurbsSurface()
3197 |     if ns is None: return scriptcontext.errorhandler()
3198 |     rc = []
3199 |     for u in range(ns.Points.CountU):
3200 |         for v in range(ns.Points.CountV):
3201 |             pt = ns.Points.GetControlPoint(u,v)
3202 |             rc.append(pt.Weight)
3203 |     return rc
3204 | 
3205 | 
3206 | def TrimBrep(object_id, cutter, tolerance=None):
3207 |     """Trims a surface using an oriented cutter
3208 |     Parameters:
3209 |       object_id (guid): surface or polysurface identifier
3210 |       cutter (guid|plane): surface, polysurface, or plane performing the trim
3211 |       tolerance (number, optional): trimming tolerance. If omitted, the document's absolute
3212 |         tolerance is used
3213 |     Returns:
3214 |       list(guid, ...): identifiers of retained components on success
3215 |     Example:
3216 |       import rhinoscriptsyntax as rs
3217 |       filter = rs.filter.surface + rs.filter.polysurface
3218 |       obj = rs.GetObject("Select surface or polysurface to trim", filter)
3219 |       if obj:
3220 |           cutter = rs.GetObject("Select cutting surface or polysurface", filter)
3221 |           if cutter:
3222 |               rs.TrimBrep(obj,cutter)
3223 |     See Also:
3224 |       TrimSurface
3225 |     """
3226 |     brep = rhutil.coercebrep(object_id, True)
3227 |     brep_cutter = rhutil.coercebrep(cutter, False)
3228 |     if brep_cutter: cutter = brep_cutter
3229 |     else: cutter = rhutil.coerceplane(cutter, True)
3230 |     if tolerance is None: tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3231 |     breps = brep.Trim(cutter, tolerance)
3232 |     rhid = rhutil.coerceguid(object_id, False)
3233 | 
3234 |     attrs = None
3235 |     if len(breps) > 1:
3236 |       rho = rhutil.coercerhinoobject(object_id, False)
3237 |       if rho: attrs = rho.Attributes
3238 | 
3239 |     if rhid:
3240 |         rc = []
3241 |         for i in range(len(breps)):
3242 |             if i==0:
3243 |                 scriptcontext.doc.Objects.Replace(rhid, breps[i])
3244 |                 rc.append(rhid)
3245 |             else:
3246 |                 rc.append(scriptcontext.doc.Objects.AddBrep(breps[i], attrs))
3247 |     else:
3248 |         rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in breps]
3249 |     scriptcontext.doc.Views.Redraw()
3250 |     return rc
3251 | 
3252 | 
3253 | def TrimSurface( surface_id, direction, interval, delete_input=False):
3254 |     """Remove portions of the surface outside of the specified interval
3255 |     Parameters:
3256 |       surface_id (guid): surface identifier
3257 |       direction (number, optional): 0(U), 1(V), or 2(U and V)
3258 |       interval (interval): sub section of the surface to keep.
3259 |         If both U and V then a list or tuple of 2 intervals
3260 |       delete_input (bool, optional): should the input surface be deleted
3261 |     Returns:
3262 |       guid: new surface identifier on success
3263 |     Example:
3264 |       import rhinoscriptsyntax as rs
3265 |       surface = rs.GetObject("Select surface to split", rs.filter.surface)
3266 |       if surface:
3267 |           domain_u = rs.SurfaceDomain(surface, 0)
3268 |           domain_u[0] = (domain_u[1] - domain_u[0]) * 0.25
3269 |           rs.TrimSurface( surface, 0, domain_u, True )
3270 |     See Also:
3271 |       
3272 |     """
3273 |     surface = rhutil.coercesurface(surface_id, True)
3274 |     u = surface.Domain(0)
3275 |     v = surface.Domain(1)
3276 |     if direction==0:
3277 |         u[0] = interval[0]
3278 |         u[1] = interval[1]
3279 |     elif direction==1:
3280 |         v[0] = interval[0]
3281 |         v[1] = interval[1]
3282 |     else:
3283 |         u[0] = interval[0][0]
3284 |         u[1] = interval[0][1]
3285 |         v[0] = interval[1][0]
3286 |         v[1] = interval[1][1]
3287 |     new_surface = surface.Trim(u,v)
3288 |     if new_surface:
3289 |         rc = scriptcontext.doc.Objects.AddSurface(new_surface)
3290 |         if delete_input: scriptcontext.doc.Objects.Delete(rhutil.coerceguid(surface_id), True)
3291 |         scriptcontext.doc.Views.Redraw()
3292 |         return rc
3293 | 
3294 | 
3295 | def UnrollSurface(surface_id, explode=False, following_geometry=None, absolute_tolerance=None, relative_tolerance=None):
3296 |     """Flattens a developable surface or polysurface
3297 |     Parameters:
3298 |       surface_id (guid): the surface's identifier
3299 |       explode (bool, optional): If True, the resulting surfaces ar not joined
3300 |       following_geometry ({guid, ...]): List of curves, dots, and points which
3301 |         should be unrolled with the surface
3302 |     Returns:
3303 |       list(guid, ...): of unrolled surface ids
3304 |       tuple((guid, ...),(guid, ...)): if following_geometry is not None, a tuple
3305 |         [1] is the list of unrolled surface ids
3306 |         [2] is the list of unrolled following geometry
3307 |     Example:
3308 |       import rhinoscriptsyntax as rs
3309 |       surface = rs.GetObject("Select surface or polysurface to unroll", rs.filter.surface + rs.filter.polysurface)
3310 |       if surface: rs.UnrollSurface(surface)
3311 |     See Also:
3312 |       
3313 |     """
3314 |     brep = rhutil.coercebrep(surface_id, True)
3315 |     unroll = Rhino.Geometry.Unroller(brep)
3316 |     unroll.ExplodeOutput = explode
3317 |     if relative_tolerance is None: relative_tolerance = scriptcontext.doc.ModelRelativeTolerance
3318 |     if absolute_tolerance is None: absolute_tolerance = scriptcontext.doc.ModelAbsoluteTolerance
3319 |     unroll.AbsoluteTolerance = absolute_tolerance
3320 |     unroll.RelativeTolerance = relative_tolerance
3321 |     if following_geometry:
3322 |         for id in following_geometry:
3323 |             geom = rhutil.coercegeometry(id)
3324 |             unroll.AddFollowingGeometry(geom)
3325 |     breps, curves, points, dots = unroll.PerformUnroll()
3326 |     if not breps: return None
3327 |     rc = [scriptcontext.doc.Objects.AddBrep(brep) for brep in breps]
3328 |     new_following = []
3329 |     for curve in curves:
3330 |         id = scriptcontext.doc.Objects.AddCurve(curve)
3331 |         new_following.append(id)
3332 |     for point in points:
3333 |         id = scriptcontext.doc.Objects.AddPoint(point)
3334 |         new_following.append(id)
3335 |     for dot in dots:
3336 |         id = scriptcontext.doc.Objects.AddTextDot(dot)
3337 |         new_following.append(id)
3338 |     scriptcontext.doc.Views.Redraw()
3339 |     if following_geometry: return rc, new_following
3340 |     return rc
3341 | 
3342 | 
3343 | def ChangeSurfaceDegree(object_id, degree):
3344 |   """Changes the degree of a surface object.  For more information see the Rhino help file for the ChangeDegree command.
3345 |   Parameters:
3346 |     object_id (guid): the object's identifier.
3347 |     degree ([number, number]) two integers, specifying the degrees for the U  V directions
3348 |   Returns:
3349 |     bool: True of False indicating success or failure.
3350 |     None: on failure.
3351 |   Example:
3352 |     
3353 |   See Also:
3354 |     IsSurface
3355 |   """
3356 |   object = rhutil.coercerhinoobject(object_id)
3357 |   if not object: return None
3358 |   obj_ref = Rhino.DocObjects.ObjRef(object)
3359 |   
3360 |   surface = obj_ref.Surface()
3361 |   if not surface: return None
3362 | 
3363 |   if not isinstance(surface, Rhino.Geometry.NurbsSurface):
3364 |     surface = surface.ToNurbsSurface() # could be a Surface or BrepFace
3365 | 
3366 |   max_nurbs_degree = 11
3367 |   if degree[0] < 1 or degree[0] > max_nurbs_degree or \
3368 |       degree[1] < 1 or degree[1] > max_nurbs_degree or \
3369 |       (surface.Degree(0) == degree[0] and surface.Degree(1) == degree[1]):
3370 |     return None
3371 | 
3372 |   r = False
3373 |   if surface.IncreaseDegreeU(degree[0]):
3374 |     if surface.IncreaseDegreeV(degree[1]):
3375 |       r = scriptcontext.doc.Objects.Replace(object_id, surface)
3376 |   return r
3377 | 
```
Page 7/8FirstPrevNextLast