#
tokens: 43873/50000 4/82 files (page 3/8)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 3 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/pointvector.py:
--------------------------------------------------------------------------------

```python
  1 | import math
  2 | 
  3 | import Rhino
  4 | 
  5 | import scriptcontext
  6 | 
  7 | from rhinoscript import utility as rhutil
  8 | 
  9 | 
 10 | def IsVectorParallelTo(vector1, vector2):
 11 |     """Compares two vectors to see if they are parallel
 12 |     Parameters:
 13 |       vector1, vector2 (vector): the vectors to compare
 14 |     Returns:
 15 |     number: the value represents
 16 |             -1 = the vectors are anti-parallel
 17 |              0 = the vectors are not parallel
 18 |              1 = the vectors are parallel
 19 |     Example:
 20 |       import rhinoscriptsyntax as rs
 21 |       vector1 = (1,0,0)
 22 |       vector2 = (0,1,0)
 23 |       print(rs.IsVectorParallelTo( vector1, vector2 ))
 24 |     See Also:
 25 |       IsVectorPerpendicularTo
 26 |       IsVectorTiny
 27 |       IsVectorZero
 28 |     """
 29 |     vector1 = rhutil.coerce3dvector(vector1, True)
 30 |     vector2 = rhutil.coerce3dvector(vector2, True)
 31 |     return vector1.IsParallelTo(vector2)
 32 | 
 33 | 
 34 | def IsVectorPerpendicularTo(vector1, vector2):
 35 |     """Compares two vectors to see if they are perpendicular
 36 |     Parameters:
 37 |       vector1, vector2 (vector): the vectors to compare
 38 |     Returns:
 39 |       bool: True if vectors are perpendicular, otherwise False
 40 |     Example:
 41 |       import rhinoscriptsyntax as rs
 42 |       vector1 = (1,0,0)
 43 |       vector2 = (0,1,0)
 44 |       print(rs.IsVectorPerpendicularTo( vector1, vector2 ))
 45 |     See Also:
 46 |       IsVectorParallelTo
 47 |       IsVectorTiny
 48 |       IsVectorZero
 49 |     """
 50 |     vector1 = rhutil.coerce3dvector(vector1, True)
 51 |     vector2 = rhutil.coerce3dvector(vector2, True)
 52 |     return vector1.IsPerpendicularTo(vector2)
 53 | 
 54 | 
 55 | def IsVectorTiny(vector):
 56 |     """Verifies that a vector is very short. The X,Y,Z elements are <= 1.0e-12
 57 |     Parameters:
 58 |       vector (vector): the vector to check
 59 |     Returns:
 60 |       bool: True if the vector is tiny, otherwise False
 61 |     Example:
 62 |       import rhinoscriptsyntax as rs
 63 |       pt1 = rs.GetPoint("First point")
 64 |       pt2 = rs.GetPoint("Next point")
 65 |       vector = pt2 - pt1
 66 |       if rs.IsVectorTiny(vector):
 67 |           print("The vector is tiny.")
 68 |       else:
 69 |           print("The vector is not tiny.")
 70 |     See Also:
 71 |       IsVectorZero
 72 |       VectorCreate
 73 |     """
 74 |     vector = rhutil.coerce3dvector(vector, True)
 75 |     return vector.IsTiny( 1.0e-12 )
 76 | 
 77 | 
 78 | def IsVectorZero(vector):
 79 |     """Verifies that a vector is zero, or tiny. The X,Y,Z elements are equal to 0.0
 80 |     Parameters:
 81 |       vector (vector): the vector to check
 82 |     Returns:
 83 |       bool: True if the vector is zero, otherwise False
 84 |     Example:
 85 |       import rhinoscriptsyntax as rs
 86 |       pt1 = rs.GetPoint("First point")
 87 |       pt2 = rs.GetPoint("Next point")
 88 |       vector = pt2 - pt1
 89 |       if rs.IsVectorZero(vector):
 90 |           print("The vector is zero.")
 91 |       else:
 92 |           print("The vector is not zero.")
 93 |     See Also:
 94 |       IsVectorTiny
 95 |       VectorCreate
 96 |     """
 97 |     vector = rhutil.coerce3dvector(vector, True)
 98 |     return vector.IsZero
 99 | 
100 | 
101 | def PointAdd(point1, point2):
102 |     """Adds a 3D point or a 3D vector to a 3D point
103 |     Parameters:
104 |       point1, point2 (point): the points to add
105 |     Returns:
106 |       point: the resulting 3D point if successful
107 |     Example:
108 |       import rhinoscriptsyntax as rs
109 |       point1 = (1,1,1)
110 |       point2 = (2,2,2)
111 |       point = rs.PointAdd(point1, point2)
112 |       print(point)
113 |     See Also:
114 |       PointCompare
115 |       PointDivide
116 |       PointScale
117 |       PointSubtract
118 |       PointTransform
119 |     """
120 |     point1 = rhutil.coerce3dpoint(point1, True)
121 |     point2 = rhutil.coerce3dpoint(point2, True)
122 |     return point1+point2
123 | 
124 | 
125 | def PointArrayClosestPoint(points, test_point):
126 |     """Finds the point in a list of 3D points that is closest to a test point
127 |     Parameters:
128 |       points ([point, ...]): list of points
129 |       test_point (point): the point to compare against
130 |     Returns:
131 |       number: index of the element in the point list that is closest to the test point
132 |     Example:
133 |       import rhinoscriptsyntax as rs
134 |       cloud = rs.GetObject("Select point cloud")
135 |       if cloud:
136 |           point = rs.GetPoint("Point to test")
137 |           if point:
138 |               cloud = rs.PointCloudPoints(cloud)
139 |               index = rs.PointArrayClosestPoint(cloud, point)
140 |               if index is not None:
141 |                   point_id = rs.AddPoint(cloud[index])
142 |                   rs.SelectObject( point_id )
143 |     See Also:
144 |       CurveClosestPoint
145 |       SurfaceClosestPoint
146 |     """
147 |     points = rhutil.coerce3dpointlist(points, True)
148 |     test_point = rhutil.coerce3dpoint(test_point, True)
149 |     index = Rhino.Collections.Point3dList.ClosestIndexInList(points, test_point)
150 |     if index>=0: return index
151 | 
152 | 
153 | def PointArrayTransform(points, xform):
154 |     """Transforms a list of 3D points
155 |     Parameters:
156 |       points ([point, ...]): list of 3D points
157 |       xform (transform): transformation to apply
158 |     Returns:
159 |       list(point, ...): transformed points on success
160 |     Example:
161 |       import rhinoscriptsyntax as rs
162 |       obj = rs.GetObject("Select object")
163 |       points = rs.BoundingBox(obj)
164 |       xform = rs.XformRotation2(45.0, (0,0,1), (0,0,0))
165 |       points = rs.PointArrayTransform(points, xform)
166 |       rs.AddPoints(points)
167 |     See Also:
168 |       PointArrayClosestPoint
169 |     """
170 |     points = rhutil.coerce3dpointlist(points, True)
171 |     xform = rhutil.coercexform(xform, True)
172 |     return [xform*point for point in points]
173 | 
174 | 
175 | def PointClosestObject(point, object_ids):
176 |     """Finds the object that is closest to a test point
177 |     Parameters:
178 |       point (point): point to test
179 |       object_id ([guid, ...]): identifiers of one or more objects
180 |     Returns:
181 |       list(guid, point): closest [0] object_id and [1] point on object on success
182 |       None: on failure
183 |     Example:
184 |       import rhinoscriptsyntax as rs
185 |       objs = rs.GetObjects("Select target objects for closest point", 63)
186 |       if objs:
187 |           point = rs.GetPoint("Test point")
188 |           if point:
189 |               results = rs.PointClosestObject(point, objs)
190 |               if results:
191 |                   print("Object id:{}".format(results[0]))
192 |                   rs.AddPoint( results[1] )
193 |     See Also:
194 |       CurveClosestObject
195 |     """
196 |     object_ids = rhutil.coerceguidlist(object_ids)
197 |     point = rhutil.coerce3dpoint(point, True)
198 |     closest = None
199 |     for id in object_ids:
200 |         geom = rhutil.coercegeometry(id, True)
201 |         point_geometry = geom
202 |         if isinstance(point_geometry, Rhino.Geometry.Point):
203 |             distance = point.DistanceTo( point_geometry.Location )
204 |             if closest is None or distance<closest[0]:
205 |                 closest = distance, id, point_geometry.Location
206 |             continue
207 |         point_cloud = geom
208 |         if isinstance(point_cloud, Rhino.Geometry.PointCloud):
209 |             index = point_cloud.ClosestPoint(point)
210 |             if index>=0:
211 |                 distance = point.DistanceTo( point_cloud[index].Location )
212 |                 if closest is None or distance<closest[0]:
213 |                     closest = distance, id, point_cloud[index].Location
214 |             continue
215 |         curve = geom
216 |         if isinstance(curve, Rhino.Geometry.Curve):
217 |             rc, t = curve.ClosestPoint(point)
218 |             if rc:
219 |                 distance = point.DistanceTo( curve.PointAt(t) )
220 |                 if closest is None or distance<closest[0]:
221 |                     closest = distance, id, curve.PointAt(t)
222 |             continue
223 |         brep = geom
224 |         if isinstance(brep, Rhino.Geometry.Brep):
225 |             brep_closest = brep.ClosestPoint(point)
226 |             distance = point.DistanceTo( brep_closest )
227 |             if closest is None or distance<closest[0]:
228 |                 closest = distance, id, brep_closest
229 |             continue
230 |         mesh = geom
231 |         if isinstance(mesh, Rhino.Geometry.Mesh):
232 |             mesh_closest = mesh.ClosestPoint(point)
233 |             distance = point.DistanceTo( mesh_closest )
234 |             if closest is None or distance<closest[0]:
235 |                 closest = distance, id, mesh_closest
236 |             continue
237 |     if closest: return closest[1], closest[2]
238 | 
239 | 
240 | def PointCompare(point1, point2, tolerance=None):
241 |     """Compares two 3D points
242 |     Parameters:
243 |       point1, point2 (point): the points to compare
244 |       tolerance (number, optional): tolerance to use for comparison. If omitted,
245 |                                     Rhino's internal zero tolerance is used
246 |     Returns:
247 |       bool: True or False
248 |     Example:
249 |       import rhinoscriptsyntax as rs
250 |       point1 = (1,1,1)
251 |       point2 = (2,2,2)
252 |       print(rs.PointCompare(point1, point2))
253 |     See Also:
254 |       PointAdd
255 |       PointDivide
256 |       PointScale
257 |       PointSubtract
258 |       PointTransform
259 |     """
260 |     point1 = rhutil.coerce3dpoint(point1, True)
261 |     point2 = rhutil.coerce3dpoint(point2, True)
262 |     if tolerance is None: tolerance = Rhino.RhinoMath.ZeroTolerance
263 |     vector = point2-point1
264 |     return vector.IsTiny(tolerance)
265 | 
266 | 
267 | def PointDivide(point, divide):
268 |     """Divides a 3D point by a value
269 |     Parameters:
270 |       point (point): the point to divide
271 |       divide (number): a non-zero value to divide
272 |     Returns:
273 |       point: resulting point
274 |     Example:
275 |       import rhinoscriptsyntax as rs
276 |       point = rs.PointDivide([5,5,0], 5)
277 |       print(point)
278 |     See Also:
279 |       PointAdd
280 |       PointCompare
281 |       PointScale
282 |       PointSubtract
283 |       PointTransform
284 |     """
285 |     point = rhutil.coerce3dpoint(point, True)
286 |     return point/divide
287 | 
288 | 
289 | def PointsAreCoplanar(points, tolerance=1.0e-12):
290 |     """Verifies that a list of 3D points are coplanar
291 |     Parameters:
292 |       points ([point, ...]): 3D points to test
293 |       tolerance (number, optional): tolerance to use when verifying
294 |     Returns:
295 |       bool: True or False
296 |     Example:
297 |       import rhinoscriptsyntax as rs
298 |       def SurfacesAreCoplanar(srf1, srf2):
299 |           if( not rs.IsSurface(srf1) or not rs.IsSurface(srf2) ): return False
300 |           if( not rs.IsSurfacePlanar(srf1) or not rs.IsSurfacePlanar(srf2) ): return False
301 |           pts1 = rs.SurfacePoints(srf1)
302 |           pts2 = rs.SurfacePoints(srf2)
303 |           if( pts1==None or pts2==None ): return False
304 |           pts1.extend(pts2)
305 |           return rs.PointsAreCoplanar(pts1)
306 |        
307 |       x = rs.GetObject( "First surface to test", rs.filter.surface)
308 |       y = rs.GetObject( "Second surface to test", rs.filter.surface)
309 |       print(SurfacesAreCoplanar(x, y))
310 |     See Also:
311 |       IsPoint
312 |       IsPointCloud
313 |       PointCoordinates
314 |     """
315 |     points = rhutil.coerce3dpointlist(points, True)
316 |     return Rhino.Geometry.Point3d.ArePointsCoplanar(points, tolerance)
317 | 
318 | 
319 | def PointScale(point, scale):
320 |     """Scales a 3D point by a value
321 |     Parameters:
322 |       point (point): the point to divide
323 |       scale (number): scale factor to apply
324 |     Returns:
325 |       point: resulting point on success
326 |     Example:
327 |       import rhinoscriptsyntax as rs
328 |       point = rs.PointScale([1,0,0], 5)
329 |       print(point)
330 |     See Also:
331 |       PointAdd
332 |       PointCompare
333 |       PointDivide
334 |       PointSubtract
335 |       PointTransform
336 |     """
337 |     point = rhutil.coerce3dpoint(point, True)
338 |     return point*scale
339 | 
340 | 
341 | def PointSubtract(point1, point2):
342 |     """Subtracts a 3D point or a 3D vector from a 3D point
343 |     Parameters:
344 |       point1, point2 (point): the points to subtract
345 |     Returns:
346 |       point: the resulting 3D point if successful
347 |     Example:
348 |       import rhinoscriptsyntax as rs
349 |       point1 = (1,1,1)
350 |       point2 = (2,2,2)
351 |       point = rs.PointSubtract(point1, point2)
352 |       print(point)
353 |     See Also:
354 |       PointAdd
355 |       PointCompare
356 |       PointDivide
357 |       PointScale
358 |       PointTransform
359 |     """
360 |     point1 = rhutil.coerce3dpoint(point1, True)
361 |     point2 = rhutil.coerce3dpoint(point2, True)
362 |     v = point1-point2
363 |     return Rhino.Geometry.Point3d(v)
364 | 
365 |   
366 | def PointTransform(point, xform):
367 |     """Transforms a 3D point
368 |     Parameters:
369 |       point (point): the point to transform
370 |       xform (transform): a valid 4x4 transformation matrix
371 |     Returns:
372 |       point: transformed point on success
373 |     Example:
374 |       # Translate (move) objects by (10,10,0)
375 |       import rhinoscriptsyntax as rs
376 |       point = 5,5,0
377 |       matrix = rs.XformTranslation((10,10,0))
378 |       result = rs.PointTransform(point, matrix)
379 |       print(result)
380 |     See Also:
381 |       PointAdd
382 |       PointCompare
383 |       PointDivide
384 |       PointScale
385 |       PointSubtract
386 |     """
387 |     point = rhutil.coerce3dpoint(point, True)
388 |     xform = rhutil.coercexform(xform, True)
389 |     return xform*point
390 | 
391 | 
392 | def ProjectPointToMesh(points, mesh_ids, direction):
393 |     """Projects one or more points onto one or more meshes
394 |     Parameters:
395 |       points ([point, ...]): one or more 3D points
396 |       mesh_ids ([guid, ...]): identifiers of one or more meshes
397 |       direction (vector): direction vector to project the points
398 |     Returns:
399 |      list(point, ...): projected points on success
400 |     Example:
401 |       import rhinoscriptsyntax as rs
402 |       mesh = rs.GetObject("Select mesh to project onto", rs.filter.mesh)
403 |       objects = rs.GetObjects("Select points to project", rs.filter.point)
404 |       points = [rs.PointCoordinates(obj) for obj in objects]
405 |       # project down...
406 |       results = rs.ProjectPointToMesh(points, mesh, (0,0,-1))
407 |       rs.AddPoints( results )
408 |     See Also:
409 |       ProjectCurveToMesh
410 |       ProjectCurveToSurface
411 |       ProjectPointToSurface
412 |     """
413 |     pts = rhutil.coerce3dpointlist(points, False)
414 |     if pts is None:
415 |         pts = [rhutil.coerce3dpoint(points, True)]
416 |     direction = rhutil.coerce3dvector(direction, True)
417 |     id = rhutil.coerceguid(mesh_ids, False)
418 |     if id: mesh_ids = [id]
419 |     meshes = [rhutil.coercemesh(id, True) for id in mesh_ids]
420 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
421 |     rc = Rhino.Geometry.Intersect.Intersection.ProjectPointsToMeshes(meshes, pts, direction, tolerance)
422 |     return rc
423 | 
424 | 
425 | def ProjectPointToSurface(points, surface_ids, direction):
426 |     """Projects one or more points onto one or more surfaces or polysurfaces
427 |     Parameters:
428 |       points ([point, ...]): one or more 3D points
429 |       surface_ids ([guid, ...]): identifiers of one or more surfaces/polysurfaces
430 |       direction (vector): direction vector to project the points
431 |     Returns:
432 |      list(point, ...): projected points on success
433 |     Example:
434 |       import rhinoscriptsyntax as rs
435 |       surface = rs.GetObject("Select surface to project onto", rs.filter.surface)
436 |       objects = rs.GetObjects("Select points to project", rs.filter.point)
437 |       points = [rs.PointCoordinates(obj) for obj in objects]
438 |       # Project down...
439 |       results = rs.ProjectPointToSurface(points, surface, (0,0,-1))
440 |       rs.AddPoints(results)
441 |     See Also:
442 |       ProjectCurveToMesh
443 |       ProjectCurveToSurface
444 |       ProjectPointToMesh
445 |     """
446 |     pts = rhutil.coerce3dpointlist(points)
447 |     if pts is None:
448 |         pts = [rhutil.coerce3dpoint(points, True)]
449 |     direction = rhutil.coerce3dvector(direction, True)
450 |     id = rhutil.coerceguid(surface_ids, False)
451 |     if id: surface_ids = [id]
452 |     breps = [rhutil.coercebrep(id, True) for id in surface_ids]
453 |     tolerance = scriptcontext.doc.ModelAbsoluteTolerance
454 |     return Rhino.Geometry.Intersect.Intersection.ProjectPointsToBreps(breps, pts, direction, tolerance)
455 | 
456 | 
457 | def PullPoints(object_id, points):
458 |     """Pulls an array of points to a surface or mesh object. For more
459 |     information, see the Rhino help file Pull command
460 |     Parameters:
461 |       object_id (guid): the identifier of the surface or mesh object that pulls
462 |       points ([point, ...]): list of 3D points
463 |     Returns:
464 |       list(point, ...): 3D points pulled onto surface or mesh
465 |     Example:
466 |       import rhinoscriptsyntax as rs
467 |       surface = rs.GetObject("Select surface that pulls", rs.filter.surface)
468 |       objects = rs.GetObjects("Select points to pull", rs.filter.point)
469 |       points = [rs.PointCoordinates(obj) for obj in objects]
470 |       results = rs.PullPoints( surface, points )
471 |       rs.AddPoints( results )
472 |     See Also:
473 |       PullCurve
474 |     """
475 |     id = rhutil.coerceguid(object_id, True)
476 |     points = rhutil.coerce3dpointlist(points, True)
477 |     mesh = rhutil.coercemesh(id, False)
478 |     if mesh:
479 |         points = mesh.PullPointsToMesh(points)
480 |         return list(points)
481 |     brep = rhutil.coercebrep(id, False)
482 |     if brep and brep.Faces.Count==1:
483 |         tolerance = scriptcontext.doc.ModelAbsoluteTolerance
484 |         points = brep.Faces[0].PullPointsToFace(points, tolerance)
485 |         return list(points)
486 |     return []
487 | 
488 | 
489 | def VectorAdd(vector1, vector2):
490 |     """Adds two 3D vectors
491 |     Parameters:
492 |       vector1, vector2 (vector): the vectors to add
493 |     Returns:
494 |       vector: the resulting 3D vector if successful
495 |     Example:
496 |       import rhinoscriptsyntax as rs
497 |       vector1 = (1,0,0)
498 |       vector2 = (0,1,0)
499 |       vector = rs.VectorAdd(vector1, vector2)
500 |       print(vector)
501 |     See Also:
502 |       VectorCreate
503 |       VectorScale
504 |       VectorSubtract
505 |     """
506 |     vector1 = rhutil.coerce3dvector(vector1, True)
507 |     vector2 = rhutil.coerce3dvector(vector2, True)
508 |     return vector1+vector2
509 | 
510 | 
511 | def VectorAngle(vector1, vector2):
512 |     """Returns the angle, in degrees, between two 3-D vectors
513 |     Parameters:
514 |       vector1 (vector): The first 3-D vector.
515 |       vector2 (vector): The second 3-D vector.
516 |     Returns:
517 |       number: The angle in degrees if successful
518 |       None: if not successful
519 |     Example:
520 |       import rhinoscriptsyntax as rs
521 |       s0 = rs.GetObject("Surface 0", rs.filter.surface)
522 |       s1 = rs.GetObject("Surface 1", rs.filter.surface)
523 |       du0 = rs.SurfaceDomain(s0, 0)
524 |       dv0 = rs.SurfaceDomain(s0, 1)
525 |       du1 = rs.SurfaceDomain(s1, 0)
526 |       dv1 = rs.SurfaceDomain(s1, 1)
527 |       n0 = rs.SurfaceNormal(s0, (du0[0], dv0[0]))
528 |       n1 = rs.SurfaceNormal(s1, (du1[0], dv1[0]))
529 |       print(rs.VectorAngle(n0, n1))
530 |       print(rs.VectorAngle(n0, rs.VectorReverse(n1)))
531 |     See Also:
532 |       Angle
533 |       Angle2
534 |     """
535 |     vector1 = rhutil.coerce3dvector(vector1, True)
536 |     vector2 = rhutil.coerce3dvector(vector2, True)
537 |     vector1 = Rhino.Geometry.Vector3d(vector1.X, vector1.Y, vector1.Z)
538 |     vector2 = Rhino.Geometry.Vector3d(vector2.X, vector2.Y, vector2.Z)
539 |     if not vector1.Unitize() or not vector2.Unitize():
540 |         raise ValueError("unable to unitize vector")
541 |     dot = vector1 * vector2
542 |     dot = rhutil.clamp(-1,1,dot)
543 |     radians = math.acos(dot)
544 |     return math.degrees(radians)
545 | 
546 | 
547 | def VectorCompare(vector1, vector2):
548 |     """Compares two 3D vectors
549 |     Parameters:
550 |       vector1, vector2 (vector): the two vectors to compare
551 |     Returns:
552 |       number: result of comparing the vectors.
553 |               -1 if vector1 is less than vector2
554 |               0 if vector1 is equal to vector2
555 |               1 if vector1 is greater than vector2
556 |     Example:
557 |       import rhinoscriptsyntax as rs
558 |       vector1 = (1,0,0)
559 |       vector2 = (0,1,0)
560 |       rc = rs.VectorCompare(vector1 , vector2)
561 |       print(rc)
562 |     See Also:
563 |       IsVectorTiny
564 |       IsVectorZero
565 |       VectorCreate
566 |     """
567 |     vector1 = rhutil.coerce3dvector(vector1, True)
568 |     vector2 = rhutil.coerce3dvector(vector2, True)
569 |     return vector1.CompareTo(vector2)
570 | 
571 | 
572 | def VectorCreate(to_point, from_point):
573 |     """Creates a vector from two 3D points
574 |     Parameters:
575 |       to_point, from_point (point): the points defining the vector
576 |     Returns:
577 |       vector: the resulting vector if successful
578 |     Example:
579 |       import rhinoscriptsyntax as rs
580 |       point1 = rs.GetPoint("First point")
581 |       point2 = rs.GetPoint("Next point")
582 |       vector = rs.VectorCreate(point2, point1)
583 |       print(vector)
584 |     See Also:
585 |       IsVectorTiny
586 |       IsVectorZero
587 |       VectorCompare
588 |       VectorUnitize
589 |     """
590 |     to_point = rhutil.coerce3dpoint(to_point, True)
591 |     from_point = rhutil.coerce3dpoint(from_point, True)
592 |     return to_point-from_point
593 | 
594 | 
595 | def VectorCrossProduct(vector1, vector2):
596 |     """Calculates the cross product of two 3D vectors
597 |     Parameters:
598 |       vector1, vector2 (vector): the vectors to perform cross product on
599 |     Returns:
600 |       vector: the resulting cross product direction if successful
601 |     Example:
602 |       import rhinoscriptsyntax as rs
603 |       vector1 = (1,0,0)
604 |       vector2 = (0,1,0)
605 |       vector = rs.VectorCrossProduct(vector1, vector2)
606 |       print(vector)
607 |     See Also:
608 |       VectorDotProduct
609 |       VectorUnitize
610 |     """
611 |     vector1 = rhutil.coerce3dvector(vector1, True)
612 |     vector2 = rhutil.coerce3dvector(vector2, True)
613 |     return Rhino.Geometry.Vector3d.CrossProduct( vector1, vector2 )
614 | 
615 | 
616 | def VectorDivide(vector, divide):
617 |     """Divides a 3D vector by a value
618 |     Parameters:
619 |       vector (vector): the vector to divide
620 |       divide (number): a non-zero value to divide
621 |     Returns:
622 |       vector: resulting vector on success
623 |     Example:
624 |       import rhinoscriptsyntax as rs
625 |       vector = rs.VectorDivide((5,5,0), 5)
626 |       print(vector)
627 |     See Also:
628 |       VectorAdd
629 |       VectorCreate
630 |       VectorSubtract
631 |     """
632 |     vector = rhutil.coerce3dvector(vector, True)
633 |     return vector/divide
634 | 
635 | 
636 | def VectorDotProduct(vector1, vector2):
637 |     """Calculates the dot product of two 3D vectors
638 |     Parameters:
639 |       vector1, vector2 (vector): the vectors to perform the dot product on
640 |     Returns:
641 |       vector: the resulting dot product if successful
642 |     Example:
643 |       import rhinoscriptsyntax as rs
644 |       vector1 = [1,0,0]
645 |       vector2 = [0,1,0]
646 |       dblDotProduct = rs.VectorDotProduct(vector1, vector2)
647 |       print(dblDotProduct)
648 |     See Also:
649 |       VectorCrossProduct
650 |       VectorUnitize
651 |     """
652 |     vector1 = rhutil.coerce3dvector(vector1, True)
653 |     vector2 = rhutil.coerce3dvector(vector2, True)
654 |     return vector1*vector2
655 | 
656 | 
657 | def VectorLength(vector):
658 |     """Returns the length of a 3D vector
659 |     Parameters:
660 |       vector (vector):  The 3-D vector.
661 |     Returns:
662 |       number: The length of the vector if successful, otherwise None
663 |     Example:
664 |       import rhinoscriptsyntax as rs
665 |       point1 = rs.GetPoint("First point")
666 |       point2 = rs.GetPoint("Next point")
667 |       vector = rs.VectorCreate(point1, point2)
668 |       print(rs.VectorLength(vector))
669 |     See Also:
670 |       VectorAdd
671 |       VectorCreate
672 |       VectorSubtract
673 |       VectorUnitize
674 |     """
675 |     vector = rhutil.coerce3dvector(vector, True)
676 |     return vector.Length
677 | 
678 | 
679 | def VectorMultiply(vector1, vector2):
680 |     """Multiplies two 3D vectors
681 |     Parameters:
682 |       vector1, vector2 (vector): the vectors to multiply
683 |     Returns:
684 |       vector: the resulting inner (dot) product if successful
685 |     Example:
686 |       import rhinoscriptsyntax as rs
687 |       product = rs.VectorMultiply( [2,2,2], [3,3,3] )
688 |       print(product)
689 |     See Also:
690 |       VectorAdd
691 |       VectorCreate
692 |       VectorSubtract
693 |     """
694 |     return VectorDotProduct(vector1, vector2)
695 | 
696 | 
697 | def VectorReverse(vector):
698 |     """Reverses the direction of a 3D vector
699 |     Parameters:
700 |       vector (vector): the vector to reverse
701 |     Returns:
702 |       vector: reversed vector on success
703 |     Example:
704 |       import rhinoscriptsyntax as rs
705 |       vector = rs.VectorReverse([1,0,0])
706 |       print(vector)
707 |     See Also:
708 |       VectorCreate
709 |       VectorUnitize
710 |     """
711 |     vector = rhutil.coerce3dvector(vector, True)
712 |     rc = Rhino.Geometry.Vector3d(vector.X, vector.Y, vector.Z)
713 |     rc.Reverse()
714 |     return rc
715 | 
716 | 
717 | def VectorRotate(vector, angle_degrees, axis):
718 |     """Rotates a 3D vector
719 |     Parameters:
720 |       vector (vector): the vector to rotate
721 |       angle_degrees (number): rotation angle
722 |       axis (vector): axis of rotation
723 |     Returns:
724 |       vector: rotated vector on success
725 |     Example:
726 |       import rhinoscriptsyntax as rs
727 |       vector = rs.VectorRotate([1,0,0], 90.0, [0,0,1])
728 |       print(vector)
729 |     See Also:
730 |       VectorCreate
731 |       VectorScale
732 |     """
733 |     vector = rhutil.coerce3dvector(vector, True)
734 |     axis = rhutil.coerce3dvector(axis, True)
735 |     angle_radians = Rhino.RhinoMath.ToRadians(angle_degrees)
736 |     rc = Rhino.Geometry.Vector3d(vector.X, vector.Y, vector.Z)
737 |     if rc.Rotate(angle_radians, axis): return rc
738 | 
739 | 
740 | def VectorScale(vector, scale):
741 |     """Scales a 3-D vector
742 |     Parameters:
743 |       vector (vector): the vector to scale
744 |       scale (number): scale factor to apply
745 |     Returns:
746 |       vector: resulting vector on success
747 |     Example:
748 |       import rhinoscriptsyntax as rs
749 |       vector = rs.VectorScale([1,0,0], 5)
750 |       print(vector)
751 |     See Also:
752 |       VectorAdd
753 |       VectorCreate
754 |       VectorSubtract
755 |     """
756 |     vector = rhutil.coerce3dvector(vector, True)
757 |     return vector*scale
758 | 
759 | 
760 | def VectorSubtract(vector1, vector2):
761 |     """Subtracts two 3D vectors
762 |     Parameters:
763 |       vector1 (vector): the vector to subtract from
764 |       vector2 (vector): the vector to subtract
765 |     Returns:
766 |       vector: the resulting 3D vector
767 |     Example:
768 |       import rhinoscriptsyntax as rs
769 |       vector1 = [1,0,0]
770 |       vector2 = [0,1,0]
771 |       vector = rs.VectorSubtract(vector1, vector2)
772 |       print(vector)
773 |     See Also:
774 |       VectorAdd
775 |       VectorCreate
776 |       VectorScale
777 |     """
778 |     vector1 = rhutil.coerce3dvector(vector1, True)
779 |     vector2 = rhutil.coerce3dvector(vector2, True)
780 |     return vector1-vector2
781 | 
782 | 
783 | def VectorTransform(vector, xform):
784 |     """Transforms a 3D vector
785 |     Parameters:
786 |       vector (vector): the vector to transform
787 |       xform (transform): a valid 4x4 transformation matrix
788 |     Returns:
789 |       vector: transformed vector on success
790 |     Example:
791 |       import rhinoscriptsyntax as rs
792 |       vector = (1,0,0) #world x-axis
793 |       xform = rs.XformRotation2(90.0, (0,0,1), (0,0,0))
794 |       vector = rs.VectorTransform(vector, xform)
795 |       print(vector)
796 |     See Also:
797 |       IsVectorZero
798 |       VectorCreate
799 |       VectorUnitize
800 |     """
801 |     vector = rhutil.coerce3dvector(vector, True)
802 |     xform = rhutil.coercexform(xform, True)
803 |     return xform*vector
804 | 
805 | 
806 | def VectorUnitize(vector):
807 |     """Unitizes, or normalizes a 3D vector. Note, zero vectors cannot be unitized
808 |     Parameters:
809 |       vector (vector): the vector to unitize
810 |     Returns:
811 |       vector: unitized vector on success
812 |       None: on error
813 |     Example:
814 |       import rhinoscriptsyntax as rs
815 |       vector = rs.VectorUnitize( [1.5,-4.1,3.6] )
816 |       print(vector)
817 |     See Also:
818 |       IsVectorZero
819 |       VectorCreate
820 |     """
821 |     vector = rhutil.coerce3dvector(vector, True)
822 |     rc = Rhino.Geometry.Vector3d(vector.X, vector.Y, vector.Z)
823 |     if rc.Unitize(): return rc
824 | 
825 | 
826 | def PointArrayBoundingBox(points, view_or_plane=None, in_world_coords=True):
827 |     """Returns either a world axis-aligned or a construction plane axis-aligned 
828 |     bounding box of an array of 3-D point locations.
829 |     Parameters:
830 |       points ([point, ...]): A list of 3-D points
831 |       view_or_plane (str|plane, optional): Title or id of the view that contains the
832 |           construction plane to which the bounding box should be aligned -or-
833 |           user defined plane. If omitted, a world axis-aligned bounding box
834 |           will be calculated
835 |       in_world_coords (bool, optional): return the bounding box as world coordinates or
836 |           construction plane coordinates. Note, this option does not apply to
837 |           world axis-aligned bounding boxes.
838 |     Returns:
839 |       list(point, ....): Eight points that define the bounding box. Points returned in counter-
840 |       clockwise order starting with the bottom rectangle of the box.
841 |       None: on error
842 |     Example:
843 |       
844 |     See Also:
845 |       BoundingBox
846 |     """
847 |     points = rhutil.coerce3dpointlist(points)
848 |     if not points:
849 |       return None
850 |     bbox = Rhino.Geometry.BoundingBox(points)
851 | 
852 |     xform = None
853 |     plane = rhutil.coerceplane(view_or_plane)
854 |     if plane is None and view_or_plane:
855 |         view = view_or_plane
856 |         modelviews = scriptcontext.doc.Views.GetStandardRhinoViews()
857 |         for item in modelviews:
858 |             viewport = item.MainViewport
859 |             if type(view) is str and viewport.Name==view:
860 |                 plane = viewport.ConstructionPlane()
861 |                 break
862 |             elif type(view) is System.Guid and viewport.Id==view:
863 |                 plane = viewport.ConstructionPlane()
864 |                 break
865 |         if plane is None: return scriptcontext.errorhandler()
866 |     if plane:
867 |         xform = Rhino.Geometry.Transform.ChangeBasis(Rhino.Geometry.Plane.WorldXY, plane)
868 |         bbox = xform.TransformBoundingBox(bbox)
869 |     if not bbox.IsValid: return scriptcontext.errorhandler()
870 | 
871 |     corners = list(bbox.GetCorners())
872 |     if in_world_coords and plane is not None:
873 |         plane_to_world = Rhino.Geometry.Transform.ChangeBasis(plane, Rhino.Geometry.Plane.WorldXY)
874 |         for pt in corners: pt.Transform(plane_to_world)
875 |     return corners
876 | 
```

--------------------------------------------------------------------------------
/rhino_mcp_server/static/layer.py:
--------------------------------------------------------------------------------

```python
  1 | import System
  2 | 
  3 | import Rhino
  4 | from Rhino.DocObjects import Layer
  5 | from Rhino import RhinoMath
  6 | 
  7 | import scriptcontext
  8 | 
  9 | from rhinoscript import utility as rhutil
 10 | 
 11 | 
 12 | def __getlayer(name_or_id, raise_if_missing):
 13 |     if not name_or_id: raise TypeError("Parameter must be a string or Guid")
 14 |     id = rhutil.coerceguid(name_or_id)
 15 |     if id:
 16 |         layer = scriptcontext.doc.Layers.FindId(id)
 17 |     else:
 18 |         name = name_or_id
 19 |         layer_index = scriptcontext.doc.Layers.FindByFullPath(name, RhinoMath.UnsetIntIndex)
 20 |         if layer_index != RhinoMath.UnsetIntIndex: return scriptcontext.doc.Layers[layer_index]
 21 |         layer = scriptcontext.doc.Layers.FindName(name)
 22 |     if layer: return layer
 23 |     if raise_if_missing: raise ValueError("%s does not exist in LayerTable" % name_or_id)
 24 | 
 25 | 
 26 | def AddLayer(name=None, color=None, visible=True, locked=False, parent=None):
 27 |     """Add a new layer to the document
 28 |     Parameters:
 29 |       name (str, optional): The name of the new layer. If omitted, Rhino automatically
 30 |           generates the layer name.
 31 |       color (color): A Red-Green-Blue color value. If omitted, the color Black is assigned.
 32 |       visible (bool optional): layer's visibility
 33 |       locked (bool, optional): layer's locked state
 34 |       parent (str, optional): name of the new layer's parent layer. If omitted, the new
 35 |           layer will not have a parent layer.
 36 |     Returns:
 37 |       str: The full name of the new layer if successful.
 38 |     Example:
 39 |       import rhinoscriptsyntax as rs
 40 |       from System.Drawing import Color
 41 |       print("New layer:{}".format(rs.AddLayer()))
 42 |       print("New layer:{}".format(rs.AddLayer("MyLayer1")))
 43 |       print("New layer:{}".format(rs.AddLayer("MyLayer2", Color.DarkSeaGreen)))
 44 |       print("New layer:{}".format(rs.AddLayer("MyLayer3", Color.Cornsilk)))
 45 |       print("New layer:{}".format(rs.AddLayer("MyLayer4",parent="MyLayer3")))
 46 |     See Also:
 47 |       CurrentLayer
 48 |       DeleteLayer
 49 |       RenameLayer
 50 |     """
 51 |     names = ['']
 52 |     if name:
 53 |       if not isinstance(name, str): name = str(name)
 54 |       names = [n for n in name.split("::") if name]
 55 |       
 56 |     last_parent_index = -1
 57 |     last_parent = None
 58 |     for idx, name in enumerate(names):
 59 |       layer = Rhino.DocObjects.Layer.GetDefaultLayerProperties()
 60 | 
 61 |       if idx == 0:
 62 |         if parent:
 63 |           last_parent = __getlayer(parent, True)
 64 |       else:
 65 |         if last_parent_index != -1:
 66 |           last_parent = scriptcontext.doc.Layers[last_parent_index]
 67 | 
 68 |       if last_parent:
 69 |         layer.ParentLayerId = last_parent.Id
 70 |       if name:
 71 |         layer.Name = name
 72 |         
 73 |       color = rhutil.coercecolor(color)
 74 |       if color: layer.Color = color
 75 |       layer.IsVisible = visible
 76 |       layer.IsLocked = locked
 77 |     
 78 |       last_parent_index = scriptcontext.doc.Layers.Add(layer)
 79 |       if last_parent_index == -1:
 80 |         full_path = layer.Name
 81 |         if last_parent:
 82 |             full_path = last_parent.FullPath + "::" + full_path
 83 |         last_parent_index = scriptcontext.doc.Layers.FindByFullPath(full_path, RhinoMath.UnsetIntIndex)
 84 |     return scriptcontext.doc.Layers[last_parent_index].FullPath
 85 | 
 86 | 
 87 | def CurrentLayer(layer=None):
 88 |     """Returns or changes the current layer
 89 |     Parameters:
 90 |       layer (guid): the name or Guid of an existing layer to make current
 91 |     Returns:
 92 |       str: If a layer name is not specified, the full name of the current layer
 93 |       str: If a layer name is specified, the full name of the previous current layer
 94 |     Example:
 95 |       import rhinoscriptsyntax as rs
 96 |       rs.AddLayer("MyLayer")
 97 |       rs.CurrentLayer("MyLayer")
 98 |     See Also:
 99 |       AddLayer
100 |       DeleteLayer
101 |       RenameLayer
102 |     """
103 |     rc = scriptcontext.doc.Layers.CurrentLayer.FullPath
104 |     if layer:
105 |         layer = __getlayer(layer, True)
106 |         scriptcontext.doc.Layers.SetCurrentLayerIndex(layer.LayerIndex, True)
107 |     return rc
108 | 
109 | 
110 | def DeleteLayer(layer):
111 |     """Removes an existing layer from the document. The layer to be removed
112 |     cannot be the current layer. Unlike the PurgeLayer method, the layer must
113 |     be empty, or contain no objects, before it can be removed. Any layers that
114 |     are children of the specified layer will also be removed if they are also
115 |     empty.
116 |     Parameters:
117 |       layer (str|guid): the name or id of an existing empty layer
118 |     Returns:
119 |       bool: True or False indicating success or failure
120 |     Example:
121 |       import rhinoscriptsyntax as rs
122 |       layer = rs.GetString("Layer to remove")
123 |       if layer: rs.DeleteLayer(layer)
124 |     See Also:
125 |       AddLayer
126 |       CurrentLayer
127 |       PurgeLayer
128 |       RenameLayer
129 |     """
130 |     layer = __getlayer(layer, True)
131 |     return scriptcontext.doc.Layers.Delete( layer.LayerIndex, True)
132 | 
133 | 
134 | def ExpandLayer( layer, expand ):
135 |     """Expands a layer. Expanded layers can be viewed in Rhino's layer dialog
136 |     Parameters:
137 |       layer (str): name of the layer to expand
138 |       expand (bool): True to expand, False to collapse
139 |     Returns:
140 |       bool: True or False indicating success or failure
141 |     Example:
142 |       import rhinoscriptsyntax as rs
143 |       if rs.IsLayerExpanded("Default"):
144 |           rs.ExpandLayer( "Default", False )
145 |     See Also:
146 |       IsLayerExpanded
147 |     """
148 |     layer = __getlayer(layer, True)
149 |     if layer.IsExpanded==expand: return False
150 |     layer.IsExpanded = expand
151 |     return True
152 | 
153 | 
154 | def IsLayer(layer):
155 |     """Verifies the existance of a layer in the document
156 |     Parameters:
157 |       layer (str|guid): the name or id of a layer to search for
158 |     Returns:
159 |       bool: True on success otherwise False
160 |     Example:
161 |       import rhinoscriptsyntax as rs
162 |       layer = rs.GetString("Layer name")
163 |       if rs.IsLayer(layer):
164 |           print("The layer exists.")
165 |       else:
166 |           print("The layer does not exist.")
167 |     See Also:
168 |       IsLayerChangeable
169 |       IsLayerEmpty
170 |       IsLayerLocked
171 |       IsLayerOn
172 |       IsLayerReference
173 |       IsLayerSelectable
174 |       IsLayerVisible
175 |     """
176 |     layer = __getlayer(layer, False)
177 |     return layer is not None
178 | 
179 | 
180 | def IsLayerChangeable(layer):
181 |     """Verifies that the objects on a layer can be changed (normal)
182 |     Parameters:
183 |       layer (str|guid): the name or id of an existing layer
184 |     Returns:
185 |       bool: True on success otherwise False
186 |     Example:
187 |       import rhinoscriptsyntax as rs
188 |       layer = rs.GetString("Layer name")
189 |       if rs.IsLayer(layer):
190 |           if rs.IsLayerChangeable(layer): print("The layer is changeable.")
191 |           else: print("The layer is not changeable.")
192 |       else:
193 |           print("The layer does not exist.")
194 |     See Also:
195 |       IsLayer
196 |       IsLayerEmpty
197 |       IsLayerLocked
198 |       IsLayerOn
199 |       IsLayerReference
200 |       IsLayerSelectable
201 |       IsLayerVisible
202 |     """
203 |     layer = __getlayer(layer, True)
204 |     rc = layer.IsVisible and not layer.IsLocked
205 |     return rc
206 | 
207 | 
208 | def IsLayerChildOf(layer, test):
209 |     """Verifies that a layer is a child of another layer
210 |     Parameters:
211 |       layer (str|guid): the name or id of the layer to test against
212 |       test (str|guid): the name or id to the layer to test
213 |     Returns:
214 |       bool: True on success otherwise False
215 |     Example:
216 |       import rhinoscriptsyntax as rs
217 |       rs.AddLayer("MyLayer1")
218 |       rs.AddLayer("MyLayer2", parent="MyLayer1")
219 |       rs.AddLayer("MyLayer3", parent="MyLayer2")
220 |       rs.MessageBox( rs.IsLayerChildOf("MyLayer1", "MyLayer3") )
221 |     See Also:
222 |       IsLayerParentOf
223 |     """
224 |     layer = __getlayer(layer, True)
225 |     test = __getlayer(test, True)
226 |     return test.IsChildOf(layer)
227 | 
228 | 
229 | def IsLayerCurrent(layer):
230 |     """Verifies that a layer is the current layer
231 |     Parameters:
232 |       layer (str|guid): the name or id of an existing layer
233 |     Returns:
234 |       bool: True on success otherwise False
235 |     Example:
236 |       import rhinoscriptsyntax as rs
237 |       layer = rs.GetString("Layer name")
238 |       if rs.IsLayer(layer):
239 |           if rs.IsLayerCurrent(layer): print("The layer is current.")
240 |           else: print("The layer is not current.")
241 |       else:
242 |           print("The layer does not exist.")
243 |     See Also:
244 |       IsLayer
245 |       IsLayerEmpty
246 |       IsLayerLocked
247 |       IsLayerOn
248 |       IsLayerReference
249 |       IsLayerSelectable
250 |       IsLayerVisible
251 |     """
252 |     layer = __getlayer(layer, True)
253 |     return layer.LayerIndex == scriptcontext.doc.Layers.CurrentLayerIndex
254 | 
255 | 
256 | def IsLayerEmpty(layer):
257 |     """Verifies that an existing layer is empty, or contains no objects
258 |     Parameters:
259 |       layer (str|guid): the name or id of an existing layer
260 |     Returns:
261 |       bool: True on success otherwise False
262 |     Example:
263 |       import rhinoscriptsyntax as rs
264 |       layer = rs.GetString("Layer name")
265 |       if rs.IsLayer(layer):
266 |           if rs.IsLayerEmpty(layer): print("The layer is empty.")
267 |           else: print("The layer is not empty.")
268 |       else:
269 |           print("The layer does not exist.")
270 |     See Also:
271 |       IsLayerChangeable
272 |       IsLayerLocked
273 |       IsLayerOn
274 |       IsLayerReference
275 |       IsLayerSelectable
276 |       IsLayerVisible
277 |     """
278 |     layer = __getlayer(layer, True)
279 |     rhobjs = scriptcontext.doc.Objects.FindByLayer(layer)
280 |     if not rhobjs: return True
281 |     return False
282 | 
283 | 
284 | def IsLayerExpanded(layer):
285 |     """Verifies that a layer is expanded. Expanded layers can be viewed in
286 |     Rhino's layer dialog
287 |     Parameters:
288 |       layer (str|guid): the name or id of an existing layer
289 |     Returns:
290 |       bool: True on success otherwise False
291 |     Example:
292 |       import rhinoscriptsyntax as rs
293 |       if rs.IsLayerExpanded("Default"):
294 |           rs.ExpandLayer( "Default", False )
295 |     See Also:
296 |       ExpandLayer
297 |     """
298 |     layer = __getlayer(layer, True)
299 |     return layer.IsExpanded   
300 | 
301 | 
302 | def IsLayerLocked(layer):
303 |     """Verifies that a layer is locked.
304 |     Parameters:
305 |       layer (str|guid): the name or id of an existing layer
306 |     Returns:
307 |       cool: True on success otherwise False
308 |     Example:
309 |       import rhinoscriptsyntax as rs
310 |       layer = rs.GetString("Layer name")
311 |       if rs.IsLayer(layer):
312 |           if rs.IsLayerLocked(layer): print("The layer is locked.")
313 |           else: print("The layer is not locked.")
314 |       else:
315 |           print("The layer does not exist.")
316 |     See Also:
317 |       IsLayer
318 |       IsLayerChangeable
319 |       IsLayerEmpty
320 |       IsLayerOn
321 |       IsLayerReference
322 |       IsLayerSelectable
323 |       IsLayerVisible
324 |     """
325 |     layer = __getlayer(layer, True)
326 |     return layer.IsLocked
327 | 
328 | 
329 | def IsLayerOn(layer):
330 |     """Verifies that a layer is on.
331 |     Parameters:
332 |       layer (str|guid): the name or id of an existing layer
333 |     Returns:
334 |       bool: True on success otherwise False
335 |     Example:
336 |       import rhinoscriptsyntax as rs
337 |       layer = rs.GetString("Layer name")
338 |       if rs.IsLayer(layer):
339 |           if rs.IsLayerOn(layer): print("The layer is on.")
340 |           else: print("The layer is not on.")
341 |       else:
342 |           print("The layer does not exist.")
343 |     See Also:
344 |       IsLayer
345 |       IsLayerChangeable
346 |       IsLayerEmpty
347 |       IsLayerLocked
348 |       IsLayerReference
349 |       IsLayerSelectable
350 |       IsLayerVisible
351 |     """
352 |     layer = __getlayer(layer, True)
353 |     return layer.IsVisible
354 | 
355 | 
356 | def IsLayerSelectable(layer):
357 |     """Verifies that an existing layer is selectable (normal and reference)
358 |     Parameters:
359 |       layer (str|guid): the name or id of an existing layer
360 |     Returns:
361 |       bool: True on success otherwise False
362 |     Example:
363 |       import rhinoscriptsyntax as rs
364 |       layer = rs.GetString("Layer name")
365 |       if rs.IsLayer(layer):
366 |           if rs.IsLayerSelectable(layer): print("The layer is selectable.")
367 |           else: print("The layer is not selectable.")
368 |       else:
369 |           print("The layer does not exist.")
370 |     See Also:
371 |       IsLayer
372 |       IsLayerChangeable
373 |       IsLayerEmpty
374 |       IsLayerLocked
375 |       IsLayerOn
376 |       IsLayerReference
377 |       IsLayerVisible
378 |     """
379 |     layer = __getlayer(layer, True)
380 |     return layer.IsVisible and not layer.IsLocked
381 | 
382 | 
383 | def IsLayerParentOf(layer, test):
384 |     """Verifies that a layer is a parent of another layer
385 |     Parameters:
386 |       layer (str|guid): the name or id of the layer to test against
387 |       test (str|guid): the name or id to the layer to test
388 |     Returns:
389 |       bool: True on success otherwise False
390 |     Example:
391 |       import rhinoscriptsyntax as rs
392 |       rs.AddLayer("MyLayer1")
393 |       rs.AddLayer("MyLayer2", parent="MyLayer1")
394 |       rs.AddLayer("MyLayer3", parent="MyLayer2")
395 |       rs.MessageBox( rs.IsLayerParentOf("MyLayer3", "MyLayer1") )
396 |     See Also:
397 |       IsLayerChildOf
398 |     """
399 |     layer = __getlayer(layer, True)
400 |     test = __getlayer(test, True)
401 |     return test.IsParentOf(layer)
402 | 
403 | 
404 | def IsLayerReference(layer):
405 |     """Verifies that a layer is from a reference file.
406 |     Parameters:
407 |       layer (str|guid): the name or id of an existing layer
408 |     Returns:
409 |       bool: True on success otherwise False
410 |     Example:
411 |       import rhinoscriptsyntax as rs
412 |       layer = rs.GetString("Layer name")
413 |       if rs.IsLayer(layer):
414 |           if rs.IsLayerReference(layer): print("The layer is a reference layer.")
415 |           else: print("The layer is not a reference layer.")
416 |       else:
417 |           print("The layer does not exist.")
418 |     See Also:
419 |       IsLayer
420 |       IsLayerChangeable
421 |       IsLayerEmpty
422 |       IsLayerLocked
423 |       IsLayerOn
424 |       IsLayerSelectable
425 |       IsLayerVisible
426 |     """
427 |     layer = __getlayer(layer, True)
428 |     return layer.IsReference
429 | 
430 | 
431 | def IsLayerVisible(layer):
432 |     """Verifies that a layer is visible (normal, locked, and reference)
433 |     Parameters:
434 |       layer (str|guid): the name or id of an existing layer
435 |     Returns:
436 |       bool: True on success otherwise False
437 |     Example:
438 |       import rhinoscriptsyntax as rs
439 |       layer = rs.GetString("Layer name")
440 |       if rs.IsLayer(layer):
441 |           if rs.IsLayerVisible(layer): print("The layer is visible")
442 |           else: print("The layer is not visible")
443 |       else:
444 |           print("The layer does not exist.")
445 |     See Also:
446 |       IsLayer
447 |       IsLayerChangeable
448 |       IsLayerEmpty
449 |       IsLayerLocked
450 |       IsLayerOn
451 |       IsLayerReference
452 |       IsLayerSelectable
453 |     """
454 |     layer = __getlayer(layer, True)
455 |     return layer.IsVisible
456 | 
457 | 
458 | def LayerChildCount(layer):
459 |     """Returns the number of immediate child layers of a layer
460 |     Parameters:
461 |       layer (str|guid): the name or id of an existing layer
462 |     Returns:
463 |       number: the number of immediate child layers if successful
464 |     Example:
465 |       import rhinoscriptsyntax as rs
466 |       children = rs.LayerChildCount("Default")
467 |       if children: rs.ExpandLayer("Default", True)
468 |     See Also:
469 |       LayerChildren
470 |     """
471 |     layer = __getlayer(layer, True)
472 |     children = layer.GetChildren()
473 |     if children: return len(children)
474 |     return 0
475 | 
476 | 
477 | def LayerChildren(layer):
478 |     """Returns the immediate child layers of a layer
479 |     Parameters:
480 |       layer (str|guid): the name or id of an existing layer
481 |     Returns:
482 |       list(str, ...): List of children layer names
483 |     Example:
484 |       import rhinoscriptsyntax as rs
485 |       children = rs.LayerChildren("Default")
486 |       if children:
487 |           for child in children: print(child)
488 |     See Also:
489 |       LayerChildCount
490 |       ParentLayer
491 |     """
492 |     layer = __getlayer(layer, True)
493 |     children = layer.GetChildren()
494 |     if children: return [child.FullPath for child in children]
495 |     return [] #empty list
496 | 
497 | 
498 | def LayerColor(layer, color=None):
499 |     """Returns or changes the color of a layer.
500 |     Parameters:
501 |       layer (str|guid): name or id of an existing layer
502 |       color (color): the new color value. If omitted, the current layer color is returned.
503 |     Returns:
504 |       color: If a color value is not specified, the current color value on success
505 |       color: If a color value is specified, the previous color value on success
506 |     Example:
507 |       import rhinoscriptsyntax as rs
508 |       import random
509 |       from System.Drawing import Color
510 |        
511 |       def randomcolor():
512 |           red = int(255*random.random())
513 |           green = int(255*random.random())
514 |           blue = int(255*random.random())
515 |           return Color.FromArgb(red,green,blue)
516 |        
517 |       layerNames = rs.LayerNames()
518 |       if layerNames:
519 |           for name in layerNames: rs.LayerColor(name, randomcolor())
520 |     See Also:
521 |       
522 |     """
523 |     layer = __getlayer(layer, True)
524 |     rc = layer.Color
525 |     if color:
526 |         color = rhutil.coercecolor(color)
527 |         if color is not None:
528 |           layer.Color = color
529 |           scriptcontext.doc.Views.Redraw()
530 |     return rc
531 | 
532 | 
533 | def LayerCount():
534 |     """Returns the number of layers in the document
535 |     Returns:
536 |       number: the number of layers in the document
537 |     Example:
538 |       import rhinoscriptsyntax as rs
539 |       count = rs.LayerCount()
540 |       print("There are {} layers".format(count))
541 |     See Also:
542 |       LayerNames
543 |     """
544 |     return scriptcontext.doc.Layers.ActiveCount
545 | 
546 | 
547 | def LayerIds():
548 |     """Return identifiers of all layers in the document
549 |     Returns:
550 |       list(guid, ...): the identifiers of all layers in the document
551 |     Example:
552 |       import rhinoscriptsyntax as rs
553 |       layers = rs.LayerIds()
554 |       for layer in layers: print(layer)
555 |     See Also:
556 |       LayerCount
557 |       LayerNames
558 |     """
559 |     return [layer.Id for layer in scriptcontext.doc.Layers if not layer.IsDeleted]
560 | 
561 | 
562 | def LayerLinetype(layer, linetype=None):
563 |     """Returns or changes the linetype of a layer
564 |     Parameters:
565 |       layer (str): name of an existing layer
566 |       linetype (str, optional): name of a linetype
567 |     Returns:
568 |       str: If linetype is not specified, name of the current linetype
569 |       str: If linetype is specified, name of the previous linetype
570 |     Example:
571 |       import rhinoscriptsyntax as rs
572 |       layers = rs.LayerNames()
573 |       if layers:
574 |           for layer in layers:
575 |               if rs.LayerLinetype(layer)!="Continuous":
576 |                   rs.LayerLinetype(layer,"Continuous")
577 |     See Also:
578 |       LayerPrintColor
579 |       LayerPrintWidth
580 |     """
581 |     layer = __getlayer(layer, True)
582 |     index = layer.LinetypeIndex
583 |     rc = scriptcontext.doc.Linetypes[index].Name
584 |     if linetype:
585 |         if not isinstance(linetype, str): linetype = str(linetype)
586 |         if linetype == scriptcontext.doc.Linetypes.ContinuousLinetypeName:
587 |           index = -1
588 |         else:
589 |           lt = scriptcontext.doc.Linetypes.FindName(linetype)
590 |           if lt == None: return scriptcontext.errorhandler()
591 |           index = lt.LinetypeIndex
592 |         layer.LinetypeIndex = index
593 |         scriptcontext.doc.Views.Redraw()
594 |     return rc
595 | 
596 | 
597 | def LayerLocked(layer, locked=None):
598 |     """Returns or changes the locked mode of a layer
599 |     Parameters:
600 |       layer (str): name of an existing layer
601 |       locked (bool, optional): new layer locked mode
602 |     Returns:
603 |       bool: If locked is not specified, the current layer locked mode
604 |       bool: If locked is specified, the previous layer locked mode
605 |     Example:
606 |       import rhinoscriptsyntax as rs
607 |       layers = rs.LayerNames()
608 |       if layers:
609 |           for layer in layers:
610 |               if rs.LayerLocked(layer): rs.LayerLocked(layer, False)
611 |     See Also:
612 |       LayerVisible
613 |     """
614 |     layer = __getlayer(layer, True)
615 |     rc = layer.IsLocked 
616 |     if locked!=None and locked!=layer.GetPersistentLocking():
617 |         layer.IsLocked = locked
618 |         layer.SetPersistentLocking(locked)
619 |         scriptcontext.doc.Views.Redraw()
620 |     return rc
621 | 
622 | 
623 | def LayerMaterialIndex(layer,index=None):
624 |     """Returns or changes the material index of a layer. A material index of -1
625 |     indicates that no material has been assigned to the layer. Thus, the layer
626 |     will use Rhino's default layer material
627 |     Parameters:
628 |       layer (str):  name of existing layer
629 |       index (number, optional): the new material index
630 |     Returns:
631 |       number: a zero-based material index if successful
632 |     Example:
633 |       import rhinoscriptsyntax as rs
634 |       index = rs.LayerMaterialIndex("Default")
635 |       if index is not None:
636 |           if index==-1:
637 |               print("The default layer does not have a material assigned.")
638 |           else:
639 |               print("The default layer has a material assigned.")
640 |     See Also:
641 |       
642 |     """
643 |     layer = __getlayer(layer, True)
644 |     rc = layer.RenderMaterialIndex
645 |     if index is not None and index>=-1:
646 |         layer.RenderMaterialIndex = index
647 |         scriptcontext.doc.Views.Redraw()
648 |     return rc
649 | 
650 | 
651 | def LayerId(layer):
652 |     """Returns the identifier of a layer given the layer's name.
653 |     Parameters:
654 |       layer (str): name of existing layer
655 |     Returns:
656 |       guid (str): The layer's identifier if successful.
657 |       None: If not successful, or on error.
658 |     Example:
659 |       import rhinoscriptsyntax as  rs
660 |       id = rs.LayerId('Layer 01')
661 |     See Also:
662 |       LayerName
663 |     """
664 |     idx = scriptcontext.doc.Layers.FindByFullPath(layer, RhinoMath.UnsetIntIndex)
665 |     return str(scriptcontext.doc.Layers[idx].Id) if idx != RhinoMath.UnsetIntIndex else None
666 | 
667 | 
668 | def LayerName(layer_id, fullpath=True):
669 |     """Return the name of a layer given it's identifier
670 |     Parameters:
671 |       layer_id (guid): layer identifier
672 |       fullpath (bool, optional): return the full path name `True` or short name `False`
673 |     Returns:
674 |       str: the layer's name if successful
675 |       None: if not successful
676 |     Example:
677 |       import rhinoscriptsyntax as rs
678 |       layers = rs.LayerIds()
679 |       if layers:
680 |           for layer in layers: print(rs.LayerName(layer))
681 |     See Also:
682 |       LayerId
683 |     """
684 |     layer = __getlayer(layer_id, True)
685 |     if fullpath: return layer.FullPath
686 |     return layer.Name
687 | 
688 | 
689 | def LayerNames(sort=False):
690 |     """Returns the names of all layers in the document.
691 |     Parameters:
692 |       sort (bool, optional): return a sorted list of the layer names
693 |     Returns:
694 |       list(str, ...): list of layer names
695 |     Example:
696 |       import rhinoscriptsyntax as rs
697 |       layers = rs.LayerNames()
698 |       if layers:
699 |           for layer in layers: print(layer)
700 |     See Also:
701 |       LayerCount
702 |     """
703 |     rc = []
704 |     for layer in scriptcontext.doc.Layers:
705 |         if not layer.IsDeleted: rc.append(layer.FullPath)
706 |     if sort: rc.sort()
707 |     return rc
708 | 
709 | 
710 | def LayerOrder(layer):
711 |     """Returns the current display order index of a layer as displayed in Rhino's
712 |     layer dialog box. A display order index of -1 indicates that the current
713 |     layer dialog filter does not allow the layer to appear in the layer list
714 |     Parameters:
715 |       layer (str): name of existing layer
716 |     Returns:
717 |       number: 0 based index of layer
718 |     Example:
719 |       import rhinoscriptsyntax as rs
720 |       index = rs.LayerOrder("Default")
721 |       if index is not None:
722 |           if index==-1: print("The layer does not display in the Layer dialog.")
723 |           else: print("The layer does display in the Layer dialog.")
724 |     See Also:
725 |       
726 |     """
727 |     layer = __getlayer(layer, True)
728 |     return layer.SortIndex
729 | 
730 | 
731 | def LayerPrintColor(layer, color=None):
732 |     """Returns or changes the print color of a layer. Layer print colors are
733 |     represented as RGB colors.
734 |     Parameters:
735 |       layer (str): name of existing layer
736 |       color (color): new print color
737 |     Returns:
738 |       color: if color is not specified, the current layer print color
739 |       color: if color is specified, the previous layer print color
740 |       None: on error
741 |     Example:
742 |       import rhinoscriptsyntax as rs
743 |       layers = rs.LayerNames()
744 |       if layers:
745 |           for layer in layers:
746 |               black = rs.CreateColor((0,0,0))
747 |               if rs.LayerPrintColor(layer)!=black:
748 |                   rs.LayerPrintColor(layer, black)
749 |     See Also:
750 |       LayerLinetype
751 |       LayerPrintWidth
752 |     """
753 |     layer = __getlayer(layer, True)
754 |     rc = layer.PlotColor
755 |     if color:
756 |         color = rhutil.coercecolor(color)
757 |         layer.PlotColor = color
758 |         scriptcontext.doc.Views.Redraw()
759 |     return rc
760 | 
761 | 
762 | def LayerPrintWidth(layer, width=None):
763 |     """Returns or changes the print width of a layer. Print width is specified
764 |     in millimeters. A print width of 0.0 denotes the "default" print width.
765 |     Parameters:
766 |       layer (str): name of existing layer
767 |       width (number, optional): new print width
768 |     Returns:
769 |       number: if width is not specified, the current layer print width
770 |       number: if width is specified, the previous layer print width
771 |     Example:
772 |       import rhinoscriptsyntax as rs
773 |       layers = rs.LayerNames()
774 |       if layers:
775 |           for layer in layers:
776 |               if rs.LayerPrintWidth(layer)!=0:
777 |                   rs.LayerPrintWidth(layer, 0)
778 |     See Also:
779 |       LayerLinetype
780 |       LayerPrintColor
781 |     """
782 |     layer = __getlayer(layer, True)
783 |     rc = layer.PlotWeight
784 |     if width is not None and width!=rc:
785 |         layer.PlotWeight = width
786 |         scriptcontext.doc.Views.Redraw()
787 |     return rc
788 | 
789 | 
790 | def LayerVisible(layer, visible=None, forcevisible_or_donotpersist=False):
791 |     """Returns or changes the visible property of a layer.
792 |     Parameters:
793 |       layer (str): name of existing layer
794 |       visible (bool, optional): new visible state
795 |       forcevisible_or_donotpersist (bool, optional): if visible is True then turn parent layers on if True.  If visible is False then do not persist if True
796 |     Returns:
797 |       bool: if visible is not specified, the current layer visibility
798 |       bool: if visible is specified, the previous layer visibility
799 |     Example:
800 |       import rhinoscriptsyntax as rs
801 |       layers = rs.LayerNames()
802 |       if layers:
803 |           for layer in layers:
804 |               if rs.LayerVisible(layer)==False:
805 |                   rs.LayerVisible(layer,True)
806 |     See Also:
807 |       LayerLocked
808 |     """
809 |     layer = __getlayer(layer, True)
810 |     rc = layer.IsVisible
811 |     if visible is not None:
812 |         layer.IsVisible = visible
813 |         if visible and forcevisible_or_donotpersist:
814 |             scriptcontext.doc.Layers.ForceLayerVisible(layer.Id)
815 |         if not visible and not forcevisible_or_donotpersist:
816 |           if layer.ParentLayerId != System.Guid.Empty:
817 |             layer.SetPersistentVisibility(visible)
818 |         scriptcontext.doc.Views.Redraw()
819 |     return rc
820 | 
821 | 
822 | def ParentLayer(layer, parent=None):
823 |     """Return or modify the parent layer of a layer
824 |     Parameters:
825 |       layer (str): name of an existing layer
826 |       parent (str, optional):  name of new parent layer. To remove the parent layer,
827 |         thus making a root-level layer, specify an empty string
828 |     Returns:
829 |       str: If parent is not specified, the name of the current parent layer
830 |       str: If parent is specified, the name of the previous parent layer
831 |       None: if the layer does not have a parent
832 |     Example:
833 |       import rhinoscriptsyntax as rs
834 |       layers = rs.LayerNames()
835 |       for layer in layers:
836 |           parent = rs.ParentLayer(layer)
837 |           print("Layer: {}, Parent: {}".format(layer, parent))
838 |     See Also:
839 |       LayerChildren
840 |     """
841 |     layer = __getlayer(layer, True)
842 |     parent_id = layer.ParentLayerId
843 |     oldparent = None
844 |     if parent_id!=System.Guid.Empty:
845 |         oldparentlayer = scriptcontext.doc.Layers.Find(parent_id, True, -1)
846 |         if oldparentlayer is not None:
847 |             oldparentlayer = scriptcontext.doc.Layers[oldparentlayer]
848 |             oldparent = oldparentlayer.FullPath
849 |     if parent is None: return oldparent
850 |     if parent=="":
851 |         layer.ParentLayerId = System.Guid.Empty
852 |     else:
853 |         parent = __getlayer(parent, True)
854 |         layer.ParentLayerId = parent.Id
855 |     return oldparent
856 | 
857 | 
858 | def PurgeLayer(layer):
859 |     """Removes an existing layer from the document. The layer will be removed
860 |     even if it contains geometry objects. The layer to be removed cannot be the
861 |     current layer
862 |     empty.
863 |     Parameters:
864 |       layer (str|guid): the name or id of an existing empty layer
865 |     Returns:
866 |       bool: True or False indicating success or failure
867 |     Example:
868 |       import rhinoscriptsyntax as rs
869 |       layer = rs.GetString("Layer to purge")
870 |       if layer: rs.PurgeLayer(layer)
871 |     See Also:
872 |       AddLayer
873 |       CurrentLayer
874 |       DeleteLayer
875 |       RenameLayer
876 |     """
877 |     layer = __getlayer(layer, True)
878 |     rc = scriptcontext.doc.Layers.Purge( layer.LayerIndex, True)
879 |     scriptcontext.doc.Views.Redraw()
880 |     return rc
881 | 
882 | 
883 | def RenameLayer(oldname, newname):
884 |     """Renames an existing layer
885 |     Parameters:
886 |       oldname (str): original layer name
887 |       newname (str): new layer name
888 |     Returns: 
889 |       str: The new layer name if successful otherwise None
890 |     Example:
891 |       import rhinoscriptsyntax as rs
892 |       oldname = rs.GetString("Old layer name")
893 |       if oldname:
894 |           newname = rs.GetString("New layer name")
895 |           if newname: rs.RenameLayer(oldname, newname)
896 |     See Also:
897 |       AddLayer
898 |       CurrentLayer
899 |       DeleteLayer
900 |     """
901 |     if oldname and newname:
902 |         layer = __getlayer(oldname, True)
903 |         layer.Name = newname
904 |         return newname
905 | 
```

--------------------------------------------------------------------------------
/rhino_mcp_server/static/utility.py:
--------------------------------------------------------------------------------

```python
   1 | import time
   2 | import math
   3 | import string
   4 | import numbers
   5 | from operator import attrgetter
   6 | 
   7 | import System
   8 | import System.Drawing
   9 | import System.Windows.Forms
  10 | 
  11 | import Rhino
  12 | 
  13 | import rhinocompat as compat
  14 | import scriptcontext
  15 | 
  16 | 
  17 | def ContextIsRhino():
  18 |     """Return True if the script is being executed in the context of Rhino
  19 |     Returns:
  20 |       bool: True if the script is being executed in the context of Rhino
  21 |     Example:
  22 |       import rhinoscriptsyntax as  rs
  23 |       print(rs.ContextIsRhino())
  24 |     See Also:
  25 |       ContextIsGrasshopper
  26 |     """
  27 |     return scriptcontext.id == 1
  28 | 
  29 | 
  30 | def ContextIsGrasshopper():
  31 |     """Return True if the script is being executed in a grasshopper component
  32 |     Returns:
  33 |       bool: True if the script is being executed in a grasshopper component
  34 |     Example:
  35 |       import rhinoscriptsyntax as  rs
  36 |       print(rs.ContextIsGrasshopper())
  37 |     See Also:
  38 |       ContextIsRhino
  39 |     """
  40 |     return scriptcontext.id == 2
  41 | 
  42 | 
  43 | def Angle(point1, point2, plane=True):
  44 |     """Measures the angle between two points
  45 |     Parameters:
  46 |       point1, point2 (point): the input points
  47 |       plane (bool, optional): Boolean or Plane
  48 |         If True, angle calculation is based on the world coordinate system.
  49 |         If False, angle calculation is based on the active construction plane
  50 |         If a plane is provided, angle calculation is with respect to this plane
  51 |     Returns:
  52 |       tuple(tuple(number, number), number, number, number, number): containing the following elements if successful
  53 |         element 0 = the X,Y angle in degrees
  54 |         element 1 = the elevation
  55 |         element 2 = delta in the X direction
  56 |         element 3 = delta in the Y direction
  57 |         element 4 = delta in the Z direction
  58 |       None: if not successful
  59 |     Example:
  60 |       import rhinoscriptsyntax as  rs
  61 |       point1 = rs.GetPoint("First  point")
  62 |       if point1:
  63 |           point2  = rs.GetPoint("Second point")
  64 |           if point2:
  65 |               angle  = rs.Angle(point1, point2)
  66 |               if  angle: print("Angle: {}".format(angle[0]))
  67 |     See Also:
  68 |       Angle2
  69 |       Distance
  70 |     """
  71 |     pt1 = coerce3dpoint(point1)
  72 |     if pt1 is None:
  73 |         pt1 = coercerhinoobject(point1)
  74 |         if isinstance(pt1, Rhino.DocObjects.PointObject): pt1 = pt1.Geometry.Location
  75 |         else: pt1=None
  76 |     pt2 = coerce3dpoint(point2)
  77 |     if pt2 is None:
  78 |         pt2 = coercerhinoobject(point2)
  79 |         if isinstance(pt2, Rhino.DocObjects.PointObject): pt2 = pt2.Geometry.Location
  80 |         else: pt2=None
  81 |     point1 = pt1
  82 |     point2 = pt2
  83 |     if point1 is None or point2 is None: return scriptcontext.errorhandler()
  84 |     vector = point2 - point1
  85 |     x = vector.X
  86 |     y = vector.Y
  87 |     z = vector.Z
  88 |     if plane!=True:
  89 |         plane = coerceplane(plane)
  90 |         if plane is None:
  91 |             plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
  92 |         vfrom = point1 - plane.Origin
  93 |         vto = point2 - plane.Origin
  94 |         x = vto * plane.XAxis - vfrom * plane.XAxis
  95 |         y = vto * plane.YAxis - vfrom * plane.YAxis
  96 |         z = vto * plane.ZAxis - vfrom * plane.ZAxis
  97 |     h = math.sqrt( x * x + y * y)
  98 |     angle_xy = math.degrees( math.atan2( y, x ) )
  99 |     elevation = math.degrees( math.atan2( z, h ) )
 100 |     return angle_xy, elevation, x, y, z
 101 | 
 102 | 
 103 | def Angle2(line1, line2):
 104 |     """Measures the angle between two lines
 105 |     Parameters:
 106 |       line1 (line): List of 6 numbers or 2 Point3d.
 107 |       line2 (line): List of 6 numbers or 2 Point3d.
 108 |     Returns:
 109 |       tuple(number, number): containing the following elements if successful.
 110 |         0 The angle in degrees.
 111 |         1 The reflex angle in degrees.
 112 |       None: If not successful, or on error.
 113 |     Example:
 114 |       import rhinoscriptsyntax as rs
 115 |       point1 = rs.GetPoint("Start of first line")
 116 |       point2 = rs.GetPoint("End of first line", point1)
 117 |       point3 = rs.GetPoint("Start of second line")
 118 |       point4 = rs.GetPoint("End of second line", point3)
 119 |       angle = rs.Angle2( (point1, point2), (point3, point4))
 120 |       if angle: print("Angle: {}".format(angle))
 121 |     See Also:
 122 |       Angle
 123 |       Distance
 124 |     """
 125 |     line1 = coerceline(line1, True)
 126 |     line2 = coerceline(line2, True)
 127 |     vec0 = line1.To - line1.From
 128 |     vec1 = line2.To - line2.From
 129 |     if not vec0.Unitize() or not vec1.Unitize(): return scriptcontext.errorhandler()
 130 |     dot = vec0 * vec1
 131 |     dot = clamp(-1,1,dot)
 132 |     angle = math.acos(dot)
 133 |     reflex_angle = 2.0*math.pi - angle
 134 |     angle = math.degrees(angle)
 135 |     reflex_angle = math.degrees(reflex_angle)
 136 |     return angle, reflex_angle
 137 | 
 138 | 
 139 | def ClipboardText(text=None):
 140 |     """Returns or sets a text string to the Windows clipboard
 141 |     Parameters:
 142 |       text (str, optional): text to set
 143 |     Returns:
 144 |       str: if text is not specified, the current text in the clipboard
 145 |       str: if text is specified, the previous text in the clipboard
 146 |       None: if not successful
 147 |     Example:
 148 |       import rhinoscriptsyntax as rs
 149 |       txt = rs.ClipboardText("Hello Rhino!")
 150 |       if txt: rs.MessageBox(txt, 0, "Clipboard Text")
 151 |     See Also:
 152 |       
 153 |     """
 154 |     rc = None
 155 |     if System.Windows.Forms.Clipboard.ContainsText():
 156 |         rc = System.Windows.Forms.Clipboard.GetText()
 157 |     if text:
 158 |         if not isinstance(text, str): text = str(text)
 159 |         System.Windows.Forms.Clipboard.SetText(text)
 160 |     return rc
 161 | 
 162 | 
 163 | def ColorAdjustLuma(rgb, luma, scale=False):
 164 |     """Changes the luminance of a red-green-blue value. Hue and saturation are
 165 |     not affected
 166 |     Parameters:
 167 |       rgb (color): initial rgb value
 168 |       luma (number): The luminance in units of 0.1 percent of the total range. A
 169 |           value of luma = 50 corresponds to 5 percent of the maximum luminance
 170 |       scale (bool, optional): if True, luma specifies how much to increment or decrement the
 171 |           current luminance. If False, luma specified the absolute luminance.
 172 |     Returns:
 173 |       color: modified rgb value if successful
 174 |     Example:
 175 |       import rhinoscriptsyntax as rs
 176 |       rgb = rs.ColorAdjustLuma((128, 128, 128), 50)
 177 |       print("Red = {}".format(rs.ColorRedValue(rgb)))
 178 |       print("Green = {}".format(rs.ColorGreenValue(rgb)))
 179 |       print("Blue = {}".format(rs.ColorBlueValue(rgb)))
 180 |     See Also:
 181 |       ColorHLSToRGB
 182 |       ColorRGBToHLS
 183 |     """
 184 |     rgb = coercecolor(rgb, True)
 185 |     hsl = Rhino.Display.ColorHSL(rgb)
 186 |     luma = luma / 1000.0
 187 |     if scale: luma = hsl.L + luma
 188 |     hsl.L = luma
 189 |     return hsl.ToArgbColor()
 190 | 
 191 | 
 192 | def ColorBlueValue(rgb):
 193 |     """Retrieves intensity value for the blue component of an RGB color
 194 |     Parameters:
 195 |       rgb (color): the RGB color value
 196 |     Returns:
 197 |       number: The blue component if successful, otherwise None
 198 |     Example:
 199 |       import rhinoscriptsyntax as rs
 200 |       rgb = rs.LayerColor("Default")
 201 |       print("Red = {}".format(rs.ColorRedValue(rgb)))
 202 |       print("Green = {}".format(rs.ColorGreenValue(rgb)))
 203 |       print("Blue = {}".format(rs.ColorBlueValue(rgb)))
 204 |     See Also:
 205 |       ColorGreenValue
 206 |       ColorRedValue
 207 |     """
 208 |     return coercecolor(rgb, True).B
 209 | 
 210 | 
 211 | def ColorGreenValue(rgb):
 212 |     """Retrieves intensity value for the green component of an RGB color
 213 |     Parameters:
 214 |       rgb (color): the RGB color value
 215 |     Returns:
 216 |       number: The green component if successful, otherwise None
 217 |     Example:
 218 |       import rhinoscriptsyntax as rs
 219 |       rgb = rs.LayerColor("Default")
 220 |       print("Red = {}".format(rs.ColorRedValue(rgb)))
 221 |       print("Green = {}".format(rs.ColorGreenValue(rgb)))
 222 |       print("Blue = {}".format(rs.ColorBlueValue(rgb)))
 223 |     See Also:
 224 |       ColorBlueValue
 225 |       ColorRedValue
 226 |     """
 227 |     return coercecolor(rgb, True).G
 228 | 
 229 | 
 230 | def ColorHLSToRGB(hls):
 231 |     """Converts colors from hue-lumanence-saturation to RGB
 232 |     Parameters:
 233 |       hls (color): the HLS color value
 234 |     Returns:
 235 |       color: The RGB color value if successful, otherwise False
 236 |     Example:
 237 |       import rhinoscriptsyntax as rs
 238 |       rgb = rs.ColorHLSToRGB( (160, 120, 0) )
 239 |       print("Red = {}".format(rs.ColorRedValue(rgb)))
 240 |       print("Green = {}".format(rs.ColorGreenValue(rgb)))
 241 |       print("Blue = {}".format(rs.ColorBlueValue(rgb)))
 242 |     See Also:
 243 |       ColorAdjustLuma
 244 |       ColorRGBToHLS
 245 |     """
 246 |     if len(hls)==3:
 247 |         hls = Rhino.Display.ColorHSL(hls[0]/240.0, hls[2]/240.0, hls[1]/240.0)
 248 |     elif len(hls)==4:
 249 |         hls = Rhino.Display.ColorHSL(hls[3]/240.0, hls[0]/240.0, hls[2]/240.0, hls[1]/240.0)
 250 |     return hls.ToArgbColor()
 251 | 
 252 | 
 253 | def ColorRedValue(rgb):
 254 |     """Retrieves intensity value for the red component of an RGB color
 255 |     Parameters:
 256 |       hls (color): the HLS color value
 257 |     Returns:
 258 |       color: The red color value if successful, otherwise False
 259 |     Example:
 260 |       import rhinoscriptsyntax as rs
 261 |       rgb = rs.LayerColor("Default")
 262 |       print("Red = {}".format(rs.ColorRedValue(rgb)))
 263 |       print("Green = {}".format(rs.ColorGreenValue(rgb)))
 264 |       print("Blue = {}".format(rs.ColorBlueValue(rgb)))
 265 |     See Also:
 266 |       ColorBlueValue
 267 |       ColorGreenValue
 268 |     """
 269 |     return coercecolor(rgb, True).R
 270 | 
 271 | 
 272 | def ColorRGBToHLS(rgb):
 273 |     """Convert colors from RGB to HLS
 274 |     Parameters:
 275 |       rgb (color): the RGB color value
 276 |     Returns:
 277 |       color: The HLS color value if successful, otherwise False
 278 |     Example:
 279 |       import rhinoscriptsyntax as rs
 280 |       hls = rs.ColorRGBToHLS((128, 128, 128))
 281 |       print("Hue = {}".format(hls[0]))
 282 |       print("Luminance = {}".format(hls[1]))
 283 |       print("Saturation = {}".format(hls[2]))
 284 |     See Also:
 285 |       ColorAdjustLuma
 286 |       ColorHLSToRGB
 287 |     """
 288 |     rgb = coercecolor(rgb, True)
 289 |     hsl = Rhino.Display.ColorHSL(rgb)
 290 |     return hsl.H, hsl.S, hsl.L
 291 | 
 292 | 
 293 | def CullDuplicateNumbers(numbers, tolerance=None):
 294 |     """Removes duplicates from an array of numbers.
 295 |     Parameters:
 296 |       numbers ([number, ...]): list or tuple
 297 |       tolerance (number, optional): The minimum distance between numbers.  Numbers that fall within this tolerance will be discarded.  If omitted, Rhino's internal zero tolerance is used.
 298 |     Returns:
 299 |       list(number, ...): numbers with duplicates removed if successful.
 300 |     Example:
 301 |       import rhinoscriptsyntax as rs
 302 |       arr = [1,1,2,2,3,3,4,4,5,5]
 303 |       arr = rs.CullDuplicateNumbers(arr)
 304 |       for n in arr: print(n)
 305 |     See Also:
 306 |       CullDuplicatePoints
 307 |     """
 308 |     count = len(numbers)
 309 |     if count < 2: return numbers
 310 |     if tolerance is None: tolerance = scriptcontext.doc.ModelAbsoluteTolerance
 311 |     numbers = sorted(numbers)
 312 |     d = numbers[0]
 313 |     index = 1
 314 |     for step in range(1,count):
 315 |         test_value = numbers[index]
 316 |         if math.fabs(d-test_value)<=tolerance:
 317 |             numbers.pop(index)
 318 |         else:
 319 |             d = test_value
 320 |             index += 1
 321 |     return numbers
 322 | 
 323 | 
 324 | def CullDuplicatePoints(points, tolerance=-1):
 325 |     """Removes duplicates from a list of 3D points.
 326 |     Parameters:
 327 |       points ([point, ...]): A list of 3D points.
 328 |       tolerance (number): Minimum distance between points. Points within this
 329 |         tolerance will be discarded. If omitted, Rhino's internal zero tolerance
 330 |         is used.
 331 |     Returns:
 332 |       list(point, ...): of 3D points with duplicates removed if successful.
 333 |       None: if not successful
 334 |     Example:
 335 |       import rhinoscriptsyntax as rs
 336 |       points = rs.GetPoints(,,"First point", "Next point")
 337 |       if points:
 338 |           points= rs.CullDuplicatePoints(points)
 339 |           for p in points: print(p)
 340 |     See Also:
 341 |       CullDuplicateNumbers
 342 |     """
 343 |     points = coerce3dpointlist(points, True)
 344 |     if tolerance is None or tolerance < 0:
 345 |         tolerance = Rhino.RhinoMath.ZeroTolerance
 346 |     return list(Rhino.Geometry.Point3d.CullDuplicates(points, tolerance))
 347 | 
 348 | 
 349 | def Distance(point1, point2):
 350 |     """Measures distance between two 3D points, or between a 3D point and
 351 |     an array of 3D points.
 352 |     Parameters:
 353 |       point1 (point): The first 3D point.
 354 |       point2 (point): The second 3D point or list of 3-D points.
 355 |     Returns:
 356 |       point: If point2 is a 3D point then the distance if successful.
 357 |       point: If point2 is a list of points, then an list of distances if successful.
 358 |       None: if not successful
 359 |     Example:
 360 |       import rhinoscriptsyntax as rs
 361 |       point1 = rs.GetPoint("First point")
 362 |       if point1:
 363 |           point2 = rs.GetPoint("Second point")
 364 |           if point2:
 365 |               print("Distance: {}".format(rs.Distance(point1, point2)))
 366 |     See Also:
 367 |       Angle
 368 |       Angle2
 369 |     """
 370 |     from_pt = coerce3dpoint(point1, True)
 371 |     to_pt = coerce3dpoint(point2)
 372 |     if to_pt: return (to_pt - from_pt).Length
 373 |     # check if we have a list of points
 374 |     to_pt = coerce3dpointlist(point2, True)
 375 |     distances = [(point - from_pt).Length for point in to_pt]
 376 |     if distances: return distances
 377 | 
 378 | 
 379 | def GetSettings(filename, section=None, entry=None):
 380 |     """Returns string from a specified section in a initialization file.
 381 |     Parameters:
 382 |       filename (str): name of the initialization file
 383 |       section (str, optional): section containing the entry
 384 |       entry (str, optional): entry whose associated string is to be returned
 385 |     Returns:
 386 |       list(str, ...): If section is not specified, a list containing all section names
 387 |       list:(str, ...): If entry is not specified, a list containing all entry names for a given section
 388 |       str: If section and entry are specified, a value for entry
 389 |       None: if not successful
 390 |     Example:
 391 |       import rhinoscriptsyntax as rs
 392 |       filename = rs.OpenFileName("Open", "Initialization Files (*.ini)|*.ini||")
 393 |       if filename:
 394 |           sections = rs.GetSettings(filename)
 395 |           if sections:
 396 |               section = rs.ListBox(sections, "Select a section", filename)
 397 |               if section:
 398 |                   entries = rs.GetSettings(filename, section)
 399 |                   if entries:
 400 |                       entry = rs.ListBox(entries, "Select an entry", section)
 401 |                       if entry:
 402 |                           value = rs.GetSettings(filename, section, entry)
 403 |                           if value: rs.MessageBox( value, 0, entry )
 404 |     See Also:
 405 |       
 406 |     """
 407 |     CP = compat.GET_IMPORT_CONFIG_PARSER()
 408 |     try:
 409 |         cp = CP.ConfigParser()
 410 |         cp.read(filename)
 411 |         if not section: return cp.sections()
 412 |         section = string.lower(section)
 413 |         if not entry: return cp.options(section)
 414 |         entry = string.lower(entry)
 415 |         return cp.get(section, entry)
 416 |     except IOError:
 417 |         return scriptcontext.errorhander()
 418 |     return scriptcontext.errorhandler()
 419 | 
 420 | 
 421 | def Polar(point, angle_degrees, distance, plane=None):
 422 |     """Returns 3D point that is a specified angle and distance from a 3D point
 423 |     Parameters:
 424 |       point (point): the point to transform
 425 |       plane (plane, optional): plane to base the transformation. If omitted, the world
 426 |         x-y plane is used
 427 |     Returns:
 428 |       point: resulting point is successful
 429 |       None: on error
 430 |     Example:
 431 |       import rhinoscriptsyntax as rs
 432 |       point = (1.0, 1.0, 0.0)
 433 |       result = rs.Polar(point, 45.0, 1.414214)
 434 |       print(result)
 435 |     See Also:
 436 |       PointAdd
 437 |       PointCompare
 438 |       PointDivide
 439 |       PointScale
 440 |       PointSubtract
 441 |     """
 442 |     point = coerce3dpoint(point, True)
 443 |     angle = math.radians(angle_degrees)
 444 |     if plane: plane = coerceplane(plane)
 445 |     else: plane = Rhino.Geometry.Plane.WorldXY
 446 |     offset = plane.XAxis
 447 |     offset.Unitize()
 448 |     offset *= distance
 449 |     rc = point+offset
 450 |     xform = Rhino.Geometry.Transform.Rotation(angle, plane.ZAxis, point)
 451 |     rc.Transform(xform)
 452 |     return rc
 453 | 
 454 | 
 455 | def SimplifyArray(points):
 456 |     """Flattens an array of 3-D points into a one-dimensional list of real numbers. For example, if you had an array containing three 3-D points, this method would return a one-dimensional array containing nine real numbers.
 457 |     Parameters:
 458 |       points ([point, ...]): Points to flatten
 459 |     Returns:
 460 |       list(number, ...): A one-dimensional list containing real numbers, if successful, otherwise None
 461 |     Example:
 462 |       import rhinoscriptsyntax as rs
 463 |       points = rs.GetPoints()
 464 |       if points:
 465 |           numbers = rs.SimplifyArray(points)
 466 |           for n in numbers: print(n)
 467 |     See Also:
 468 |       
 469 |     """
 470 |     rc = []
 471 |     for point in points:
 472 |         point = coerce3dpoint(point, True)
 473 |         rc.append(point.X)
 474 |         rc.append(point.Y)
 475 |         rc.append(point.Z)
 476 |     return rc
 477 | 
 478 | 
 479 | def Sleep(milliseconds):
 480 |     """Suspends execution of a running script for the specified interval
 481 |     Parameters:
 482 |       milliseconds (number): thousands of a second
 483 |     Returns:
 484 |       None
 485 |     Example:
 486 |       import rhinoscriptsyntax as rs
 487 |       print("This")
 488 |       rs.Sleep(2000)
 489 |       print("is")
 490 |       rs.Sleep(2000)
 491 |       print("a")
 492 |       rs.Sleep(2000)
 493 |       print("slow")
 494 |       rs.Sleep(2000)
 495 |       print("message!")
 496 |     See Also:
 497 |       
 498 |     """
 499 |     time.sleep( milliseconds / 1000.0 )
 500 |     Rhino.RhinoApp.Wait() #keep the message pump alive
 501 | 
 502 | def SortPointList(points, tolerance=None):
 503 |     """Sorts list of points so they will be connected in a "reasonable" polyline order
 504 |     Parameters:
 505 |       points ({point, ...])the points to sort
 506 |       tolerance (number, optional): minimum distance between points. Points that fall within this tolerance
 507 |         will be discarded. If omitted, Rhino's internal zero tolerance is used.
 508 |     Returns:
 509 |       list(point, ...): of sorted 3D points if successful
 510 |       None: on error
 511 |     Example:
 512 |       import rhinoscriptsyntax as rs
 513 |       points = rs.GetPointCoordinates()
 514 |       if points:
 515 |           sorted = rs.SortPointList(points)
 516 |           rs.AddPolyline(sorted)
 517 |     See Also:
 518 |       SortPoints
 519 |     """
 520 |     points = coerce3dpointlist(points, True)
 521 |     if tolerance is None: tolerance = Rhino.RhinoMath.ZeroTolerance
 522 |     return list(Rhino.Geometry.Point3d.SortAndCullPointList(points, tolerance))
 523 | 
 524 | 
 525 | def SortPoints(points, ascending=True, order=0):
 526 |     """Sorts the components of an array of 3D points
 527 |     Parameters:
 528 |       points ([point, ...]): points to sort
 529 |       ascending (bool, optional: ascending if omitted (True) or True, descending if False.
 530 |       order (number, optional): the component sort order
 531 |         Value       Component Sort Order
 532 |         0 (default) X, Y, Z
 533 |         1           X, Z, Y
 534 |         2           Y, X, Z
 535 |         3           Y, Z, X
 536 |         4           Z, X, Y
 537 |         5           Z, Y, X
 538 |     Returns:
 539 |       list(point, ...): sorted 3-D points if successful
 540 |       None: if not successful
 541 |     Example:
 542 |       import rhinoscriptsyntax as rs
 543 |       points = rs.GetPoints()
 544 |       if points:
 545 |           points = rs.SortPoints(points)
 546 |           for p in points: print(p)
 547 |     See Also:
 548 |       
 549 |     """
 550 |     __attrXYZ = attrgetter('X', 'Y', 'Z')
 551 |     __attrXZY = attrgetter('X', 'Z', 'Y')
 552 |     __attrYXZ = attrgetter('Y', 'X', 'Z')
 553 |     __attrYZX = attrgetter('Y', 'Z', 'X')
 554 |     __attrZXY = attrgetter('Z', 'X', 'Y')
 555 |     __attrZYX = attrgetter('Z', 'Y', 'X')
 556 |     __attrgetter = (__attrXYZ, __attrXZY, __attrYXZ, __attrYZX, __attrZXY, __attrZYX)[order]
 557 |     return sorted(points, key=__attrgetter, reverse=not ascending)
 558 | 
 559 | 
 560 | def Str2Pt(point):
 561 |     """convert a formatted string value into a 3D point value
 562 |     Parameters:
 563 |       point (str): A string that contains a delimited point like "1,2,3".
 564 |     Returns:
 565 |       point: Point structure from the input string.
 566 |       None: error on invalid format
 567 |     Example:
 568 |       import rhinoscriptsyntax as rs
 569 |       point = rs.Str2Pt("1,2,3")
 570 |       if point: rs.AddPoint( point )
 571 |     See Also:
 572 |       
 573 |     """
 574 |     return coerce3dpoint(point, True)
 575 | 
 576 | 
 577 | def clamp(lowvalue, highvalue, value):
 578 |     if lowvalue>=highvalue: raise Exception("lowvalue must be less than highvalue")
 579 |     if value<lowvalue: return lowvalue
 580 |     if value>highvalue: return highvalue
 581 |     return value
 582 | 
 583 | 
 584 | def fxrange(start, stop, step):
 585 |     "float version of the xrange function"
 586 |     if step==0: raise ValueError("step must not equal 0")
 587 |     x = start
 588 |     if start<stop:
 589 |         if step<0: raise ValueError("step must be greater than 0")
 590 |         while x<=stop:
 591 |             yield x
 592 |             x+=step
 593 |     else:
 594 |         if step>0: raise ValueError("step must be less than 0")
 595 |         while x>=stop:
 596 |             yield x
 597 |             x+=step
 598 | 
 599 | 
 600 | def frange(start, stop, step):
 601 |     "float version of the range function"
 602 |     return [x for x in fxrange(start, stop, step)]
 603 | 
 604 | 
 605 | def coerce3dpoint(point, raise_on_error=False):
 606 |     """Converts input into a Rhino.Geometry.Point3d if possible.
 607 |     Parameters:
 608 |       point = Point3d, Vector3d, Point3f, Vector3f, str, uuid
 609 |       raise_on_error [opt] = True or False
 610 |     Returns:
 611 |       a Rhino.Geometry.Point3d
 612 |     Example:
 613 |     See Also:
 614 |     """
 615 |     if type(point) is Rhino.Geometry.Point3d: return point
 616 |     enumerable = compat.GET_HOST().Coerce3dPointFromEnumerables(point)
 617 |     if enumerable is not None: return enumerable
 618 |     if type(point) is System.Guid:
 619 |         found, pt = scriptcontext.doc.Objects.TryFindPoint(point)
 620 |         if found: return pt
 621 |     if hasattr(point, "__len__") and len(point)==3 and hasattr(point, "__getitem__"):
 622 |         try:
 623 |             return Rhino.Geometry.Point3d(float(point[0]), float(point[1]), float(point[2]))
 624 |         except:
 625 |             if raise_on_error: raise
 626 |     if type(point) is Rhino.Geometry.Vector3d or type(point) is Rhino.Geometry.Point3f or type(point) is Rhino.Geometry.Vector3f:
 627 |         return Rhino.Geometry.Point3d(point.X, point.Y, point.Z)
 628 |     if type(point) is str:
 629 |         point = point.split(',')
 630 |         return Rhino.Geometry.Point3d( float(point[0]), float(point[1]), float(point[2]) )
 631 |     if hasattr(point, "__len__") and len(point)==2 and hasattr(point, "__getitem__"):
 632 |         try:
 633 |             return Rhino.Geometry.Point3d(float(point[0]), float(point[1]), 0.0)
 634 |         except:
 635 |             if raise_on_error: raise
 636 |     if raise_on_error: raise ValueError("Could not convert %s to a Point3d" % point)
 637 | 
 638 | 
 639 | def CreatePoint(point, y=None, z=None):
 640 |     """Converts 'point' into a Rhino.Geometry.Point3d if possible.
 641 |     If the provided object is already a point, it value is copied.
 642 |     In case the conversion fails, an error is raised.
 643 |     Alternatively, you can also pass two coordinates singularly for a
 644 |     point on the XY plane, or three for a 3D point.
 645 |     Parameters:
 646 |       point (Point3d|Vector3d|Point3f|Vector3f|str|guid|[number, number, number])
 647 |     Returns:
 648 |       point: a Rhino.Geometry.Point3d. This can be seen as an object with three indices:
 649 |         [0]  X coordinate
 650 |         [1]  Y coordinate
 651 |         [2]  Z coordinate.
 652 |     Example:
 653 |     See Also:
 654 |     """
 655 |     if y is not None: return Rhino.Geometry.Point3d(float(point), float(y), float(z or 0.0))
 656 |     if type(point) is System.Drawing.Color: return Rhino.Geometry.Point3d(point)
 657 |     return coerce3dpoint(point, True)
 658 | 
 659 | 
 660 | def coerce2dpoint(point, raise_on_error=False):
 661 |     """Convert input into a Rhino.Geometry.Point2d if possible.
 662 |     Parameters:
 663 |       point = Point2d, list, tuple, Vector3d, Point3d, str
 664 |       raise_on_error [opt] = True or False
 665 |     Returns:
 666 |       a Rhino.Geometry.Point2d
 667 |     Example:
 668 |     See Also:
 669 |     """
 670 |     if type(point) is Rhino.Geometry.Point2d: return point
 671 |     if type(point) is list or type(point) is tuple:
 672 |         length = len(point)
 673 |         if length==2 and type(point[0]) is not list and type(point[0]) is not Rhino.Geometry.Point2d:
 674 |             return Rhino.Geometry.Point2d(point[0], point[1])
 675 |     if type(point) is Rhino.Geometry.Vector3d or type(point) is Rhino.Geometry.Point3d:
 676 |         return Rhino.Geometry.Point2d(point.X, point.Y)
 677 |     if type(point) is str:
 678 |         point = point.split(',')
 679 |         return Rhino.Geometry.Point2d( float(point[0]), float(point[1]) )
 680 |     if raise_on_error: raise ValueError("Could not convert %s to a Point2d" % point)
 681 | 
 682 | 
 683 | def coerce3dvector(vector, raise_on_error=False):
 684 |     """Convert input into a Rhino.Geometry.Vector3d if possible.
 685 |     Parameters:
 686 |       vector = Vector3d, Point3d, list, Point3f, Vector3f, str, uuid
 687 |       raise_on_error [opt] = True or False
 688 |     Returns:
 689 |       a Rhino.Geometry.Vector3d
 690 |     Example:
 691 |     See Also:
 692 |     """
 693 |     if type(vector) is Rhino.Geometry.Vector3d: return vector
 694 |     point = coerce3dpoint(vector, False)
 695 |     if point: return Rhino.Geometry.Vector3d(point.X, point.Y, point.Z)
 696 |     if raise_on_error: raise ValueError("Could not convert %s to a Vector3d" % vector)
 697 | 
 698 | 
 699 | def CreateVector(vector, y=None, z=None):
 700 |     """Converts 'vector' into a Rhino.Geometry.Vector3d if possible.
 701 |     If the provided object is already a vector, it value is copied.
 702 |     If the conversion fails, an error is raised.
 703 |     Alternatively, you can also pass two coordinates singularly for a
 704 |     vector on the XY plane, or three for a 3D vector.
 705 |     Parameters:
 706 |       vector (Vector3d|Point3d|Point3f|Vector3f\str|guid|[number, number, number])
 707 |       raise_on_error (bool, optionals): True or False
 708 |     Returns:
 709 |       a Rhino.Geometry.Vector3d. This can be seen as an object with three indices:
 710 |       result[0]: X component, result[1]: Y component, and result[2] Z component.
 711 |     Example:
 712 |     See Also:
 713 |     """
 714 |     if y is not None: return Rhino.Geometry.Vector3d(float(vector), float(y), float(z or 0.0))
 715 |     if type(vector) is Rhino.Geometry.Vector3d: return Rhino.Geometry.Vector3d(vector)
 716 |     return coerce3dvector(vector, True)
 717 | 
 718 | 
 719 | def coerce3dpointlist(points, raise_on_error=False):
 720 |     if isinstance(points, System.Array[Rhino.Geometry.Point3d]):
 721 |         return list(points)
 722 |     if isinstance(points, Rhino.Collections.Point3dList): return list(points)
 723 |     if type(points) is list or type(points) is tuple:
 724 |         count = len(points)
 725 |         if count>10 and type(points[0]) is Rhino.Geometry.Point3d: return points
 726 |         if count>0 and (coerce3dpoint(points[0]) is not None):
 727 |             return [coerce3dpoint(points[i], raise_on_error) for i in compat.RANGE(count)]
 728 |         elif count>2 and type(points[0]) is not list:
 729 |             point_count = count/3
 730 |             rc = []
 731 |             for i in compat.RANGE(point_count):
 732 |                 pt = Rhino.Geometry.Point3d(points[i*3], points[i*3+1], points[i*3+2])
 733 |                 rc.append(pt)
 734 |             return rc
 735 |     if hasattr(points, '__iter__'):
 736 |         return [coerce3dpoint(pt, raise_on_error) for pt in points]
 737 |     if raise_on_error: raise ValueError("Could not convert %s to a list of points" % points)
 738 | 
 739 | 
 740 | def coerce2dpointlist(points):
 741 |     if points is None or isinstance(points, System.Array[Rhino.Geometry.Point2d]):
 742 |         return points
 743 |     if type(points) is list or type(points) is tuple:
 744 |         count = len(points)
 745 |         if count>0 and type(points[0]) is Rhino.Geometry.Point2d:
 746 |             rc = System.Array.CreateInstance(Rhino.Geometry.Point2d, count)
 747 |             for i in compat.RANGE(count): rc[i] = points[i]
 748 |             return rc
 749 |         elif count>1 and type(points[0]) is not list:
 750 |             point_count = count/2
 751 |             rc = System.Array.CreateInstance(Rhino.Geometry.Point2d,point_count)
 752 |             for i in compat.RANGE(point_count):
 753 |                 rc[i] = Rhino.Geometry.Point2d(points[i*2], points[i*2+1])
 754 |             return rc
 755 |         elif count>0 and type(points[0]) is list:
 756 |             point_count = count
 757 |             rc = System.Array.CreateInstance(Rhino.Geometry.Point2d,point_count)
 758 |             for i in compat.RANGE(point_count):
 759 |                 pt = points[i]
 760 |                 rc[i] = Rhino.Geometry.Point2d(pt[0],pt[1])
 761 |             return rc
 762 |         return None
 763 |     return None
 764 | 
 765 | 
 766 | def coerceplane(plane, raise_on_bad_input=False):
 767 |     """Convert input into a Rhino.Geometry.Plane if possible.
 768 |     Parameters:
 769 |       plane = Plane, list, tuple
 770 |     Returns:
 771 |       a Rhino.Geometry.Plane
 772 |     Example:
 773 |     See Also:
 774 |     """
 775 |     if type(plane) is Rhino.Geometry.Plane: return plane
 776 |     if type(plane) is list or type(plane) is tuple:
 777 |         length = len(plane)
 778 |         if length == 1:
 779 |             point = coerce3dpoint(plane, False)
 780 |             if point: plane = point; length = 3
 781 |             elif plane[0] is list or plane[0] is tuple: return coerceplane(plane[0])
 782 |         if length==3 and type(plane[0]) is not list:
 783 |             rc = Rhino.Geometry.Plane.WorldXY
 784 |             rc.Origin = Rhino.Geometry.Point3d(plane[0],plane[1],plane[2])
 785 |             return rc
 786 |         if length==9 and type(plane[0]) is not list:
 787 |             origin = Rhino.Geometry.Point3d(plane[0],plane[1],plane[2])
 788 |             xpoint = Rhino.Geometry.Point3d(plane[3],plane[4],plane[5])
 789 |             ypoint = Rhino.Geometry.Point3d(plane[6],plane[7],plane[8])
 790 |             rc     = Rhino.Geometry.Plane(origin, xpoint, ypoint)
 791 |             return rc
 792 |         if (length==3 or length==4) and (type(plane[0]) is list or type(plane[0]) is tuple):
 793 |             origin = Rhino.Geometry.Point3d(plane[0][0],plane[0][1],plane[0][2])
 794 |             xpoint = Rhino.Geometry.Point3d(plane[1][0],plane[1][1],plane[1][2])
 795 |             ypoint = Rhino.Geometry.Point3d(plane[2][0],plane[2][1],plane[2][2])
 796 |             rc     = Rhino.Geometry.Plane(origin, xpoint, ypoint)
 797 |             return rc
 798 |     if raise_on_bad_input: raise TypeError("%s can not be converted to a Plane"%plane)
 799 | 
 800 | 
 801 | def CreatePlane(plane_or_origin, x_axis=None, y_axis=None, ignored=None):
 802 |     """Converts input into a Rhino.Geometry.Plane object if possible.
 803 |     If the provided object is already a plane, its value is copied.
 804 |     The returned data is accessible by indexing[origin, X axis, Y axis, Z axis], and that is the suggested method to interact with the type.
 805 |     The Z axis is in any case computed from the X and Y axes, so providing it is possible but not required.
 806 |     If the conversion fails, an error is raised.
 807 |     Parameters:
 808 |       plane (plane|point|point, vector, vector|[point, vector, vector])
 809 |     Returns:
 810 |       plane: A Rhino.Geometry.plane.
 811 |     Example:
 812 |     See Also:
 813 |     """
 814 |     if type(plane_or_origin) is Rhino.Geometry.Plane: return plane_or_origin.Clone()
 815 |     if x_axis != None:
 816 |         if y_axis == None: raise Exception("A value for the Y axis is expected if the X axis is specified.")
 817 |         origin = coerce3dpoint(plane_or_origin, True)
 818 |         x_axis = coerce3dvector(x_axis, True)
 819 |         y_axis = coerce3dvector(y_axis, True)
 820 |         return Rhino.Geometry.Plane(origin, x_axis, y_axis)
 821 |     return coerceplane(plane_or_origin, True)
 822 | 
 823 | 
 824 | def coercexform(xform, raise_on_bad_input=False):
 825 |     """Convert input into a Rhino.Transform if possible.
 826 |     Parameters:
 827 |       xform = the xform
 828 |       raise_on_bad_input [opt] = True or False
 829 |     Example:
 830 |     See Also:
 831 |     """
 832 |     t = type(xform)
 833 |     if t is Rhino.Geometry.Transform: return xform
 834 |     if( (t is list or t is tuple) and len(xform)==4 and len(xform[0])==4):
 835 |         xf = Rhino.Geometry.Transform()
 836 |         for i in range(4):
 837 |             for j in range(4):
 838 |                 xf[i,j] = xform[i][j]
 839 |         return xf
 840 |     if raise_on_bad_input: raise TypeError("%s can not be converted to a Transform"%xform)
 841 | 
 842 | 
 843 | def CreateXform(xform):
 844 |     """Converts input into a Rhino.Geometry.Transform object if possible.
 845 |     If the provided object is already a transform, its value is copied.
 846 |     The returned data is accessible by indexing[row, column], and that is the suggested method to interact with the type.
 847 |     If the conversion fails, an error is raised.
 848 |     Parameters:
 849 |       xform (list): the transform. This can be seen as a 4x4 matrix, given as nested lists or tuples.
 850 |     Returns:
 851 |       transform: A Rhino.Geometry.Transform. result[0,3] gives access to the first row, last column.
 852 |     Example:
 853 |     See Also:
 854 |     """
 855 |     if type(xform) is Rhino.Geometry.Transform: return xform.Clone()
 856 |     return coercexform(xform, True)
 857 | 
 858 | 
 859 | def coerceguid(id, raise_exception=False):
 860 |     if type(id) is System.Guid: return id
 861 |     if type(id) is str and len(id)>30:
 862 |         try:
 863 |             id = System.Guid(id)
 864 |             return id
 865 |         except:
 866 |             pass
 867 |     if (type(id) is list or type(id) is tuple) and len(id)==1:
 868 |         return coerceguid(id[0], raise_exception)
 869 |     if type(id) is Rhino.DocObjects.ObjRef: return id.ObjectId
 870 |     if isinstance(id,Rhino.DocObjects.RhinoObject): return id.Id
 871 |     if raise_exception: raise TypeError("Parameter must be a Guid or string representing a Guid")
 872 | 
 873 | 
 874 | def coerceguidlist(ids):
 875 |     if ids is None: return None
 876 |     rc = []
 877 |     if( type(ids) is list or type(ids) is tuple ): pass
 878 |     else: ids = [ids]
 879 |     for id in ids:
 880 |         id = coerceguid(id)
 881 |         if id: rc.append(id)
 882 |     if rc: return rc
 883 | 
 884 | 
 885 | def coerceboundingbox(bbox, raise_on_bad_input=False):
 886 |     if type(bbox) is Rhino.Geometry.BoundingBox: return bbox
 887 |     points = coerce3dpointlist(bbox)
 888 |     if points: return Rhino.Geometry.BoundingBox(points)
 889 |     if raise_on_bad_input: raise TypeError("%s can not be converted to a BoundingBox"%bbox)
 890 | 
 891 | 
 892 | def coercecolor(c, raise_if_bad_input=False):
 893 |     if type(c) is System.Drawing.Color: return c
 894 |     if type(c) is list or type(c) is tuple:
 895 |         if len(c)==3: return System.Drawing.Color.FromArgb(c[0], c[1], c[2])
 896 |         elif len(c)==4: return System.Drawing.Color.FromArgb(c[3], c[0], c[1], c[2])
 897 |     if type(c)==type(1): return System.Drawing.Color.FromArgb(c)
 898 |     if raise_if_bad_input: raise TypeError("%s can not be converted to a Color"%c)
 899 | 
 900 | 
 901 | def CreateColor(color, g=None, b=None, a=None):
 902 |     """Converts 'color' into a native color object if possible.
 903 |     The returned data is accessible by indexing, and that is the suggested method to interact with the type.
 904 |     Red index is [0], Green index is [1], Blue index is [2] and Alpha index is [3].
 905 |     If the provided object is already a color, its value is copied.
 906 |     Alternatively, you can also pass three coordinates singularly for an RGB color, or four
 907 |     for an RGBA color point.
 908 |     Parameters:
 909 |       color ([number, number, number]): list or 3 or 4 items. Also, a single int can be passed and it will be bitwise-parsed.
 910 |     Returns:
 911 |       color: An object that can be indexed for red, green, blu, alpha. Item[0] is red.
 912 |     Example:
 913 |     See Also:
 914 |     """
 915 |     if g is not None and b is not None: return System.Drawing.Color.FromArgb(int(a or 255), int(color), int(g), int(b))
 916 |     if type(color) is System.Drawing.Color: return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B)
 917 |     return coercecolor(color, True)
 918 | 
 919 | 
 920 | def coerceline(line, raise_if_bad_input=False):
 921 |     if type(line) is Rhino.Geometry.Line: return line
 922 |     guid = coerceguid(line, False)
 923 |     if guid: line = scriptcontext.doc.Objects.Find(guid).Geometry
 924 |     if isinstance(line, Rhino.Geometry.Curve) and line.IsLinear:
 925 |         return Rhino.Geometry.Line(line.PointAtStart, line.PointAtEnd)
 926 |     points = coerce3dpointlist(line, raise_if_bad_input)
 927 |     if points and len(points)>1: return Rhino.Geometry.Line(points[0], points[1])
 928 |     if raise_if_bad_input: raise TypeError("%s can not be converted to a Line"%line)
 929 | 
 930 | 
 931 | def coercegeometry(id, raise_if_missing=False):
 932 |     """attempt to get GeometryBase class from given input
 933 |     Parameters:
 934 |       id = geometry identifier
 935 |       raise_if_missing [opt] = True or False
 936 |     Example:
 937 |     See Also:
 938 |     """
 939 |     if isinstance(id, Rhino.Geometry.GeometryBase): return id
 940 |     if type(id) is Rhino.DocObjects.ObjRef: return id.Geometry()
 941 |     if isinstance(id, Rhino.DocObjects.RhinoObject): return id.Geometry
 942 |     id = coerceguid(id, raise_if_missing)
 943 |     if id:
 944 |         rhobj = scriptcontext.doc.Objects.Find(id)
 945 |         if rhobj: return rhobj.Geometry
 946 |     if raise_if_missing: raise ValueError("unable to convert %s into geometry"%id)
 947 | 
 948 | 
 949 | def coercebrep(id, raise_if_missing=False):
 950 |     """attempt to get polysurface geometry from the document with a given id
 951 |     Parameters:
 952 |       id = id to be coerced into a brep
 953 |       raise_if_missing [opt] = True or False
 954 |     Returns:
 955 |       a Rhino.Geometry.Brep
 956 |     Example:
 957 |     See Also:
 958 |     """
 959 |     geom = coercegeometry(id, False)
 960 |     if isinstance(geom, Rhino.Geometry.Brep): return geom
 961 |     if isinstance(geom, Rhino.Geometry.Extrusion): return geom.ToBrep(True)
 962 |     if raise_if_missing: raise ValueError("unable to convert %s into Brep geometry"%id)
 963 | 
 964 | 
 965 | def coercecurve(id, segment_index=-1, raise_if_missing=False):
 966 |     """attempt to get curve geometry from the document with a given id
 967 |     Parameters:
 968 |       id = id to be coerced into a curve
 969 |       segment_index [opt] = index of segment to retrieve
 970 |       raise_if_missing [opt] = True or False
 971 |     Example:
 972 |     See Also:
 973 |     """
 974 |     if isinstance(id, Rhino.Geometry.Curve): return id
 975 |     if type(id) is Rhino.DocObjects.ObjRef: return id.Curve()
 976 |     id = coerceguid(id, True)
 977 |     crvObj = scriptcontext.doc.Objects.Find(id)
 978 |     if crvObj:
 979 |         curve = crvObj.Geometry
 980 |         if curve and segment_index>=0 and type(curve) is Rhino.Geometry.PolyCurve:
 981 |             curve = curve.SegmentCurve(segment_index)
 982 |         if isinstance(curve, Rhino.Geometry.Curve): return curve
 983 |     if raise_if_missing: raise ValueError("unable to convert %s into Curve geometry"%id)
 984 | 
 985 | 
 986 | def coercesurface(object_id, raise_if_missing=False):
 987 |     """attempt to get surface geometry from the document with a given id
 988 |     Parameters:
 989 |       object_id = the object's identifier
 990 |       raise_if_missing [opt] = True or False
 991 |     Returns:
 992 |       a Rhino.Geometry.Surface
 993 |     Example:
 994 |     See Also:
 995 |     """
 996 |     if isinstance(object_id, Rhino.Geometry.Surface): return object_id
 997 |     if isinstance(object_id, Rhino.Geometry.Brep) and object_id.Faces.Count==1: return object_id.Faces[0]
 998 |     if type(object_id) is Rhino.DocObjects.ObjRef: return object_id.Face()
 999 |     object_id = coerceguid(object_id, True)
1000 |     srfObj = scriptcontext.doc.Objects.Find(object_id)
1001 |     if srfObj:
1002 |         srf = srfObj.Geometry
1003 |         if isinstance(srf, Rhino.Geometry.Surface): return srf
1004 |         #single face breps are considered surfaces in the context of scripts
1005 |         if isinstance(srf, Rhino.Geometry.Brep) and srf.Faces.Count==1:
1006 |             return srf.Faces[0]
1007 |     if raise_if_missing: raise ValueError("unable to convert %s into Surface geometry"%object_id)
1008 | 
1009 | 
1010 | def coercemesh(object_id, raise_if_missing=False):
1011 |     """attempt to get mesh geometry from the document with a given id
1012 |     Parameters:
1013 |       object_id = object identifier
1014 |       raise_if_missing [opt] = True or False
1015 |     Returns:
1016 |       a Rhino.Geometry.Mesh
1017 |     Example:
1018 |     See Also:
1019 |     """
1020 |     if type(object_id) is Rhino.DocObjects.ObjRef: return object_id.Mesh()
1021 |     if isinstance(object_id, Rhino.Geometry.Mesh): return object_id
1022 |     object_id = coerceguid(object_id, raise_if_missing)
1023 |     if object_id: 
1024 |         meshObj = scriptcontext.doc.Objects.Find(object_id)
1025 |         if meshObj:
1026 |             mesh = meshObj.Geometry
1027 |             if isinstance(mesh, Rhino.Geometry.Mesh): return mesh
1028 |     if raise_if_missing: raise ValueError("unable to convert %s into Mesh geometry"%object_id)
1029 | 
1030 | 
1031 | def coercerhinoobject(object_id, raise_if_bad_input=False, raise_if_missing=False):
1032 |     """attempt to get RhinoObject from the document with a given id
1033 |     Parameters:
1034 |         object_id = object's identifier
1035 |         raise_if_bad_input [opt] = True or False
1036 |         raise_if_missing [opt] = True or False
1037 |     Returns:
1038 |       a RhinoObject
1039 |     Example:
1040 |     See Also:
1041 |     """
1042 |     if isinstance(object_id, Rhino.DocObjects.RhinoObject): return object_id
1043 |     object_id = coerceguid(object_id, raise_if_bad_input)
1044 |     if object_id is None: return None
1045 |     rc = scriptcontext.doc.Objects.Find(object_id)
1046 |     if not rc and raise_if_missing: raise ValueError("%s does not exist in ObjectTable" % object_id)
1047 |     return rc
1048 | 
1049 | def CreateInterval(interval, y=None):
1050 |     """Converts 'interval' into a Rhino.Geometry.Interval.
1051 |     If the provided object is already an interval, its value is copied.
1052 |     In case the conversion fails, an error is raised.
1053 |     In case a single number is provided, it will be translated to an increasing interval that includes
1054 |     the provided input and 0. If two values are provided, they will be used instead.
1055 |     Parameters:
1056 |       interval ([number, number]): or any item that can be accessed at index 0 and 1; an Interval
1057 |     Returns:
1058 |       interval: a Rhino.Geometry.Interval. This can be seen as an object made of two items:
1059 |         [0] start of interval
1060 |         [1] end of interval
1061 |     Example:
1062 |     See Also:
1063 |     """
1064 |     if y is not None: return Rhino.Geometry.Interval(float(interval), float(y))
1065 |     if isinstance(interval, numbers.Number):
1066 |         return Rhino.Geometry.Interval(interval if interval < 0 else 0, interval if interval > 0 else 0)
1067 |     try:
1068 |         return Rhino.Geometry.Interval(interval[0], interval[1])
1069 |     except:
1070 |         raise ValueError("unable to convert %s into an Interval: it cannot be indexed."%interval)
1071 | 
```

--------------------------------------------------------------------------------
/rhino_mcp_server/static/document.py:
--------------------------------------------------------------------------------

```python
  1 | import math
  2 | 
  3 | import System
  4 | import System.Drawing
  5 | import System.IO
  6 | 
  7 | import Rhino
  8 | 
  9 | import scriptcontext
 10 | 
 11 | from rhinoscript import utility as rhutil
 12 | 
 13 | 
 14 | def _SetRenderMeshAndUpdateStyle(current):
 15 |     scriptcontext.doc.SetCustomMeshingParameters(current)
 16 |     scriptcontext.doc.MeshingParameterStyle = Rhino.Geometry.MeshingParameterStyle.Custom
 17 | 
 18 | 
 19 | def CreatePreviewImage(filename, view=None, size=None, flags=0, wireframe=False):
 20 |     """Create a bitmap preview image of the current model
 21 |     Parameters:
 22 |       filename (str): name of the bitmap file to create
 23 |       view (str, optional): title of the view. If omitted, the active view is used
 24 |       size (number, optional): two integers that specify width and height of the bitmap
 25 |       flags (number, optional): Bitmap creation flags. Can be the combination of:
 26 |           1 = honor object highlighting
 27 |           2 = draw construction plane
 28 |           4 = use ghosted shading
 29 |       wireframe (bool, optional): If True then a wireframe preview image. If False,
 30 |           a rendered image will be created
 31 |     Returns:
 32 |       bool: True or False indicating success or failure
 33 |     Example:
 34 |       import rhinoscriptsyntax as  rs
 35 |       result = rs.CreatePreviewImage("test.jpg")
 36 |       if result:
 37 |           print( "test.jpg created successfully.")
 38 |       else:
 39 |           print( "Unable to create preview image.")
 40 |     See Also:
 41 |       ExtractPreviewImage
 42 |     """
 43 |     rhview = scriptcontext.doc.Views.ActiveView
 44 |     if view is not None:
 45 |         rhview = scriptcontext.doc.Views.Find(view, False)
 46 |         if rhview is None: return False
 47 |     rhsize = rhview.ClientRectangle.Size
 48 |     if size: rhsize = System.Drawing.Size(size[0], size[1])
 49 |     ignore_highlights = (flags&1)!=1
 50 |     drawcplane = (flags&2)==2
 51 |     useghostedshading = (flags&4)==4
 52 |     if wireframe:
 53 |         return rhview.CreateWireframePreviewImage(filename, rhsize, ignore_highlights, drawcplane)
 54 |     else:
 55 |         return rhview.CreateShadedPreviewImage(filename, rhsize, ignore_highlights, drawcplane, useghostedshading)
 56 | 
 57 | 
 58 | def DocumentModified(modified=None):
 59 |     """Returns or sets the document's modified flag. This flag indicates whether
 60 |     or not any changes to the current document have been made. NOTE: setting the
 61 |     document modified flag to False will prevent the "Do you want to save this
 62 |     file..." from displaying when you close Rhino.
 63 |     Parameters:
 64 |       modified (bool): the modified state, either True or False
 65 |     Returns:
 66 |       bool: if no modified state is specified, the current modified state
 67 |       bool: if a modified state is specified, the previous modified state
 68 |     Example:
 69 |       import rhinoscriptsyntax as rs
 70 |       modified = rs.IsDocumentModified()
 71 |       if not modified: rs.DocumentModified(True)
 72 |     See Also:
 73 |       IsDocumentModified
 74 |     """
 75 |     oldstate = scriptcontext.doc.Modified
 76 |     if modified is not None and modified!=oldstate:
 77 |         scriptcontext.doc.Modified = modified
 78 |     return oldstate
 79 | 
 80 | 
 81 | def DocumentName():
 82 |     """Returns the name of the currently loaded Rhino document (3DM file)
 83 |     Returns:
 84 |       str: the name of the currently loaded Rhino document (3DM file)
 85 |     Example:
 86 |       import rhinoscriptsyntax as rs
 87 |       name = rs.DocumentName()
 88 |       print(name)
 89 |     See Also:
 90 |       DocumentPath
 91 |     """
 92 |     return scriptcontext.doc.Name or None
 93 | 
 94 | 
 95 | def DocumentPath():
 96 |     """Returns path of the currently loaded Rhino document (3DM file)
 97 |     Returns:
 98 |       str: the path of the currently loaded Rhino document (3DM file)
 99 |     Example:
100 |       import rhinoscriptsyntax as rs
101 |       path = rs.DocumentPath()
102 |       print(path)
103 |     See Also:
104 |       DocumentName
105 |     """
106 |     # GetDirectoryName throws an exception if an empty string is passed hence the 'or None'
107 |     path = System.IO.Path.GetDirectoryName(scriptcontext.doc.Path or None)
108 |     # add \ or / at the end to be consistent with RhinoScript
109 |     if path and not path.endswith(str(System.IO.Path.DirectorySeparatorChar)):
110 |       path += System.IO.Path.DirectorySeparatorChar
111 |     return path
112 | 
113 | 
114 | def EnableRedraw(enable=True):
115 |     """Enables or disables screen redrawing
116 |     Parameters:
117 |       enable (bool, optional): True to enable, False to disable
118 |     Returns: 
119 |       bool: previous screen redrawing state
120 |     Example:
121 |       import rhinoscriptsyntax as rs
122 |       redraw = rs.EnableRedraw(True)
123 |     See Also:
124 |       Redraw
125 |     """
126 |     old = scriptcontext.doc.Views.RedrawEnabled
127 |     if old!=enable: scriptcontext.doc.Views.RedrawEnabled = enable
128 |     return old
129 | 
130 | 
131 | def ExtractPreviewImage(filename, modelname=None):
132 |     """Extracts the bitmap preview image from the specified model (.3dm)
133 |     Parameters:
134 |       filename (str): name of the bitmap file to create. The extension of
135 |          the filename controls the format of the bitmap file created.
136 |          (.bmp, .tga, .jpg, .jpeg, .pcx, .png, .tif, .tiff)
137 |       modelname (str, optional): The model (.3dm) from which to extract the
138 |          preview image. If omitted, the currently loaded model is used.
139 |     Returns:
140 |       bool: True or False indicating success or failure
141 |     Example:
142 |       import rhinoscriptsyntax as rs
143 |       result = rs.ExtractPreviewImage("test.jpg")
144 |       if result:
145 |           print("Test.jpg created successfully.")
146 |       else:
147 |           print("Unable to extract preview image.")
148 |     See Also:
149 |       CreatePreviewImage
150 |     """
151 |     return scriptcontext.doc.ExtractPreviewImage(filename, modelname)
152 | 
153 | 
154 | def IsDocumentModified():
155 |     """Verifies that the current document has been modified in some way
156 |     Returns:
157 |       bool: True or False. None on error
158 |     Example:
159 |       import rhinoscriptsyntax as rs
160 |       modified = rs.IsDocumentModified()
161 |       if not modified: rs.DocumentModified(True)
162 |     See Also:
163 |       DocumentModified
164 |     """
165 |     return scriptcontext.doc.Modified
166 | 
167 | 
168 | def Notes(newnotes=None):
169 |     """Returns or sets the document's notes. Notes are generally created
170 |     using Rhino's Notes command
171 |     Parameters:
172 |       newnotes (str): new notes to set
173 |     Returns:
174 |       str: if `newnotes` is omitted, the current notes if successful
175 |       str: if `newnotes` is specified, the previous notes if successful
176 |     Example:
177 |       import rhinoscriptsyntax as rs
178 |       notes = rs.Notes()
179 |       if notes: rs.MessageBox(notes)
180 |     See Also:
181 |       
182 |     """
183 |     old = scriptcontext.doc.Notes
184 |     if newnotes is not None: scriptcontext.doc.Notes = newnotes
185 |     return old
186 | 
187 | 
188 | def ReadFileVersion():
189 |     """Returns the file version of the current document. Use this function to
190 |     determine which version of Rhino last saved the document. Note, this
191 |     function will not return values from referenced or merged files.
192 |     Returns:
193 |       str: the file version of the current document
194 |     Example:
195 |       import rhinoscriptsyntax as rs
196 |       print("ReadFileVersion = {}".format(rs.ReadFileVersion()))
197 |     See Also:
198 |       DocumentName
199 |       DocumentPath
200 |     """
201 |     return scriptcontext.doc.ReadFileVersion()
202 | 
203 | 
204 | def Redraw():
205 |     """Redraws all views
206 |     Returns:
207 |       None 
208 |     Example:
209 |       import rhinoscriptsyntax as rs
210 |       rs.Redraw()
211 |     See Also:
212 |       EnableRedraw
213 |     """
214 |     old = scriptcontext.doc.Views.RedrawEnabled
215 |     scriptcontext.doc.Views.RedrawEnabled = True
216 |     scriptcontext.doc.Views.Redraw()
217 |     Rhino.RhinoApp.Wait()
218 |     scriptcontext.doc.Views.RedrawEnabled = old
219 | 
220 | 
221 | def RenderAntialias(style=None):
222 |     """Returns or sets render antialiasing style
223 |     Parameters:
224 |       style (number, optional): level of antialiasing (0=none, 1=normal, 2=best)
225 |     Returns:
226 |       number: if style is not specified, the current antialiasing style
227 |       number: if style is specified, the previous antialiasing style
228 |     Example:
229 |       import rhinoscriptsyntax as rs
230 |       rs.RenderAntialias(1)
231 |     See Also:
232 |       RenderColor
233 |       RenderResolution
234 |       RenderSettings
235 |     """
236 |     rc = scriptcontext.doc.RenderSettings.AntialiasLevel
237 |     if style==0 or style==1 or style==2:
238 |         settings = scriptcontext.doc.RenderSettings
239 |         settings.AntialiasLevel = style
240 |         scriptcontext.doc.RenderSettings = settings
241 |     return rc
242 | 
243 | 
244 | def RenderColor(item, color=None):
245 |     """Returns or sets the render ambient light or background color
246 |     Parameters:
247 |       item (number): 0=ambient light color, 1=background color
248 |       color (color, optional): the new color value. If omitted, the current item color is returned
249 |     Returns:
250 |       color: if color is not specified, the current item color
251 |       color: if color is specified, the previous item color
252 |     Example:
253 |       import rhinoscriptsyntax as rs
254 |       render_background_color = 1
255 |       rs.RenderColor( render_background_color, (0,0,255) )
256 |     See Also:
257 |       RenderAntialias
258 |       RenderResolution
259 |       RenderSettings
260 |     """
261 |     if item!=0 and item!=1: raise ValueError("item must be 0 or 1")
262 |     if item==0: rc = scriptcontext.doc.RenderSettings.AmbientLight
263 |     else: rc = scriptcontext.doc.RenderSettings.BackgroundColorTop
264 |     if color is not None:
265 |         color = rhutil.coercecolor(color, True)
266 |         settings = scriptcontext.doc.RenderSettings
267 |         if item==0: settings.AmbientLight = color
268 |         else: settings.BackgroundColorTop = color
269 |         scriptcontext.doc.RenderSettings = settings
270 |         scriptcontext.doc.Views.Redraw()
271 |     return rc
272 | 
273 | 
274 | def RenderResolution(resolution=None):
275 |     """Returns or sets the render resolution
276 |     Parameters:
277 |       resolution ([number, number], optional): width and height of render
278 |     Returns:
279 |       tuple(number, number): if resolution is not specified, the current resolution width,height
280 |       tuple(number, number): if resolution is specified, the previous resolution width, height
281 |     Example:
282 |       import rhinoscriptsyntax as rs
283 |       sizex, sizey = rs.Viewsize()
284 |       resolution = sizex/2 , sizey/2
285 |       rs.RenderResolution( resolution )
286 |     See Also:
287 |       RenderAntialias
288 |       RenderColor
289 |       RenderSettings
290 |     """
291 |     rc = scriptcontext.doc.RenderSettings.ImageSize
292 |     if resolution:
293 |         settings = scriptcontext.doc.RenderSettings
294 |         settings.ImageSize = System.Drawing.Size(resolution[0], resolution[1])
295 |         scriptcontext.doc.RenderSettings = settings
296 |     return rc.Width, rc.Height
297 | 
298 | 
299 | def RenderMeshDensity(density=None):
300 |     """Returns or sets the render mesh density property of the active document.
301 |         For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
302 |     Parameters:
303 |       density (number, optional): the new render mesh density, which is a number between 0.0 and 1.0.
304 |     Returns:
305 |       number: if density is not specified, the current render mesh density if successful.
306 |       number: if density is specified, the previous render mesh density if successful.
307 |     Example:
308 |       import rhinoscriptsyntax as  rs
309 |       print("Quality: %s" % rs.RenderMeshQuality())
310 |       print("Mesh density: %s" % rs.RenderMeshDensity())
311 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
312 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
313 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
314 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
315 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
316 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
317 |       print("Other settings: %s" % rs.RenderMeshSettings())
318 |     See Also:
319 |       RenderMeshDensity
320 |       RenderMeshMaxAngle
321 |       RenderMeshMaxAspectRatio
322 |       RenderMeshMaxDistEdgeToSrf
323 |       RenderMeshMaxEdgeLength
324 |       RenderMeshMinEdgeLength
325 |       RenderMeshMinInitialGridQuads
326 |       RenderMeshQuality
327 |       RenderMeshSettings
328 |     """
329 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
330 |     rc = current.RelativeTolerance
331 |     if density is not None:
332 |         if Rhino.RhinoMath.Clamp(density, 0.0, 1.0) != density: return None
333 |         current.RelativeTolerance = density
334 |         _SetRenderMeshAndUpdateStyle(current)
335 |     return rc
336 | 
337 | 
338 | def RenderMeshMaxAngle(angle_degrees=None):
339 |     """Returns or sets the render mesh maximum angle property of the active document.  
340 |       For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
341 |     Parameters:
342 |       angle_degrees (number, optional): the new maximum angle, which is a positive number in degrees.
343 |     Returns:
344 |       number: if angle_degrees is not specified, the current maximum angle if successful.
345 |       number: if angle_degrees is specified, the previous maximum angle if successful.
346 |       None: if not successful, or on error.
347 |     Example:
348 |       import rhinoscriptsyntax as  rs
349 |       print("Quality: %s" % rs.RenderMeshQuality())
350 |       print("Mesh density: %s" % rs.RenderMeshDensity())
351 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
352 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
353 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
354 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
355 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
356 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
357 |       print("Other settings: %s" % rs.RenderMeshSettings())
358 |     See Also:
359 |       RenderMeshDensity
360 |       RenderMeshMaxAngle
361 |       RenderMeshMaxAspectRatio
362 |       RenderMeshMaxDistEdgeToSrf
363 |       RenderMeshMaxEdgeLength
364 |       RenderMeshMinEdgeLength
365 |       RenderMeshMinInitialGridQuads
366 |       RenderMeshQuality
367 |       RenderMeshSettings
368 |     """
369 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
370 |     rc = math.degrees(current.RefineAngle)
371 |     if angle_degrees is not None:
372 |         if angle_degrees < 0: return None
373 |         current.RefineAngle = math.radians(angle_degrees)
374 |         _SetRenderMeshAndUpdateStyle(current)
375 |     return rc
376 | 
377 | 
378 | def RenderMeshMaxAspectRatio(ratio=None):
379 |     """Returns or sets the render mesh maximum aspect ratio property of the active document.
380 |       For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
381 |      Parameters:
382 |       ratio (number, optional): the render mesh maximum aspect ratio.  The suggested range, when not zero, is from 1 to 100.
383 |     Returns:
384 |       number: if ratio is not specified, the current render mesh maximum aspect ratio if successful.
385 |       number: if ratio is specified, the previous render mesh maximum aspect ratio if successful.
386 |       None: if not successful, or on error.
387 |     Example:
388 |       import rhinoscriptsyntax as  rs
389 |       print("Quality: %s" % rs.RenderMeshQuality())
390 |       print("Mesh density: %s" % rs.RenderMeshDensity())
391 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
392 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
393 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
394 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
395 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
396 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
397 |       print("Other settings: %s" % rs.RenderMeshSettings())
398 |     See Also:
399 |       RenderMeshDensity
400 |       RenderMeshMaxAngle
401 |       RenderMeshMaxAspectRatio
402 |       RenderMeshMaxDistEdgeToSrf
403 |       RenderMeshMaxEdgeLength
404 |       RenderMeshMinEdgeLength
405 |       RenderMeshMinInitialGridQuads
406 |       RenderMeshQuality
407 |       RenderMeshSettings
408 |     """
409 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
410 |     rc = current.GridAspectRatio
411 |     if ratio is not None:
412 |         current.GridAspectRatio = ratio
413 |         _SetRenderMeshAndUpdateStyle(current)
414 |     return rc
415 | 
416 | 
417 | def RenderMeshMaxDistEdgeToSrf(distance=None):
418 |     """Returns or sets the render mesh maximum distance, edge to surface parameter of the active document.
419 |       For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
420 |     Parameters:
421 |       distance (number, optional): the render mesh maximum distance, edge to surface.
422 |     Returns:
423 |       number: if distance is not specified, the current render mesh maximum distance, edge to surface if successful.
424 |       number: if distance is specified, the previous render mesh maximum distance, edge to surface if successful.
425 |       None: if not successful, or on error.
426 |     Example:
427 |       import rhinoscriptsyntax as  rs
428 |       print("Quality: %s" % rs.RenderMeshQuality())
429 |       print("Mesh density: %s" % rs.RenderMeshDensity())
430 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
431 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
432 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
433 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
434 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
435 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
436 |       print("Other settings: %s" % rs.RenderMeshSettings())
437 |     See Also:
438 |       RenderMeshDensity
439 |       RenderMeshMaxAngle
440 |       RenderMeshMaxAspectRatio
441 |       RenderMeshMaxDistEdgeToSrf
442 |       RenderMeshMaxEdgeLength
443 |       RenderMeshMinEdgeLength
444 |       RenderMeshMinInitialGridQuads
445 |       RenderMeshQuality
446 |       RenderMeshSettings
447 |     """
448 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
449 |     rc = current.Tolerance
450 |     if distance is not None:
451 |         current.Tolerance = distance
452 |         _SetRenderMeshAndUpdateStyle(current)
453 |     return rc
454 | 
455 | 
456 | def RenderMeshMaxEdgeLength(distance=None):
457 |     """Returns or sets the render mesh maximum edge length parameter of the active document.
458 |       For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
459 |     Parameters:
460 |       distance (number, optional): the render mesh maximum edge length.
461 |     Returns:
462 |       number: if distance is not specified, the current render mesh maximum edge length if successful.
463 |       number: if distance is specified, the previous render mesh maximum edge length if successful.
464 |       None: if not successful, or on error.
465 |     Example:
466 |       import rhinoscriptsyntax as  rs
467 |       print("Quality: %s" % rs.RenderMeshQuality())
468 |       print("Mesh density: %s" % rs.RenderMeshDensity())
469 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
470 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
471 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
472 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
473 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
474 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
475 |       print("Other settings: %s" % rs.RenderMeshSettings())
476 |     See Also:
477 |       RenderMeshDensity
478 |       RenderMeshMaxAngle
479 |       RenderMeshMaxAspectRatio
480 |       RenderMeshMaxDistEdgeToSrf
481 |       RenderMeshMaxEdgeLength
482 |       RenderMeshMinEdgeLength
483 |       RenderMeshMinInitialGridQuads
484 |       RenderMeshQuality
485 |       RenderMeshSettings
486 |     """
487 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
488 |     rc = current.MaximumEdgeLength
489 |     if distance is not None:
490 |         current.MaximumEdgeLength = distance
491 |         _SetRenderMeshAndUpdateStyle(current)
492 |     return rc
493 | 
494 | 
495 | def RenderMeshMinEdgeLength(distance=None):
496 |     """Returns or sets the render mesh minimum edge length parameter of the active document.
497 |       For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
498 |         Parameters:
499 |       distance (number, optional): the render mesh minimum edge length.
500 |     Returns:
501 |       number: if distance is not specified, the current render mesh minimum edge length if successful.
502 |       number: if distance is specified, the previous render mesh minimum edge length if successful.
503 |       None: if not successful, or on error.
504 |     Example:
505 |       import rhinoscriptsyntax as  rs
506 |       print("Quality: %s" % rs.RenderMeshQuality())
507 |       print("Mesh density: %s" % rs.RenderMeshDensity())
508 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
509 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
510 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
511 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
512 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
513 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
514 |       print("Other settings: %s" % rs.RenderMeshSettings())
515 |     See Also:
516 |       RenderMeshDensity
517 |       RenderMeshMaxAngle
518 |       RenderMeshMaxAspectRatio
519 |       RenderMeshMaxDistEdgeToSrf
520 |       RenderMeshMaxEdgeLength
521 |       RenderMeshMinEdgeLength
522 |       RenderMeshMinInitialGridQuads
523 |       RenderMeshQuality
524 |       RenderMeshSettings
525 |     """
526 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
527 |     rc = current.MinimumEdgeLength
528 |     if distance is not None:
529 |         current.MinimumEdgeLength = distance
530 |         _SetRenderMeshAndUpdateStyle(current)
531 |     return rc
532 | 
533 | 
534 | def RenderMeshMinInitialGridQuads(quads=None):
535 |     """Returns or sets the render mesh minimum initial grid quads parameter of the active document.
536 |       For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
537 |     Parameters:
538 |       quads (number, optional): the render mesh minimum initial grid quads. The suggested range is from 0 to 10000.
539 |     Returns:
540 |       number: if quads is not specified, the current render mesh minimum initial grid quads if successful.
541 |       number: if quads is specified, the previous render mesh minimum initial grid quads if successful.
542 |       None: if not successful, or on error.
543 |     Example:
544 |       import rhinoscriptsyntax as  rs
545 |       print("Quality: %s" % rs.RenderMeshQuality())
546 |       print("Mesh density: %s" % rs.RenderMeshDensity())
547 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
548 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
549 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
550 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
551 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
552 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
553 |       print("Other settings: %s" % rs.RenderMeshSettings())
554 |     See Also:
555 |       RenderMeshDensity
556 |       RenderMeshMaxAngle
557 |       RenderMeshMaxAspectRatio
558 |       RenderMeshMaxDistEdgeToSrf
559 |       RenderMeshMaxEdgeLength
560 |       RenderMeshMinEdgeLength
561 |       RenderMeshMinInitialGridQuads
562 |       RenderMeshQuality
563 |       RenderMeshSettings
564 |     """
565 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
566 |     rc = current.GridMinCount
567 |     if quads is not None:
568 |         current.GridMinCount = quads
569 |         _SetRenderMeshAndUpdateStyle(current)
570 |     return rc
571 | 
572 | 
573 | def RenderMeshQuality(quality=None):
574 |     """Returns or sets the render mesh quality of the active document.
575 |         For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
576 |       Parameters:
577 |       quality (number, optional): the render mesh quality, either:
578 |         0: Jagged and faster.  Objects may look jagged, but they should shade and render relatively quickly.
579 |         1: Smooth and slower.  Objects should look smooth, but they may take a very long time to shade and render.
580 |         2: Custom.
581 |     Returns:
582 |       number: if quality is not specified, the current render mesh quality if successful.
583 |       number: if quality is specified, the previous render mesh quality if successful.
584 |       None: if not successful, or on error.
585 |     Example:
586 |       import rhinoscriptsyntax as  rs
587 |       print("Quality: %s" % rs.RenderMeshQuality())
588 |       print("Mesh density: %s" % rs.RenderMeshDensity())
589 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
590 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
591 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
592 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
593 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
594 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
595 |       print("Other settings: %s" % rs.RenderMeshSettings())
596 |     See Also:
597 |       RenderMeshDensity
598 |       RenderMeshMaxAngle
599 |       RenderMeshMaxAspectRatio
600 |       RenderMeshMaxDistEdgeToSrf
601 |       RenderMeshMaxEdgeLength
602 |       RenderMeshMinEdgeLength
603 |       RenderMeshMinInitialGridQuads
604 |       RenderMeshQuality
605 |       RenderMeshSettings
606 |     """
607 |     current = scriptcontext.doc.MeshingParameterStyle
608 |     if current == Rhino.Geometry.MeshingParameterStyle.Fast:
609 |         rc = 0
610 |     elif current == Rhino.Geometry.MeshingParameterStyle.Quality:
611 |         rc = 1
612 |     elif current == Rhino.Geometry.MeshingParameterStyle.Custom:
613 |         rc = 2
614 |     else:
615 |         rc = None
616 |     if quality is not None:
617 |         if quality == 0:
618 |             new_value = Rhino.Geometry.MeshingParameterStyle.Fast
619 |         elif quality == 1:
620 |             new_value = Rhino.Geometry.MeshingParameterStyle.Quality
621 |         elif quality == 2:
622 |             new_value = Rhino.Geometry.MeshingParameterStyle.Custom
623 |         else:
624 |             return None
625 |         scriptcontext.doc.MeshingParameterStyle = new_value
626 |     return rc
627 | 
628 | 
629 | def RenderMeshSettings(settings=None):
630 |     """Returns or sets the render mesh settings of the active document.
631 |       For more information on render meshes, see the Document Properties: Mesh topic in the Rhino help file.
632 |     Parameters:
633 |       settings (number, optional): the render mesh settings, which is a bit-coded number that allows or disallows certain features.
634 |       The bits can be added together in any combination to form a value between 0 and 7.  The bit values are as follows:
635 |         0: No settings enabled.
636 |         1: Refine mesh enabled.
637 |         2: Jagged seams enabled.
638 |         4: Simple planes enabled.
639 |         8: Texture is packed, scaled and normalized; otherwise unpacked, unscaled and normalized.
640 |     Returns:
641 |       number: if settings is not specified, the current render mesh settings if successful.
642 |       number: if settings is specified, the previous render mesh settings if successful.
643 |       None: if not successful, or on error.
644 |     Example:
645 |       import rhinoscriptsyntax as  rs
646 |       print("Quality: %s" % rs.RenderMeshQuality())
647 |       print("Mesh density: %s" % rs.RenderMeshDensity())
648 |       print("Maximum angle: %s" % rs.RenderMeshMaxAngle())
649 |       print("Maximum aspect ratio: %s" % rs.RenderMeshMaxAspectRatio())
650 |       print("Minimun edge length: %s" % rs.RenderMeshMinEdgeLength())
651 |       print("Maximum edge length: %s" % rs.RenderMeshMaxEdgeLength())
652 |       print("Maximum distance, edge to surface: %s" % rs.RenderMeshMaxDistEdgeToSrf())
653 |       print("Minumum initial grid quads: %s" % rs.RenderMeshMinInitialGridQuads())
654 |       print("Other settings: %s" % rs.RenderMeshSettings())
655 |     See Also:
656 |       RenderMeshDensity
657 |       RenderMeshMaxAngle
658 |       RenderMeshMaxAspectRatio
659 |       RenderMeshMaxDistEdgeToSrf
660 |       RenderMeshMaxEdgeLength
661 |       RenderMeshMinEdgeLength
662 |       RenderMeshMinInitialGridQuads
663 |       RenderMeshQuality
664 |       RenderMeshSettings
665 |     """
666 |     current = scriptcontext.doc.GetCurrentMeshingParameters()
667 |     rc = 0
668 |     if current.RefineGrid: rc += 1
669 |     if current.JaggedSeams: rc += 2
670 |     if current.SimplePlanes: rc += 4
671 |     if current.TextureRange == Rhino.Geometry.MeshingParameterTextureRange.PackedScaledNormalized: rc += 8
672 |     if settings is not None:
673 |         current.RefineGrid = (settings & 1)
674 |         current.JaggedSeams = (settings & 2)
675 |         current.SimplePlanes = (settings & 4)
676 |         current.TextureRange = Rhino.Geometry.MeshingParameterTextureRange.PackedScaledNormalized if (settings & 8) else Rhino.Geometry.MeshingParameterTextureRange.UnpackedUnscaledNormalized
677 |         _SetRenderMeshAndUpdateStyle(current)
678 |     return rc
679 | 
680 | 
681 | def RenderSettings(settings=None):
682 |     """Returns or sets render settings
683 |     Parameters:
684 |       settings (number, optional): bit-coded flags of render settings to modify.
685 |         0=none,
686 |         1=create shadows,
687 |         2=use lights on layers that are off,
688 |         4=render curves and isocurves,
689 |         8=render dimensions and text
690 |     Returns:
691 |       number: if settings are not specified, the current render settings in bit-coded flags
692 |       number: if settings are specified, the previous render settings in bit-coded flags
693 |     Example:
694 |       import rhinoscriptsyntax as rs
695 |       render_annotations = 8
696 |       settings = rs.RenderSettings()
697 |       if settings & render_annotations:
698 |           settings = settings - render_annotations
699 |           rs.RenderSettings( settings )
700 |     See Also:
701 |       RenderAntialias
702 |       RenderColor
703 |       RenderResolution
704 |     """
705 |     rc = 0
706 |     rendersettings = scriptcontext.doc.RenderSettings
707 |     if rendersettings.ShadowmapLevel: rc+=1
708 |     if rendersettings.UseHiddenLights: rc+=2
709 |     if rendersettings.RenderCurves: rc+=4
710 |     if rendersettings.RenderAnnotations: rc+=8
711 |     if settings is not None:
712 |         rendersettings.ShadowmapLevel = (settings & 1)
713 |         rendersettings.UseHiddenLights = (settings & 2)==2
714 |         rendersettings.RenderCurves = (settings & 4)==4
715 |         rendersettings.RenderAnnotations = (settings & 8)==8
716 |         scriptcontext.doc.RenderSettings = rendersettings
717 |     return rc
718 | 
719 | 
720 | def UnitAbsoluteTolerance(tolerance=None, in_model_units=True):
721 |     """Resturns or sets the document's absolute tolerance. Absolute tolerance
722 |     is measured in drawing units. See Rhino's document properties command
723 |     (Units and Page Units Window) for details
724 |     Parameters:
725 |       tolerance (number, optional): the absolute tolerance to set
726 |       in_model_units (bool, optional): Return or modify the document's model units (True)
727 |                             or the document's page units (False)
728 |     Returns:
729 |       number: if tolerance is not specified, the current absolute tolerance
730 |       number: if tolerance is specified, the previous absolute tolerance
731 |     Example:
732 |       import rhinoscriptsyntax as rs
733 |       tol = rs.UnitAbsoluteTolerance()
734 |       if tol<0.01:
735 |           rs.UnitAbsoluteTolerance( 0.01 )
736 |     See Also:
737 |       UnitAngleTolerance
738 |       UnitDistanceDisplayPrecision
739 |       UnitRelativeTolerance
740 |       UnitSystem
741 |     """
742 |     if in_model_units:
743 |         rc = scriptcontext.doc.ModelAbsoluteTolerance
744 |         if tolerance is not None:
745 |             scriptcontext.doc.ModelAbsoluteTolerance = tolerance
746 |     else:
747 |         rc = scriptcontext.doc.PageAbsoluteTolerance
748 |         if tolerance is not None:
749 |             scriptcontext.doc.PageAbsoluteTolerance = tolerance
750 |     return rc
751 | 
752 | 
753 | def UnitAngleTolerance(angle_tolerance_degrees=None, in_model_units=True):
754 |     """Return or set the document's angle tolerance. Angle tolerance is
755 |     measured in degrees. See Rhino's DocumentProperties command
756 |     (Units and Page Units Window) for details
757 |     Parameters:
758 |       angle_tolerance_degrees (number, optional): the angle tolerance to set
759 |       in_model_units (number, optional): Return or modify the document's model units (True)
760 |                              or the document's page units (False)
761 |     Returns:
762 |       number: if angle_tolerance_degrees is not specified, the current angle tolerance
763 |       number: if angle_tolerance_degrees is specified, the previous angle tolerance
764 |     Example:
765 |       import rhinoscriptsyntax as rs
766 |       tol = rs.UnitAngleTolerance()
767 |       if tol<3.0:
768 |           rs.UnitAngleTolerance(3.0)
769 |     See Also:
770 |       UnitAbsoluteTolerance
771 |       UnitDistanceDisplayPrecision
772 |       UnitRelativeTolerance
773 |       UnitSystem
774 |     """
775 |     if in_model_units:
776 |         rc = scriptcontext.doc.ModelAngleToleranceDegrees
777 |         if angle_tolerance_degrees is not None:
778 |             scriptcontext.doc.ModelAngleToleranceDegrees = angle_tolerance_degrees
779 |     else:
780 |         rc = scriptcontext.doc.PageAngleToleranceDegrees
781 |         if angle_tolerance_degrees is not None:
782 |             scriptcontext.doc.PageAngleToleranceDegrees = angle_tolerance_degrees
783 |     return rc
784 | 
785 | 
786 | def UnitDistanceDisplayPrecision(precision=None, model_units=True):
787 |     """Return or set the document's distance display precision
788 |     Parameters:
789 |       precision (number, optional): The distance display precision.  If the current distance display mode is Decimal, then precision is the number of decimal places.
790 |                                     If the current distance display mode is Fractional (including Feet and Inches), then the denominator = (1/2)^precision.
791 |                                     Use UnitDistanceDisplayMode to get the current distance display mode.
792 |       model_units (bool, optional): Return or modify the document's model units (True) or the document's page units (False). The default is True.
793 |     Returns:
794 |      number: If precision is not specified, the current distance display precision if successful. If precision is specified, the previous distance display precision if successful. If not successful, or on error.
795 |     Example:
796 |       import rhinoscriptsyntax as rs
797 |       precision = 3
798 |       rs.UnitDistanceDisplayPrecision( precision )
799 |     See Also:
800 |       UnitAbsoluteTolerance
801 |       UnitAngleTolerance
802 |       UnitRelativeTolerance
803 |       UnitSystem
804 |     """
805 |     if model_units:
806 |         rc = scriptcontext.doc.ModelDistanceDisplayPrecision
807 |         if precision: scriptcontext.doc.ModelDistanceDisplayPrecision = precision
808 |         return rc
809 |     rc = scriptcontext.doc.PageDistanceDisplayPrecision
810 |     if precision: scriptcontext.doc.PageDistanceDisplayPrecision = precision
811 |     return rc
812 | 
813 | 
814 | def UnitRelativeTolerance(relative_tolerance=None, in_model_units=True):
815 |     """Return or set the document's relative tolerance. Relative tolerance
816 |     is measured in percent. See Rhino's DocumentProperties command
817 |     (Units and Page Units Window) for details
818 |     Parameters:
819 |       relative_tolerance (number, optional) the relative tolerance in percent
820 |       in_model_units (bool, optional): Return or modify the document's model units (True)
821 |                              or the document's page units (False)
822 |     Returns:
823 |       number: if relative_tolerance is not specified, the current tolerance in percent
824 |       number: if relative_tolerance is specified, the previous tolerance in percent
825 |     Example:
826 |       import rhinoscriptsyntax as rs
827 |       tol = rs.UnitRelativeTolerance()
828 |       if tol<1.0:
829 |           rs.UnitRelativeTolerance(1.0)
830 |     See Also:
831 |       UnitAbsoluteTolerance
832 |       UnitAngleTolerance
833 |       UnitDistanceDisplayPrecision
834 |       UnitSystem
835 |     """
836 |     if in_model_units:
837 |         rc = scriptcontext.doc.ModelRelativeTolerance
838 |         if relative_tolerance is not None:
839 |             scriptcontext.doc.ModelRelativeTolerance = relative_tolerance
840 |     else:
841 |         rc = scriptcontext.doc.PageRelativeTolerance
842 |         if relative_tolerance is not None:
843 |             scriptcontext.doc.PageRelativeTolerance = relative_tolerance
844 |     return rc
845 | 
846 | 
847 | def UnitScale(to_system, from_system=None):
848 |   """Return the scale factor for changing between unit systems.
849 |   Parameters:
850 |     to_system (number): The unit system to convert to. The unit systems are are:
851 |        0 - No unit system
852 |        1 - Microns (1.0e-6 meters)
853 |        2 - Millimeters (1.0e-3 meters)
854 |        3 - Centimeters (1.0e-2 meters)
855 |        4 - Meters
856 |        5 - Kilometers (1.0e+3 meters)
857 |        6 - Microinches (2.54e-8 meters, 1.0e-6 inches)
858 |        7 - Mils (2.54e-5 meters, 0.001 inches)
859 |        8 - Inches (0.0254 meters)
860 |        9 - Feet (0.3408 meters, 12 inches)
861 |       10 - Miles (1609.344 meters, 5280 feet)
862 |       11 - *Reserved for custom Unit System*
863 |       12 - Angstroms (1.0e-10 meters)
864 |       13 - Nanometers (1.0e-9 meters)
865 |       14 - Decimeters (1.0e-1 meters)
866 |       15 - Dekameters (1.0e+1 meters)
867 |       16 - Hectometers (1.0e+2 meters)
868 |       17 - Megameters (1.0e+6 meters)
869 |       18 - Gigameters (1.0e+9 meters)
870 |       19 - Yards (0.9144  meters, 36 inches)
871 |       20 - Printer point (1/72 inches, computer points)
872 |       21 - Printer pica (1/6 inches, (computer picas)
873 |       22 - Nautical mile (1852 meters)
874 |       23 - Astronomical (1.4959787e+11)
875 |       24 - Lightyears (9.46073e+15 meters)
876 |       25 - Parsecs (3.08567758e+16)
877 |     from_system (number, optional): the unit system to convert from (see above). If omitted,
878 |         the document's current unit system is used
879 |   Returns:
880 |     number: scale factor for changing between unit systems
881 |   Example:
882 |       import rhinoscriptsyntax as rs
883 |       print(rs.UnitScale(3, 4)) # 100.0
884 |       print(rs.UnitScale(3, 8)) # 2.54
885 |       print(rs.UnitScale(8, 9)) # 12.0
886 |     See Also:
887 |     UnitSystem
888 |     UnitSystemName
889 |   """
890 |   if from_system is None:
891 |       from_system = scriptcontext.doc.ModelUnitSystem
892 |   if type(from_system) is int:
893 |       from_system = System.Enum.ToObject(Rhino.UnitSystem, from_system)
894 |   if type(to_system) is int:
895 |       to_system = System.Enum.ToObject(Rhino.UnitSystem, to_system)
896 |   return Rhino.RhinoMath.UnitScale(from_system, to_system)
897 | 
898 | 
899 | def UnitSystem(unit_system=None, scale=False, in_model_units=True):
900 |     """Return or set the document's unit system. See Rhino's DocumentProperties
901 |     command (Units and Page Units Window) for details
902 |     Parameters:
903 |       unit_system (number, optional): The unit system to set the document to. The unit systems are:
904 |          0 - No unit system
905 |          1 - Microns (1.0e-6 meters)
906 |          2 - Millimeters (1.0e-3 meters)
907 |          3 - Centimeters (1.0e-2 meters)
908 |          4 - Meters
909 |          5 - Kilometers (1.0e+3 meters)
910 |          6 - Microinches (2.54e-8 meters, 1.0e-6 inches)
911 |          7 - Mils (2.54e-5 meters, 0.001 inches)
912 |          8 - Inches (0.0254 meters)
913 |          9 - Feet (0.3048 meters, 12 inches)
914 |         10 - Miles (1609.344 meters, 5280 feet)
915 |         11 - *Reserved for custom Unit System*
916 |         12 - Angstroms (1.0e-10 meters)
917 |         13 - Nanometers (1.0e-9 meters)
918 |         14 - Decimeters (1.0e-1 meters)
919 |         15 - Dekameters (1.0e+1 meters)
920 |         16 - Hectometers (1.0e+2 meters)
921 |         17 - Megameters (1.0e+6 meters)
922 |         18 - Gigameters (1.0e+9 meters)
923 |         19 - Yards (0.9144  meters, 36 inches)
924 |         20 - Printer point (1/72 inches, computer points)
925 |         21 - Printer pica (1/6 inches, (computer picas)
926 |         22 - Nautical mile (1852 meters)
927 |         23 - Astronomical (1.4959787e+11)
928 |         24 - Lightyears (9.46073e+15 meters)
929 |         25 - Parsecs (3.08567758e+16)
930 |       scale (bool, optional): Scale existing geometry based on the new unit system.
931 |           If not specified, any existing geometry is not scaled (False)
932 |       in_model_units (number, optional): Return or modify the document's model units (True)
933 |           or the document's page units (False). The default is True.
934 |     Returns:
935 |       number: if unit_system is not specified, the current unit system
936 |       number: if unit_system is specified, the previous unit system
937 |       None: on error
938 |     Example:
939 |       import rhinoscriptsyntax as rs
940 |       rhUnitMillimeters = 2
941 |       rhUnitInches = 8
942 |       current_system = rs.UnitSystem()
943 |       if current_system==rhUnitMillimeters:
944 |           rs.UnitSystem(rhUnitInches, True)
945 |     See Also:
946 |       UnitAbsoluteTolerance
947 |       UnitAngleTolerance
948 |       UnitDistanceDisplayPrecision
949 |       UnitRelativeTolerance
950 |     """
951 |     if (unit_system is not None and (unit_system<1 or unit_system>25)):
952 |         raise ValueError("unit_system value of %s is not valid"%unit_system)
953 |     if in_model_units:
954 |         rc = int(scriptcontext.doc.ModelUnitSystem)
955 |         if unit_system is not None:
956 |             unit_system = System.Enum.ToObject(Rhino.UnitSystem, unit_system)
957 |             scriptcontext.doc.AdjustModelUnitSystem(unit_system, scale)
958 |     else:
959 |         rc = int(scriptcontext.doc.PageUnitSystem)
960 |         if unit_system is not None:
961 |             unit_system = System.Enum.ToObject(Rhino.UnitSystem, unit_system)
962 |             scriptcontext.doc.AdjustPageUnitSystem(unit_system, scale)
963 |     return rc
964 | 
965 | 
966 | def UnitSystemName(capitalize=False, singular=True, abbreviate=False, model_units=True):
967 |     """Returns the name of the current unit system
968 |     Parameters:
969 |       capitalize (bool, optional): Capitalize the first character of the units system name (e.g. return "Millimeter" instead of "millimeter"). The default is not to capitalize the first character (false).
970 |       singular (bool, optional): Return the singular form of the units system name (e.g. "millimeter" instead of "millimeters"). The default is to return the singular form of the name (true).
971 |       abbreviate (bool, optional): Abbreviate the name of the units system (e.g. return "mm" instead of "millimeter"). The default is not to abbreviate the name (false).
972 |       model_units (bool, optional): Return the document's model units (True) or the document's page units (False). The default is True.
973 |     Returns:
974 |       str: The name of the current units system if successful.
975 |     Example:
976 |       import rhinoscriptsyntax as rs
977 |       system = rs.UnitSystemName(False, False, False)
978 |       print("The units system is set to{}".format(system))
979 |     See Also:
980 |       UnitSystem
981 |     """
982 |     return scriptcontext.doc.GetUnitSystemName(model_units, capitalize, singular, abbreviate)
983 | 
```
Page 3/8FirstPrevNextLast