This is page 5 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/selection.py:
--------------------------------------------------------------------------------
```python
1 | import System.Drawing
2 |
3 | import Rhino
4 |
5 | import scriptcontext
6 |
7 | import rhinocompat as compat
8 | from rhinoscript import utility as rhutil
9 | from rhinoscript import application as rhapp
10 | from rhinoscript.layer import __getlayer
11 | from rhinoscript.view import __viewhelper
12 |
13 |
14 | class filter:
15 | allobjects = 0
16 | point = 1
17 | pointcloud = 2
18 | curve = 4
19 | surface = 8
20 | polysurface = 16
21 | mesh = 32
22 | light = 256
23 | annotation = 512
24 | instance = 4096
25 | textdot = 8192
26 | grip = 16384
27 | detail = 32768
28 | hatch = 65536
29 | morph = 131072
30 | subd = 262144
31 | cage = 134217728
32 | phantom = 268435456
33 | clippingplane = 536870912
34 | extrusion = 1073741824
35 |
36 |
37 | def AllObjects(select=False, include_lights=False, include_grips=False, include_references=False):
38 | """Returns identifiers of all objects in the document.
39 | Parameters:
40 | select(bool, optional): Select the objects
41 | include_lights (bool, optional): Include light objects
42 | include_grips (bool, optional): Include grips objects
43 | Returns:
44 | list(guid, ...): identifiers for all the objects in the document
45 | Example:
46 | import rhinoscriptsyntax as rs
47 | objs = rs.AllObjects()
48 | for obj in objs: print("Object identifier: {}".format(obj))
49 | See Also:
50 | HiddenObjects
51 | LockedObjects
52 | NormalObjects
53 | """
54 | it = Rhino.DocObjects.ObjectEnumeratorSettings()
55 | it.IncludeLights = include_lights
56 | it.IncludeGrips = include_grips
57 | it.NormalObjects = True
58 | it.LockedObjects = True
59 | it.HiddenObjects = True
60 | it.ReferenceObjects = include_references
61 | e = scriptcontext.doc.Objects.GetObjectList(it)
62 | object_ids = []
63 | for object in e:
64 | if select: object.Select(True)
65 | object_ids.append(object.Id)
66 | if object_ids and select: scriptcontext.doc.Views.Redraw()
67 | return object_ids
68 |
69 |
70 | def FirstObject(select=False, include_lights=False, include_grips=False):
71 | """Returns identifier of the first object in the document. The first
72 | object is the last object created by the user.
73 | Parameters:
74 | select (bool, optional): Select the object. If omitted (False), the object is not selected.
75 | include_lights (bool, optional): Include light objects. If omitted (False), light objects are not returned.
76 | include_grips (bool, optional): Include grips objects. If omitted (False), grips objects are not returned.
77 | Returns:
78 | guid: The identifier of the object if successful.
79 | Example:
80 | import rhinoscriptsyntax as rs
81 | rs.AddLine( (0,0,0), (5,5,0) )
82 | rs.AddLine( (0,0,0), (5,0,0) )
83 | rs.AddLine( (0,0,0), (0,5,0) )
84 | objectId = rs.FirstObject()
85 | print("Object identifier: {}".format(objectId))
86 | rs.SelectObject(objectId)
87 | See Also:
88 | LastObject
89 | NextObject
90 | """
91 | it = Rhino.DocObjects.ObjectEnumeratorSettings()
92 | it.IncludeLights = include_lights
93 | it.IncludeGrips = include_grips
94 | e = scriptcontext.doc.Objects.GetObjectList(it).GetEnumerator()
95 | if not e.MoveNext(): return None
96 | object = e.Current
97 | if object:
98 | if select: object.Select(True)
99 | return object.Id
100 |
101 |
102 | def __FilterHelper(input_filter):
103 | geometry_filter = compat.ENUM_NONE(Rhino.DocObjects.ObjectType)
104 | if input_filter & 1:
105 | geometry_filter |= Rhino.DocObjects.ObjectType.Point
106 | if input_filter & 16384:
107 | geometry_filter |= Rhino.DocObjects.ObjectType.Grip
108 | if input_filter & 2:
109 | geometry_filter |= Rhino.DocObjects.ObjectType.PointSet
110 | if input_filter & 4:
111 | geometry_filter |= Rhino.DocObjects.ObjectType.Curve
112 | if input_filter & 8:
113 | geometry_filter |= Rhino.DocObjects.ObjectType.Surface
114 | if input_filter & 16:
115 | geometry_filter |= Rhino.DocObjects.ObjectType.Brep
116 | if input_filter & 32:
117 | geometry_filter |= Rhino.DocObjects.ObjectType.Mesh
118 | if input_filter & 512:
119 | geometry_filter |= Rhino.DocObjects.ObjectType.Annotation
120 | if input_filter & 256:
121 | geometry_filter |= Rhino.DocObjects.ObjectType.Light
122 | if input_filter & 4096:
123 | geometry_filter |= Rhino.DocObjects.ObjectType.InstanceReference
124 | if input_filter & 134217728:
125 | geometry_filter |= Rhino.DocObjects.ObjectType.Cage
126 | if input_filter & 65536:
127 | geometry_filter |= Rhino.DocObjects.ObjectType.Hatch
128 | if input_filter & 131072:
129 | geometry_filter |= Rhino.DocObjects.ObjectType.MorphControl
130 | if input_filter & 262144:
131 | geometry_filter |= Rhino.DocObjects.ObjectType.SubD
132 | if input_filter & 2097152:
133 | geometry_filter |= Rhino.DocObjects.ObjectType.PolysrfFilter
134 | if input_filter & 268435456:
135 | geometry_filter |= Rhino.DocObjects.ObjectType.Phantom
136 | if input_filter & 8192:
137 | geometry_filter |= Rhino.DocObjects.ObjectType.TextDot
138 | if input_filter & 32768:
139 | geometry_filter |= Rhino.DocObjects.ObjectType.Detail
140 | if input_filter & 536870912:
141 | geometry_filter |= Rhino.DocObjects.ObjectType.ClipPlane
142 | if input_filter & 1073741824:
143 | geometry_filter |= Rhino.DocObjects.ObjectType.Extrusion
144 | return geometry_filter
145 |
146 |
147 | def GetCurveObject(message=None, preselect=False, select=False):
148 | """Prompts user to pick or select a single curve object
149 | Parameters:
150 | message (str, optional): a prompt or message.
151 | preselect (bool,, optional): Allow for the selection of pre-selected objects.
152 | select (bool, optional): Select the picked objects. If False, objects that
153 | are picked are not selected.
154 | Returns:
155 | Tuple containing the following information
156 | [0] guid identifier of the curve object
157 | [1] bool True if the curve was preselected, otherwise False
158 | [2] number selection method
159 | 0 = selected by non-mouse method (SelAll, etc.).
160 | 1 = selected by mouse click on the object.
161 | 2 = selected by being inside of a mouse window.
162 | 3 = selected by intersecting a mouse crossing window.
163 | [3] point selection point
164 | [4] number the curve parameter of the selection point
165 | [5] str name of the view selection was made
166 | None: if no object picked
167 | Example:
168 | import rhinoscriptsyntax as rs
169 | select_result = rs.GetCurveObject("Select curve")
170 | if select_result:
171 | print("Curve identifier: {}".format(select_result[0]))
172 | See Also:
173 | GetObject
174 | GetObjects
175 | GetSurfaceObject
176 | """
177 | if not preselect:
178 | scriptcontext.doc.Objects.UnselectAll()
179 | scriptcontext.doc.Views.Redraw()
180 | go = Rhino.Input.Custom.GetObject()
181 | if message: go.SetCommandPrompt(message)
182 | go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve
183 | go.SubObjectSelect = False
184 | go.GroupSelect = False
185 | go.AcceptNothing(True)
186 | if go.Get()!=Rhino.Input.GetResult.Object: return None
187 |
188 | objref = go.Object(0)
189 | id = objref.ObjectId
190 | presel = go.ObjectsWerePreselected
191 | selmethod = 0
192 | sm = objref.SelectionMethod()
193 | if Rhino.DocObjects.SelectionMethod.MousePick==sm: selmethod = 1
194 | elif Rhino.DocObjects.SelectionMethod.WindowBox==sm: selmethod = 2
195 | elif Rhino.DocObjects.SelectionMethod.CrossingBox==sm: selmethod = 3
196 | point = objref.SelectionPoint()
197 | crv, curve_parameter = objref.CurveParameter()
198 | viewname = go.View().ActiveViewport.Name
199 | obj = go.Object(0).Object()
200 | go.Dispose()
201 | if not select and not presel:
202 | scriptcontext.doc.Objects.UnselectAll()
203 | scriptcontext.doc.Views.Redraw()
204 | obj.Select(select)
205 | return id, presel, selmethod, point, curve_parameter, viewname
206 |
207 |
208 | def GetObject(message=None, filter=0, preselect=False, select=False, custom_filter=None, subobjects=False):
209 | """Prompts user to pick, or select, a single object.
210 | Parameters:
211 | message(str, optional): a prompt or message.
212 | filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
213 | that can be selected. Object types can be added together to filter
214 | several different kinds of geometry. use the filter class to get values
215 | preselect (bool, optional): Allow for the selection of pre-selected objects.
216 | select (bool, optional): Select the picked objects. If False, the objects that are
217 | picked are not selected.
218 | subobjects (bool, optional): If True, subobjects can be selected. When this is the
219 | case, an ObjRef is returned instead of a Guid to allow for tracking
220 | of the subobject when passed into other functions
221 | Returns:
222 | guid: Identifier of the picked object
223 | None: if user did not pick an object
224 | Example:
225 | import rhinoscriptsyntax as rs
226 | objectId = rs.GetObject("Pick any object")
227 | if objectId:
228 | print("Object identifier: {}".format(objectId))
229 | objectId = rs.GetObject("Pick a curve or surface", rs.filter.curve | rs.filter.surface)
230 | if objectId:
231 | print("Object identifier: {}".format(objectId))
232 | See Also:
233 | GetCurveObject
234 | GetObjectEx
235 | GetObjects
236 | GetSurfaceObject
237 | """
238 | if not preselect:
239 | scriptcontext.doc.Objects.UnselectAll()
240 | scriptcontext.doc.Views.Redraw()
241 |
242 | class CustomGetObject(Rhino.Input.Custom.GetObject):
243 | def __init__(self, filter_function):
244 | super(CustomGetObject, self).__init__()
245 | self.m_filter_function = filter_function
246 | def CustomGeometryFilter( self, rhino_object, geometry, component_index ):
247 | rc = True
248 | if self.m_filter_function is not None:
249 | try:
250 | rc = self.m_filter_function(rhino_object, geometry, component_index)
251 | except:
252 | rc = True
253 | return rc
254 | go = CustomGetObject(custom_filter)
255 | if message: go.SetCommandPrompt(message)
256 | geometry_filter = __FilterHelper(filter)
257 | if filter>0: go.GeometryFilter = geometry_filter
258 | go.SubObjectSelect = subobjects
259 | go.GroupSelect = False
260 | go.AcceptNothing(True)
261 | if go.Get()!=Rhino.Input.GetResult.Object: return None
262 | objref = go.Object(0)
263 | obj = objref.Object()
264 | presel = go.ObjectsWerePreselected
265 | go.Dispose()
266 | if not select and not presel:
267 | scriptcontext.doc.Objects.UnselectAll()
268 | scriptcontext.doc.Views.Redraw()
269 | if subobjects: return objref
270 | obj.Select(select)
271 | return obj.Id
272 |
273 |
274 | class CustomGetObjectEx(Rhino.Input.Custom.GetObject):
275 | def __init__(self, allowable_geometry):
276 | super(CustomGetObjectEx, self).__init__()
277 | self.m_allowable = allowable_geometry
278 | def CustomGeometryFilter(self, rhino_object, geometry, component_index):
279 | for id in self.m_allowable:
280 | if id==rhino_object.Id: return True
281 | return False
282 |
283 |
284 | def GetObjectEx(message=None, filter=0, preselect=False, select=False, objects=None):
285 | """Prompts user to pick, or select a single object
286 | Parameters:
287 | message (str, optional): a prompt or message.
288 | filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
289 | that can be selected. Object types can be added together to filter
290 | several different kinds of geometry. use the filter class to get values
291 | preselect (bool, optional): Allow for the selection of pre-selected objects.
292 | select (bool, optional): Select the picked objects. If False, the objects that are
293 | picked are not selected.
294 | objects ([guid, ...]): list of object identifiers specifying objects that are
295 | allowed to be selected
296 | Returns:
297 | tuple(guid, bool, number, point, str): containing the following information
298 | [0] identifier of the object
299 | [1] True if the object was preselected, otherwise False
300 | [2] selection method (see help)
301 | [3] selection point
302 | [4] name of the view selection was made
303 | None: if no object selected
304 | Example:
305 | import rhinoscriptsyntax as rs
306 | obj = rs.GetObjectEx("Select object", 0, True)
307 | if obj:
308 | print("Object id = {}".format(obj[0]))
309 | print("Object was preselected = {}".format(obj[1]))
310 | if obj[2]==0:
311 | print("Selection method = 0 (non-mouse)")
312 | elif obj[2]==1:
313 | print("Selection method = 1 (mouse)")
314 | print("Pick point = {}".format(obj[3]))
315 | elif obj[2]==2:
316 | print("Selection method = 2 (window)")
317 | elif obj[2]==3:
318 | print("Selection method = 3 (crossing)")
319 | print("Active view = {}".format(obj[4]))
320 | See Also:
321 | GetCurveObject
322 | GetObject
323 | GetObjects
324 | GetObjectsEx
325 | GetSurfaceObject
326 | """
327 | if not preselect:
328 | scriptcontext.doc.Objects.UnselectAll()
329 | scriptcontext.doc.Views.Redraw()
330 | go = None
331 | if objects:
332 | ids = [rhutil.coerceguid(id, True) for id in objects]
333 | if ids: go = CustomGetObjectEx(ids)
334 | if not go: go = Rhino.Input.Custom.GetObject()
335 | if message: go.SetCommandPrompt(message)
336 | geometry_filter = __FilterHelper(filter)
337 | if filter>0: go.GeometryFilter = geometry_filter
338 | go.SubObjectSelect = False
339 | go.GroupSelect = False
340 | go.AcceptNothing(True)
341 | if go.Get()!=Rhino.Input.GetResult.Object: return None
342 | objref = go.Object(0)
343 | id = objref.ObjectId
344 | presel = go.ObjectsWerePreselected
345 | selmethod = 0
346 | sm = objref.SelectionMethod()
347 | if Rhino.DocObjects.SelectionMethod.MousePick==sm: selmethod = 1
348 | elif Rhino.DocObjects.SelectionMethod.WindowBox==sm: selmethod = 2
349 | elif Rhino.DocObjects.SelectionMethod.CrossingBox==sm: selmethod = 3
350 | point = objref.SelectionPoint()
351 | viewname = go.View().ActiveViewport.Name
352 | obj = go.Object(0).Object()
353 | go.Dispose()
354 | if not select and not presel:
355 | scriptcontext.doc.Objects.UnselectAll()
356 | scriptcontext.doc.Views.Redraw()
357 | obj.Select(select)
358 | return id, presel, selmethod, point, viewname
359 |
360 |
361 | def GetObjects(message=None, filter=0, group=True, preselect=False, select=False, objects=None, minimum_count=1, maximum_count=0, custom_filter=None):
362 | """Prompts user to pick or select one or more objects.
363 | Parameters:
364 | message (str, optional): a prompt or message.
365 | filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
366 | that can be selected. Object types can be added together to filter
367 | several different kinds of geometry. use the filter class to get values
368 | Value Description
369 | 0 All objects (default)
370 | 1 Point
371 | 2 Point cloud
372 | 4 Curve
373 | 8 Surface or single-face brep
374 | 16 Polysurface or multiple-face
375 | 32 Mesh
376 | 256 Light
377 | 512 Annotation
378 | 4096 Instance or block reference
379 | 8192 Text dot object
380 | 16384 Grip object
381 | 32768 Detail
382 | 65536 Hatch
383 | 131072 Morph control
384 | 262144 SubD
385 | 134217728 Cage
386 | 268435456 Phantom
387 | 536870912 Clipping plane
388 | 1073741824 Extrusion
389 | group (bool, optional): Honor object grouping. If omitted and the user picks a group,
390 | the entire group will be picked (True). Note, if filter is set to a
391 | value other than 0 (All objects), then group selection will be disabled.
392 | preselect (bool, optional): Allow for the selection of pre-selected objects.
393 | select (bool, optional): Select the picked objects. If False, the objects that are
394 | picked are not selected.
395 | objects ([guid, ...]): list of objects that are allowed to be selected
396 | minimum_count, maximum_count(number): limits on number of objects allowed to be selected
397 | custom_filter (str, optional): Calls a custom function in the script and passes the Rhino Object, Geometry, and component index and returns true or false indicating if the object can be selected
398 | Returns:
399 | list(guid, ...): identifiers of the picked objects
400 | Example:
401 | import rhinoscriptsyntax as rs
402 | objectIds = rs.GetObjects("Pick some curves", rs.filter.curve)
403 | for id in objectIds: print("Object identifier:{}".format(id))
404 | See Also:
405 | GetCurveObject
406 | GetObject
407 | GetSurfaceObject
408 | """
409 | if not preselect:
410 | scriptcontext.doc.Objects.UnselectAll()
411 | scriptcontext.doc.Views.Redraw()
412 |
413 | objects = rhutil.coerceguidlist(objects)
414 | class CustomGetObject(Rhino.Input.Custom.GetObject):
415 | def __init__(self, filter_function):
416 | super(CustomGetObject, self).__init__()
417 | self.m_filter_function = filter_function
418 | def CustomGeometryFilter( self, rhino_object, geometry, component_index ):
419 | if objects and not rhino_object.Id in objects: return False
420 | rc = True
421 | if self.m_filter_function is not None:
422 | try:
423 | rc = self.m_filter_function(rhino_object, geometry, component_index)
424 | except:
425 | rc = True
426 | return rc
427 | go = CustomGetObject(custom_filter)
428 | go.SetCommandPrompt(message or "Select objects")
429 | geometry_filter = __FilterHelper(filter)
430 | if filter>0: go.GeometryFilter = geometry_filter
431 | go.SubObjectSelect = False
432 | go.GroupSelect = group
433 | go.AcceptNothing(True)
434 | if go.GetMultiple(minimum_count,maximum_count)!=Rhino.Input.GetResult.Object: return None
435 | if not select and not go.ObjectsWerePreselected:
436 | scriptcontext.doc.Objects.UnselectAll()
437 | scriptcontext.doc.Views.Redraw()
438 | rc = []
439 | count = go.ObjectCount
440 | for i in compat.RANGE(count):
441 | objref = go.Object(i)
442 | rc.append(objref.ObjectId)
443 | obj = objref.Object()
444 | if select and obj is not None: obj.Select(select)
445 | go.Dispose()
446 | return rc
447 |
448 |
449 | def GetObjectsEx(message=None, filter=0, group=True, preselect=False, select=False, objects=None):
450 | """Prompts user to pick, or select one or more objects
451 | Parameters:
452 | message (str, optional): a prompt or message.
453 | filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
454 | that can be selected. Object types can be added together to filter
455 | several different kinds of geometry. use the filter class to get values
456 | group (bool, optional): Honor object grouping. If omitted and the user picks a group,
457 | the entire group will be picked (True). Note, if filter is set to a
458 | value other than 0 (All objects), then group selection will be disabled.
459 | preselect (bool, optional): Allow for the selection of pre-selected objects.
460 | select (bool, optional): Select the picked objects. If False, the objects that are
461 | picked are not selected.
462 | objects ([guid, ...]): list of object identifiers specifying objects that are
463 | allowed to be selected
464 | Returns:
465 | list(tuple(guid, bool, number, point, str), ...): containing the following information
466 | [n][0] identifier of the object
467 | [n][1] True if the object was preselected, otherwise False
468 | [n][2] selection method (see help)
469 | [n][3] selection point
470 | [n][4] name of the view selection was made
471 | Example:
472 | import rhinoscriptsyntax as rs
473 | objects = rs.GetObjectsEx("Select objects", 0, True)
474 | for obj in objects:
475 | print("Object id = {}".format(obj[0]))
476 | print("Object was preselected = {}".format(obj[1]))
477 | if obj[2]==0:
478 | print("Selection method = 0 (non-mouse)")
479 | elif obj[2]==1:
480 | print("Selection method = 1 (mouse)")
481 | print("Pick point = {}".format(obj[3]))
482 | elif obj[2]==2:
483 | print("Selection method = 2 (window)")
484 | elif obj[2]==3:
485 | print("Selection method = 3 (crossing)")
486 | print("Active view = {}".format(obj[4]))
487 | See Also:
488 | GetCurveObject
489 | GetObject
490 | GetObjectEx
491 | GetObjects
492 | GetSurfaceObject
493 | """
494 | if not preselect:
495 | scriptcontext.doc.Objects.UnselectAll()
496 | scriptcontext.doc.Views.Redraw()
497 | go = None
498 | if objects:
499 | ids = [rhutil.coerceguid(id) for id in objects]
500 | if ids: go = CustomGetObjectEx(ids)
501 | if not go: go = Rhino.Input.Custom.GetObject()
502 | go.SetCommandPrompt(message or "Select objects")
503 | geometry_filter = __FilterHelper(filter)
504 | if filter>0: go.GeometryFilter = geometry_filter
505 | go.SubObjectSelect = False
506 | go.GroupSelect = group
507 | go.AcceptNothing(True)
508 | if go.GetMultiple(1,0)!=Rhino.Input.GetResult.Object: return []
509 | if not select and not go.ObjectsWerePreselected:
510 | scriptcontext.doc.Objects.UnselectAll()
511 | scriptcontext.doc.Views.Redraw()
512 | rc = []
513 | count = go.ObjectCount
514 | for i in compat.RANGE(count):
515 | objref = go.Object(i)
516 | id = objref.ObjectId
517 | presel = go.ObjectsWerePreselected
518 | selmethod = 0
519 | sm = objref.SelectionMethod()
520 | if Rhino.DocObjects.SelectionMethod.MousePick==sm: selmethod = 1
521 | elif Rhino.DocObjects.SelectionMethod.WindowBox==sm: selmethod = 2
522 | elif Rhino.DocObjects.SelectionMethod.CrossingBox==sm: selmethod = 3
523 | point = objref.SelectionPoint()
524 | viewname = go.View().ActiveViewport.Name
525 | rc.append( (id, presel, selmethod, point, viewname) )
526 | obj = objref.Object()
527 | if select and obj is not None: obj.Select(select)
528 | go.Dispose()
529 | return rc
530 |
531 |
532 | def GetPointCoordinates(message="Select points", preselect=False):
533 | """Prompts the user to select one or more point objects.
534 | Parameters:
535 | message (str, optional): a prompt message.
536 | preselect (bool, optional): Allow for the selection of pre-selected objects. If omitted (False), pre-selected objects are not accepted.
537 | Returns:
538 | list(point, ...): 3d coordinates of point objects on success
539 | Example:
540 | import rhinoscriptsyntax as rs
541 | points = rs.GetPointCoordinates()
542 | for point in points: print(point)
543 | See Also:
544 | GetObject
545 | GetObjects
546 | GetPoint
547 | GetPoints
548 | PointCoordinates
549 | """
550 | ids = GetObjects(message, filter.point, preselect=preselect)
551 | rc = []
552 | for id in ids:
553 | rhobj = scriptcontext.doc.Objects.Find(id)
554 | rc.append(rhobj.Geometry.Location)
555 | return rc
556 |
557 |
558 | def GetSurfaceObject(message="Select surface", preselect=False, select=False):
559 | """Prompts the user to select a single surface
560 | Parameters:
561 | message(str, optional): prompt displayed
562 | preselect (bool, optional): allow for preselected objects
563 | select (bool, optional): select the picked object
564 | Returns:
565 | tuple(guid, bool, number, point, (number, number), str): of information on success
566 | [0] identifier of the surface
567 | [1] True if the surface was preselected, otherwise False
568 | [2] selection method ( see help )
569 | [3] selection point
570 | [4] u,v surface parameter of the selection point
571 | [5] name of the view in which the selection was made
572 | None: on error
573 | Example:
574 | import rhinoscriptsyntax as rs
575 | select = rs.GetSurfaceObject("Select surface")
576 | if select:
577 | print("Surface identifier: {}".format(select[0]))
578 | See Also:
579 | GetCurveObject
580 | GetObject
581 | GetObjects
582 | """
583 | if not preselect:
584 | scriptcontext.doc.Objects.UnselectAll()
585 | scriptcontext.doc.Views.Redraw()
586 | go = Rhino.Input.Custom.GetObject()
587 | go.SetCommandPrompt(message)
588 | go.GeometryFilter = Rhino.DocObjects.ObjectType.Surface
589 | go.SubObjectSelect = False
590 | go.GroupSelect = False
591 | go.AcceptNothing(True)
592 | if go.Get()!=Rhino.Input.GetResult.Object:
593 | return scriptcontext.errorhandler()
594 | objref = go.Object(0)
595 | rhobj = objref.Object()
596 | rhobj.Select(select)
597 | scriptcontext.doc.Views.Redraw()
598 |
599 | id = rhobj.Id
600 | prepicked = go.ObjectsWerePreselected
601 | selmethod = objref.SelectionMethod()
602 | point = objref.SelectionPoint()
603 | surf, u, v = objref.SurfaceParameter()
604 | uv = (u,v)
605 | if not point.IsValid:
606 | point = None
607 | uv = None
608 | view = go.View()
609 | name = view.ActiveViewport.Name
610 | go.Dispose()
611 | if not select and not prepicked:
612 | scriptcontext.doc.Objects.UnselectAll()
613 | scriptcontext.doc.Views.Redraw()
614 | return id, prepicked, selmethod, point, uv, name
615 |
616 |
617 | def LockedObjects(include_lights=False, include_grips=False, include_references=False):
618 | """Returns identifiers of all locked objects in the document. Locked objects
619 | cannot be snapped to, and cannot be selected
620 | Parameters:
621 | include_lights (bool, optional): include light objects
622 | include_grips (bool, optional): include grip objects
623 | Returns:
624 | list(guid, ...): identifiers the locked objects if successful.
625 | Example:
626 | import rhinoscriptsyntax as rs
627 | objs = rs.LockedObjects()
628 | for obj in objs: print("Object identifier:{}".format(obj))
629 | See Also:
630 | AllObjects
631 | HiddenObjects
632 | NormalObjects
633 | """
634 | settings = Rhino.DocObjects.ObjectEnumeratorSettings()
635 | settings.ActiveObjects = True
636 | settings.NormalObjects = True
637 | settings.LockedObjects = True
638 | settings.HiddenObjects = True
639 | settings.IncludeLights = include_lights
640 | settings.IncludeGrips = include_grips
641 | settings.ReferenceObjects = include_references
642 | return [i.Id for i in scriptcontext.doc.Objects.GetObjectList(settings)
643 | if i.IsLocked or (scriptcontext.doc.Layers[i.Attributes.LayerIndex]).IsLocked]
644 |
645 |
646 | def HiddenObjects(include_lights=False, include_grips=False, include_references=False):
647 | """Returns identifiers of all hidden objects in the document. Hidden objects
648 | are not visible, cannot be snapped to, and cannot be selected
649 | Parameters:
650 | include_lights (bool, optional): include light objects
651 | include_grips (bool, optional): include grip objects
652 | Returns:
653 | list(guid, ...): identifiers of the hidden objects if successful.
654 | Example:
655 | import rhinoscriptsyntax as rs
656 | hidden = rs.HiddenObjects()
657 | for obj in hidden: print("Object identifier{}".format(obj))
658 | See Also:
659 | AllObjects
660 | LockedObjects
661 | NormalObjects
662 | """
663 | settings = Rhino.DocObjects.ObjectEnumeratorSettings()
664 | settings.ActiveObjects = True
665 | settings.NormalObjects = True
666 | settings.LockedObjects = True
667 | settings.HiddenObjects = True
668 | settings.IncludeLights = include_lights
669 | settings.IncludeGrips = include_grips
670 | settings.ReferenceObjects = include_references
671 | return [i.Id for i in scriptcontext.doc.Objects.GetObjectList(settings)
672 | if i.IsHidden or not (scriptcontext.doc.Layers[i.Attributes.LayerIndex]).IsVisible]
673 |
674 |
675 | def InvertSelectedObjects(include_lights=False, include_grips=False, include_references=False):
676 | """Inverts the current object selection. The identifiers of the newly
677 | selected objects are returned
678 | Parameters:
679 | include_lights (bool, optional): Include light objects. If omitted (False), light objects are not returned.
680 | include_grips (bool, optional): Include grips objects. If omitted (False), grips objects are not returned.
681 | include_references (bool, optional): Include reference objects. If omitted (False), reference objects are not returned.
682 | Returns:
683 | list(guid, ...): identifiers of the newly selected objects if successful.
684 | Example:
685 | import rhinoscriptsyntax as rs
686 | rs.GetObjects("Select some objects", select=True)
687 | objs = rs.InvertSelectedObjects()
688 | for id in objs: print("Object identifier:{}".format(id))
689 | See Also:
690 | SelectedObjects
691 | UnselectAllObjects
692 | """
693 | settings = Rhino.DocObjects.ObjectEnumeratorSettings()
694 | settings.IncludeLights = include_lights
695 | settings.IncludeGrips = include_grips
696 | settings.IncludePhantoms = True
697 | settings.ReferenceObjects = include_references
698 | rhobjs = scriptcontext.doc.Objects.GetObjectList(settings)
699 | rc = []
700 | for obj in rhobjs:
701 | if not obj.IsSelected(False) and obj.IsSelectable():
702 | rc.append(obj.Id)
703 | obj.Select(True)
704 | else:
705 | obj.Select(False)
706 | scriptcontext.doc.Views.Redraw()
707 | return rc
708 |
709 |
710 | def LastCreatedObjects(select=False):
711 | """Returns identifiers of the objects that were most recently created or changed
712 | by scripting a Rhino command using the Command function. It is important to
713 | call this function immediately after calling the Command function as only the
714 | most recently created or changed object identifiers will be returned
715 | Parameters:
716 | select (bool, optional): Select the object. If omitted (False), the object is not selected.
717 | Returns:
718 | list(guid, ...): identifiers of the most recently created or changed objects if successful.
719 | Example:
720 | import rhinoscriptsyntax as rs
721 | rs.Command( "_-Circle 0,0,0 10" )
722 | rs.Command( "_-Circle 10,0,0 10" )
723 | rs.Command( "_-Circle 20,0,0 10" )
724 | objs = rs.LastCreatedObjects()
725 | if objs:
726 | # Only the last circle will be selected
727 | rs.SelectObjects( objs )
728 | See Also:
729 | Command
730 | """
731 | serial_numbers = rhapp.__command_serial_numbers
732 | if serial_numbers is None: return scriptcontext.errorhandler()
733 | serial_number = serial_numbers[0]
734 | end = serial_numbers[1]
735 | rc = []
736 | while serial_number<end:
737 | obj = scriptcontext.doc.Objects.Find(serial_number)
738 | if obj and not obj.IsDeleted:
739 | rc.append(obj.Id)
740 | if select: obj.Select(True)
741 | serial_number += 1
742 | if select==True and rc: scriptcontext.doc.Views.Redraw()
743 | return rc
744 |
745 |
746 | def LastObject(select=False, include_lights=False, include_grips=False):
747 | """Returns the identifier of the last object in the document. The last object
748 | in the document is the first object created by the user
749 | Parameters:
750 | select (bool, optional): select the object
751 | include_lights (bool, optional): include lights in the potential set
752 | include_grips (bool, optional): include grips in the potential set
753 | Returns:
754 | guid: identifier of the object on success
755 | Example:
756 | import rhinoscriptsyntax as rs
757 | rs.AddLine((0,0,0), (5,5,0))
758 | rs.AddCircle((0,0,0), 5)
759 | print("Object identifier: {}".format(rs.LastObject()))
760 | See Also:
761 | FirstObject
762 | NextObject
763 | """
764 | settings = Rhino.DocObjects.ObjectEnumeratorSettings()
765 | settings.IncludeLights = include_lights
766 | settings.IncludeGrips = include_grips
767 | settings.DeletedObjects = False
768 | rhobjs = scriptcontext.doc.Objects.GetObjectList(settings)
769 | firstobj = None
770 | for obj in rhobjs: firstobj = obj
771 | if firstobj is None: return scriptcontext.errorhandler()
772 | rc = firstobj.Id
773 | if select:
774 | firstobj.Select(True)
775 | scriptcontext.doc.Views.Redraw()
776 | return rc
777 |
778 |
779 | def NextObject(object_id, select=False, include_lights=False, include_grips=False):
780 | """Returns the identifier of the next object in the document
781 | Parameters:
782 | object_id (guid): the identifier of the object from which to get the next object
783 | select (bool, optional): select the object
784 | include_lights (bool, optional): include lights in the potential set
785 | include_grips (bool, optional): include grips in the potential set
786 | Returns:
787 | guid: identifier of the object on success
788 | Example:
789 | import rhinoscriptsyntax as rs
790 | obj = rs.FirstObject()
791 | while obj:
792 | print("Object identifier:{}".format(obj))
793 | obj = rs.NextObject(obj)
794 | See Also:
795 | FirstObject
796 | LastObject
797 | """
798 | current_obj = rhutil.coercerhinoobject(object_id, True)
799 | settings = Rhino.DocObjects.ObjectEnumeratorSettings()
800 | settings.IncludeLights = include_lights
801 | settings.IncludeGrips = include_grips
802 | settings.DeletedObjects = False
803 | rhobjs = scriptcontext.doc.Objects.GetObjectList(settings)
804 | found = False
805 | for obj in rhobjs:
806 | if found and obj:
807 | if select: obj.Select(True)
808 | return obj.Id
809 | if obj.Id == current_obj.Id: found = True
810 |
811 |
812 | def NormalObjects(include_lights=False, include_grips=False):
813 | """Returns identifiers of all normal objects in the document. Normal objects
814 | are visible, can be snapped to, and are independent of selection state
815 | Parameters:
816 | include_lights (bool, optional): Include light objects. If omitted (False), light objects are not returned.
817 | include_gripts (bool, optional): Include grips objects. If omitted (False), grips objects are not returned.
818 | Returns:
819 | list(guid, ...): identifier of normal objects if successful.
820 | Example:
821 | import rhinoscriptsyntax as rs
822 | objs = rs.NormalObjects()
823 | for obj in objs: print("Object identifier:{}".format(obj))
824 | See Also:
825 | AllObjects
826 | HiddenObjects
827 | LockedObjects
828 | """
829 | iter = Rhino.DocObjects.ObjectEnumeratorSettings()
830 | iter.NormalObjects = True
831 | iter.LockedObjects = False
832 | iter.IncludeLights = include_lights
833 | iter.IncludeGrips = include_grips
834 | return [obj.Id for obj in scriptcontext.doc.Objects.GetObjectList(iter)]
835 |
836 |
837 | def ObjectsByColor(color, select=False, include_lights=False):
838 | """Returns identifiers of all objects based on color
839 | Parameters:
840 | color (color): color to get objects by
841 | select (bool, optional): select the objects
842 | include_lights (bool, optional): include lights in the set
843 | Returns:
844 | list(guid, ...): identifiers of objects of the selected color.
845 | Example:
846 | import rhinoscriptsyntax as rs
847 | obj = rs.GetObject("Pick any object")
848 | if obj:
849 | color = rs.ObjectColor(obj)
850 | rs.ObjectsByColor(color, True)
851 | See Also:
852 |
853 | """
854 | color = rhutil.coercecolor(color, True)
855 | rhino_objects = scriptcontext.doc.Objects.FindByDrawColor(color, include_lights)
856 | if select:
857 | for obj in rhino_objects: obj.Select(True)
858 | scriptcontext.doc.Views.Redraw()
859 | return [obj.Id for obj in rhino_objects]
860 |
861 |
862 | def ObjectsByGroup(group_name, select=False):
863 | """Returns identifiers of all objects based on the objects' group name
864 | Parameters:
865 | group_name (str): name of the group
866 | select (bool, optional): select the objects
867 | Returns:
868 | list(guid, ...):identifiers for objects in the group on success
869 | Example:
870 | import rhinoscriptsyntax as rs
871 | group = rs.GetString("Group to select")
872 | if group: rs.ObjectsByGroup( group, True )
873 | See Also:
874 |
875 | """
876 | group_instance = scriptcontext.doc.Groups.FindName(group_name)
877 | if group_instance is None: raise ValueError("%s does not exist in GroupTable"%group_name)
878 | rhino_objects = scriptcontext.doc.Groups.GroupMembers(group_instance.Index)
879 | if not rhino_objects: return []
880 | if select:
881 | for obj in rhino_objects: obj.Select(True)
882 | scriptcontext.doc.Views.Redraw()
883 | return [obj.Id for obj in rhino_objects]
884 |
885 |
886 | def ObjectsByLayer(layer_name, select=False):
887 | """Returns identifiers of all objects based on the objects' layer name
888 | Parameters:
889 | layer_name (str): name of the layer
890 | select (bool, optional): select the objects
891 | Returns:
892 | list(guid, ...): identifiers for objects in the specified layer
893 | Example:
894 | import rhinoscriptsyntax as rs
895 | obj = rs.GetObject("Pick any object")
896 | if obj:
897 | layer = rs.ObjectLayer(obj)
898 | rs.ObjectsByLayer(layer, True)
899 | See Also:
900 |
901 | """
902 | layer = __getlayer(layer_name, True)
903 | rhino_objects = scriptcontext.doc.Objects.FindByLayer(layer)
904 | if not rhino_objects: return []
905 | if select:
906 | for rhobj in rhino_objects: rhobj.Select(True)
907 | scriptcontext.doc.Views.Redraw()
908 | return [rhobj.Id for rhobj in rhino_objects]
909 |
910 |
911 | def ObjectsByName(name, select=False, include_lights=False, include_references=False):
912 | """Returns identifiers of all objects based on user-assigned name
913 | Parameters:
914 | name (str): name of the object or objects
915 | select (bool, optional): select the objects
916 | include_lights (bool, optional): include light objects
917 | Returns:
918 | list(guid, ...): identifiers for objects with the specified name.
919 | Example:
920 | import rhinoscriptsyntax as rs
921 | name = rs.GetString("Name to select")
922 | if name: rs.ObjectsByName(name,True)
923 | See Also:
924 |
925 | """
926 | settings = Rhino.DocObjects.ObjectEnumeratorSettings()
927 | settings.HiddenObjects = True
928 | settings.DeletedObjects = False
929 | settings.IncludeGrips = False
930 | settings.IncludePhantoms = True
931 | settings.IncludeLights = include_lights
932 | settings.NameFilter = name
933 | settings.ReferenceObjects = include_references
934 | objects = scriptcontext.doc.Objects.GetObjectList(settings)
935 | ids = [rhobj.Id for rhobj in objects]
936 | if ids and select:
937 | objects = scriptcontext.doc.Objects.GetObjectList(settings)
938 | for rhobj in objects: rhobj.Select(True)
939 | scriptcontext.doc.Views.Redraw()
940 | return ids
941 |
942 |
943 | def ObjectsByType(geometry_type, select=False, state=0):
944 | """Returns identifiers of all objects based on the objects' geometry type.
945 | Parameters:
946 | geometry_type (number): The type(s) of geometry objects (points, curves, surfaces,
947 | meshes, etc.) that can be selected. Object types can be
948 | added together as bit-coded flags to filter several different kinds of geometry.
949 | Value Description
950 | 0 All objects
951 | 1 Point
952 | 2 Point cloud
953 | 4 Curve
954 | 8 Surface or single-face brep
955 | 16 Polysurface or multiple-face
956 | 32 Mesh
957 | 256 Light
958 | 512 Annotation
959 | 4096 Instance or block reference
960 | 8192 Text dot object
961 | 16384 Grip object
962 | 32768 Detail
963 | 65536 Hatch
964 | 131072 Morph control
965 | 262144 SubD
966 | 134217728 Cage
967 | 268435456 Phantom
968 | 536870912 Clipping plane
969 | 1073741824 Extrusion
970 | select (bool, optional): Select the objects
971 | state (bool, optional): The object state (normal, locked, and hidden). Object states can be
972 | added together to filter several different states of geometry.
973 | Value Description
974 | 0 All objects
975 | 1 Normal objects
976 | 2 Locked objects
977 | 4 Hidden objects
978 | Returns:
979 | list(guid, ...): identifiers of object that fit the specified type(s).
980 | Example:
981 | import rhinoscriptsyntax as rs
982 | objs = rs.ObjectsByType(4 | 8, True)
983 | See Also:
984 |
985 | """
986 | if not state: state = 7
987 | bSurface = False
988 | bPolySurface = False
989 | bLights = False
990 | bGrips = False
991 | bPhantoms = False
992 | geometry_filter = __FilterHelper(geometry_type)
993 | if type(geometry_type) is int and geometry_type==0:
994 | geometry_filter = Rhino.DocObjects.ObjectType.AnyObject
995 | if geometry_filter & Rhino.DocObjects.ObjectType.Surface: bSurface = True
996 | if geometry_filter & Rhino.DocObjects.ObjectType.Brep: bPolySurface = True
997 | if geometry_filter & Rhino.DocObjects.ObjectType.Light: bLights = True
998 | if geometry_filter & Rhino.DocObjects.ObjectType.Grip: bGrips = True
999 | if geometry_filter & Rhino.DocObjects.ObjectType.Phantom: bPhantoms = True
1000 |
1001 | it = Rhino.DocObjects.ObjectEnumeratorSettings()
1002 | it.DeletedObjects = False
1003 | it.ActiveObjects = True
1004 | it.ReferenceObjects = True
1005 | it.IncludeLights = bLights
1006 | it.IncludeGrips = bGrips
1007 | it.IncludePhantoms = bPhantoms
1008 |
1009 | if state:
1010 | it.NormalObjects = False
1011 | it.LockedObjects = False
1012 | if state & 1: it.NormalObjects = True
1013 | if state & 2: it.LockedObjects = True
1014 | if state & 4: it.HiddenObjects = True
1015 |
1016 | object_ids = []
1017 | e = scriptcontext.doc.Objects.GetObjectList(it)
1018 | for object in e:
1019 | bFound = False
1020 | object_type = object.ObjectType
1021 | if object_type==Rhino.DocObjects.ObjectType.Brep and (bSurface or bPolySurface):
1022 | brep = rhutil.coercebrep(object.Id)
1023 | if brep:
1024 | if brep.Faces.Count==1:
1025 | if bSurface: bFound = True
1026 | else:
1027 | if bPolySurface: bFound = True
1028 | elif object_type==Rhino.DocObjects.ObjectType.Extrusion and (bSurface or bPolySurface):
1029 | extrusion = object.Geometry
1030 | profile_count = extrusion.ProfileCount
1031 | cap_count = extrusion.CapCount
1032 | if profile_count==1 and cap_count==0 and bSurface:
1033 | bFound = True
1034 | elif profile_count>0 and cap_count>0 and bPolySurface:
1035 | bFound = True
1036 | elif object_type & geometry_filter:
1037 | bFound = True
1038 |
1039 | if bFound:
1040 | if select: object.Select(True)
1041 | object_ids.append(object.Id)
1042 |
1043 | if object_ids and select: scriptcontext.doc.Views.Redraw()
1044 | return object_ids
1045 |
1046 |
1047 | def SelectedObjects(include_lights=False, include_grips=False):
1048 | """Returns the identifiers of all objects that are currently selected
1049 | Parameters:
1050 | include_lights (bool, optional): include light objects
1051 | include_grips (bool, optional): include grip objects
1052 | Returns:
1053 | list(guid, ...) identifiers of selected objects
1054 | Example:
1055 | import rhinoscriptsyntax as rs
1056 | objects = rs.SelectedObjects()
1057 | for obj in objects: print("Object identifier: {}".format(obj))
1058 | See Also:
1059 | InvertSelectedObjects
1060 | UnselectAllObjects
1061 | """
1062 | selobjects = scriptcontext.doc.Objects.GetSelectedObjects(include_lights, include_grips)
1063 | return [obj.Id for obj in selobjects]
1064 |
1065 |
1066 | def UnselectAllObjects():
1067 | """Unselects all objects in the document
1068 | Returns:
1069 | number: the number of objects that were unselected
1070 | Example:
1071 | import rhinoscriptsyntax as rs
1072 | count = rs.UnselectAllObjects()
1073 | print("{} objects were unselected".format(count))
1074 | See Also:
1075 | InvertSelectedObjects
1076 | SelectedObjects
1077 | """
1078 | rc = scriptcontext.doc.Objects.UnselectAll()
1079 | if rc>0: scriptcontext.doc.Views.Redraw()
1080 | return rc
1081 |
1082 |
1083 | def VisibleObjects(view=None, select=False, include_lights=False, include_grips=False):
1084 | """Return identifiers of all objects that are visible in a specified view
1085 | Parameters:
1086 | view (bool, optional): the view to use. If omitted, the current active view is used
1087 | select (bool, optional): Select the objects
1088 | include_lights (bool, optional): include light objects
1089 | include_grips (bool, optional): include grip objects
1090 | Returns:
1091 | list(guid, ...): identifiers of the visible objects
1092 | Example:
1093 | import rhinoscriptsyntax as rs
1094 | object_ids = rs.VisibleObjects("Top")
1095 | if object_ids:
1096 | for id in object_ids: print("Object identifier:{}".format(id))
1097 | See Also:
1098 | IsView
1099 | IsVisibleInView
1100 | """
1101 | it = Rhino.DocObjects.ObjectEnumeratorSettings()
1102 | it.DeletedObjects = False
1103 | it.ActiveObjects = True
1104 | it.ReferenceObjects = True
1105 | it.IncludeLights = include_lights
1106 | it.IncludeGrips = include_grips
1107 | it.VisibleFilter = True
1108 | viewport = __viewhelper(view).MainViewport
1109 | it.ViewportFilter = viewport
1110 |
1111 | object_ids = []
1112 | e = scriptcontext.doc.Objects.GetObjectList(it)
1113 | for object in e:
1114 | bbox = object.Geometry.GetBoundingBox(True)
1115 | if viewport.IsVisible(bbox):
1116 | if select: object.Select(True)
1117 | object_ids.append(object.Id)
1118 |
1119 | if object_ids and select: scriptcontext.doc.Views.Redraw()
1120 | return object_ids
1121 |
1122 |
1123 | def WindowPick(corner1, corner2, view=None, select=False, in_window=True):
1124 | """Picks objects using either a window or crossing selection
1125 | Parameters:
1126 | corner1, corner2 (point): corners of selection window
1127 | view (bool, optional): view to perform the selection in
1128 | select (bool, optional): select picked objects
1129 | in_window (bool, optional): if False, then a crossing window selection is performed
1130 | Returns:
1131 | list(guid, ...): identifiers of selected objects on success
1132 | Example:
1133 | import rhinoscriptsyntax as rs
1134 | rs.WindowPick((0,0,0), (0,0,0), None, True)
1135 | See Also:
1136 |
1137 | """
1138 | view = __viewhelper(view)
1139 | viewport = view.MainViewport
1140 |
1141 | screen1 = rhutil.coerce3dpoint(corner1, True)
1142 | screen2 = rhutil.coerce3dpoint(corner2, True)
1143 | xf = viewport.GetTransform(Rhino.DocObjects.CoordinateSystem.World, Rhino.DocObjects.CoordinateSystem.Screen)
1144 | screen1.Transform(xf)
1145 | screen2.Transform(xf)
1146 |
1147 | pc = Rhino.Input.Custom.PickContext()
1148 | pc.View = view
1149 | pc.PickStyle = Rhino.Input.Custom.PickStyle.WindowPick if in_window else Rhino.Input.Custom.PickStyle.CrossingPick
1150 | pc.PickGroupsEnabled = True if in_window else False
1151 | _, frustumLine = viewport.GetFrustumLine((screen1.X + screen2.X) / 2.0, (screen1.Y + screen2.Y) / 2.0)
1152 | pc.PickLine = frustumLine
1153 |
1154 | leftX = min(screen1.X, screen2.X)
1155 | topY = min(screen1.Y, screen2.Y)
1156 | w = abs(screen1.X - screen2.X)
1157 | h = abs(screen1.Y - screen2.Y)
1158 | rec = System.Drawing.Rectangle(leftX, topY, w, h)
1159 |
1160 | pc.SetPickTransform(viewport.GetPickTransform(rec))
1161 | pc.UpdateClippingPlanes()
1162 |
1163 | objects = scriptcontext.doc.Objects.PickObjects(pc)
1164 |
1165 | if objects:
1166 | rc = []
1167 | for rhobj in objects:
1168 | o = rhobj.Object()
1169 | rc.append(o.Id)
1170 | if select: o.Select(True)
1171 | if select: scriptcontext.doc.Views.Redraw()
1172 | return rc
1173 |
```
--------------------------------------------------------------------------------
/rhino_mcp_server/static/mesh.py:
--------------------------------------------------------------------------------
```python
1 | import System
2 | import System.Drawing
3 |
4 | import Rhino
5 |
6 | import scriptcontext
7 |
8 | import rhinocompat as compat
9 | from rhinoscript import utility as rhutil
10 | from rhinoscript.view import __viewhelper
11 |
12 |
13 | def AddMesh(vertices, face_vertices, vertex_normals=None, texture_coordinates=None, vertex_colors=None):
14 | """Add a mesh object to the document
15 | Parameters:
16 | vertices ([point, ...]) list of 3D points defining the vertices of the mesh
17 | face_vertices ([[number, number, number], [number, number, number, number], ...]) list containing lists of 3 or 4 numbers that define the
18 | vertex indices for each face of the mesh. If the third a fourth vertex
19 | indices of a face are identical, a triangular face will be created.
20 | vertex_normals ([vector, ...], optional) list of 3D vectors defining the vertex normals of
21 | the mesh. Note, for every vertex, there must be a corresponding vertex
22 | normal
23 | texture_coordinates ([[number, number], [number, number], [number, number]], ...], optional): list of 2D texture coordinates. For every
24 | vertex, there must be a corresponding texture coordinate
25 | vertex_colors ([color, ...]) a list of color values. For every vertex,
26 | there must be a corresponding vertex color
27 | Returns:
28 | guid: Identifier of the new object if successful
29 | None: on error
30 | Example:
31 | import rhinoscriptsyntax as rs
32 | vertices = []
33 | vertices.append((0.0,0.0,0.0))
34 | vertices.append((5.0, 0.0, 0.0))
35 | vertices.append((10.0, 0.0, 0.0))
36 | vertices.append((0.0, 5.0, 0.0))
37 | vertices.append((5.0, 5.0, 0.0))
38 | vertices.append((10.0, 5.0, 0.0))
39 | vertices.append((0.0, 10.0, 0.0))
40 | vertices.append((5.0, 10.0, 0.0))
41 | vertices.append((10.0, 10.0, 0.0))
42 | faceVertices = []
43 | faceVertices.append((0,1,4,4))
44 | faceVertices.append((2,4,1,1))
45 | faceVertices.append((0,4,3,3))
46 | faceVertices.append((2,5,4,4))
47 | faceVertices.append((3,4,6,6))
48 | faceVertices.append((5,8,4,4))
49 | faceVertices.append((6,4,7,7))
50 | faceVertices.append((8,7,4,4))
51 | rs.AddMesh( vertices, faceVertices )
52 | See Also:
53 | MeshFaces
54 | MeshFaceVertices
55 | MeshVertexNormals
56 | MeshVertices
57 | """
58 | mesh = Rhino.Geometry.Mesh()
59 | for a, b, c in vertices: mesh.Vertices.Add(a, b, c)
60 | for face in face_vertices:
61 | if len(face)<4:
62 | mesh.Faces.AddFace(face[0], face[1], face[2])
63 | else:
64 | mesh.Faces.AddFace(face[0], face[1], face[2], face[3])
65 | if vertex_normals:
66 | count = len(vertex_normals)
67 | normals = System.Array.CreateInstance(Rhino.Geometry.Vector3f, count)
68 | for i, normal in enumerate(vertex_normals):
69 | normals[i] = Rhino.Geometry.Vector3f(normal[0], normal[1], normal[2])
70 | mesh.Normals.SetNormals(normals)
71 | if texture_coordinates:
72 | count = len(texture_coordinates)
73 | tcs = System.Array.CreateInstance(Rhino.Geometry.Point2f, count)
74 | for i, tc in enumerate(texture_coordinates):
75 | tcs[i] = Rhino.Geometry.Point2f(tc[0], tc[1])
76 | mesh.TextureCoordinates.SetTextureCoordinates(tcs)
77 | if vertex_colors:
78 | count = len(vertex_colors)
79 | colors = System.Array.CreateInstance(System.Drawing.Color, count)
80 | for i, color in enumerate(vertex_colors):
81 | colors[i] = rhutil.coercecolor(color)
82 | mesh.VertexColors.SetColors(colors)
83 | rc = scriptcontext.doc.Objects.AddMesh(mesh)
84 | if rc==System.Guid.Empty: raise Exception("unable to add mesh to document")
85 | scriptcontext.doc.Views.Redraw()
86 | return rc
87 |
88 |
89 | def AddPlanarMesh(object_id, delete_input=False):
90 | """Creates a planar mesh from a closed, planar curve
91 | Parameters:
92 | object_id (guid): identifier of a closed, planar curve
93 | delete_input (bool, optional) if True, delete the input curve defined by object_id
94 | Returns:
95 | guid: id of the new mesh on success
96 | None: on error
97 | Example:
98 | import rhinoscriptsyntax as rs
99 | obj = rs.GetObject("Select planar curves to build mesh", rs.filter.curve)
100 | if obj: rs.AddPlanarMesh(obj)
101 | See Also:
102 | IsCurveClosed
103 | IsCurvePlanar
104 | """
105 | curve = rhutil.coercecurve(object_id, -1, True)
106 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
107 | mesh = Rhino.Geometry.Mesh.CreateFromPlanarBoundary(curve, Rhino.Geometry.MeshingParameters.Default, tolerance)
108 | if not mesh: return scriptcontext.errorhandler()
109 | if delete_input:
110 | id = rhutil.coerceguid(object_id, True)
111 | rc = scriptcontext.doc.Objects.Replace(id, mesh)
112 | else:
113 | rc = scriptcontext.doc.Objects.AddMesh(mesh)
114 | if rc==System.Guid.Empty: raise Exception("unable to add mesh to document")
115 | scriptcontext.doc.Views.Redraw()
116 | return rc
117 |
118 |
119 | def CurveMeshIntersection(curve_id, mesh_id, return_faces=False):
120 | """Calculates the intersection of a curve object and a mesh object
121 | Parameters:
122 | curve_id (guid): identifier of a curve object
123 | mesh_id (guid): identifier or a mesh object
124 | return_faces (bool, optional): return both intersection points and face indices.
125 | If False, then just the intersection points are returned
126 | Returns:
127 | list(point, ...): if return_false is omitted or False, then a list of intersection points
128 | list([point, number], ...): if return_false is True, the a one-dimensional list containing information
129 | about each intersection. Each element contains the following two elements
130 | [0] = point of intersection
131 | [1] = mesh face index where intersection lies
132 | None: on error
133 | Example:
134 | import rhinoscriptsyntax as rs
135 | curve = rs.GetObject("Select curve to intersect", rs.filter.curve)
136 | if curve:
137 | mesh = rs.GetObject("Select mesh to intersect", rs.filter.mesh)
138 | if mesh:
139 | cmx = rs.CurveMeshIntersection(curve, mesh, True)
140 | if cmx:
141 | for element in cmx:
142 | print("{}, Face index = {}".format(element[0], element[1]))
143 | rs.AddPoint(element[0])
144 | See Also:
145 | MeshClosestPoint
146 | MeshMeshIntersection
147 | """
148 | curve = rhutil.coercecurve(curve_id, -1, True)
149 | mesh = rhutil.coercemesh(mesh_id, True)
150 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance
151 | polylinecurve = curve.ToPolyline(0,0,0,0,0.0,tolerance,0.0,0.0,True)
152 | pts, faceids = Rhino.Geometry.Intersect.Intersection.MeshPolyline(mesh, polylinecurve)
153 | if not pts: return scriptcontext.errorhandler()
154 | pts = list(pts)
155 | if return_faces:
156 | faceids = list(faceids)
157 | return compat.ITERATOR2LIST(zip(pts, faceids))
158 | return pts
159 |
160 |
161 | def DisjointMeshCount(object_id):
162 | """Returns number of meshes that could be created by calling SplitDisjointMesh
163 | Parameters:
164 | object_id (guid): identifier of a mesh object
165 | Returns:
166 | number: The number of meshes that could be created
167 | Example:
168 | import rhinoscriptsyntax as rs
169 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
170 | if rs.DisjointMeshCount(obj)>1: rs.SplitDisjointMesh(obj)
171 | See Also:
172 | IsMesh
173 | SplitDisjointMesh
174 | """
175 | mesh = rhutil.coercemesh(object_id, True)
176 | return mesh.DisjointMeshCount
177 |
178 |
179 | def DuplicateMeshBorder(mesh_id):
180 | """Creates curves that duplicates a mesh border
181 | Parameters:
182 | mesh_id (guid): identifier of a mesh object
183 | Returns:
184 | list(guid, ...): list of curve ids on success
185 | None: on error
186 | Example:
187 | import rhinoscriptsyntax as rs
188 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
189 | if obj: rs.DuplicateMeshBorder(obj)
190 | See Also:
191 | DuplicateEdgeCurves
192 | DuplicateSurfaceBorder
193 | """
194 | mesh = rhutil.coercemesh(mesh_id, True)
195 | polylines = mesh.GetNakedEdges()
196 | rc = []
197 | if polylines:
198 | for polyline in polylines:
199 | id = scriptcontext.doc.Objects.AddPolyline(polyline)
200 | if id!=System.Guid.Empty: rc.append(id)
201 | if rc: scriptcontext.doc.Views.Redraw()
202 | return rc
203 |
204 |
205 | def ExplodeMeshes(mesh_ids, delete=False):
206 | """Explodes a mesh object, or mesh objects int submeshes. A submesh is a
207 | collection of mesh faces that are contained within a closed loop of
208 | unwelded mesh edges. Unwelded mesh edges are where the mesh faces that
209 | share the edge have unique mesh vertices (not mesh topology vertices)
210 | at both ends of the edge
211 | Parameters:
212 | mesh_ids ([guid, ...]): list of mesh identifiers
213 | delete (bool, optional): delete the input meshes
214 | Returns:
215 | list(guid, ...): List of resulting objects after explode.
216 | Example:
217 | import rhinoscriptsyntax as rs
218 | obj = rs.GetObject("Select mesh to explode", rs.filter.mesh)
219 | if rs.IsMesh(obj): rs.ExplodeMeshes(obj)
220 | See Also:
221 | IsMesh
222 | """
223 | id = rhutil.coerceguid(mesh_ids)
224 | if id: mesh_ids = [mesh_ids]
225 | rc = []
226 | for mesh_id in mesh_ids:
227 | mesh = rhutil.coercemesh(mesh_id, True)
228 | if mesh:
229 | submeshes = mesh.ExplodeAtUnweldedEdges()
230 | if submeshes:
231 | for submesh in submeshes:
232 | id = scriptcontext.doc.Objects.AddMesh(submesh)
233 | if id!=System.Guid.Empty: rc.append(id)
234 | if delete:
235 | scriptcontext.doc.Objects.Delete(mesh_id, True)
236 |
237 | if rc: scriptcontext.doc.Views.Redraw()
238 | return rc
239 |
240 |
241 | def IsMesh(object_id):
242 | """Verifies if an object is a mesh
243 | Parameters:
244 | object_id (guid): the object's identifier
245 | Returns:
246 | bool: True if successful, otherwise False
247 | Example:
248 | import rhinoscriptsyntax as rs
249 | obj = rs.GetObject("Select a mesh")
250 | if rs.IsMesh(obj):
251 | print("The object is a mesh.")
252 | else:
253 | print("The object is not a mesh.")
254 | See Also:
255 | IsMeshClosed
256 | MeshFaceCount
257 | MeshFaces
258 | MeshVertexCount
259 | MeshVertices
260 | """
261 | mesh = rhutil.coercemesh(object_id)
262 | return mesh is not None
263 |
264 |
265 | def IsMeshClosed(object_id):
266 | """Verifies a mesh object is closed
267 | Parameters:
268 | object_id (guid): identifier of a mesh object
269 | Returns:
270 | bool: True if successful, otherwise False.
271 | Example:
272 | import rhinoscriptsyntax as rs
273 | obj = rs.GetObject("Select a mesh", rs.filter.mesh)
274 | if rs.IsMeshClosed(obj):
275 | print("The mesh is closed.")
276 | else:
277 | print("The mesh is not closed.")
278 | See Also:
279 | IsMesh
280 | """
281 | mesh = rhutil.coercemesh(object_id, True)
282 | return mesh.IsClosed
283 |
284 |
285 | def IsMeshManifold(object_id):
286 | """Verifies a mesh object is manifold. A mesh for which every edge is shared
287 | by at most two faces is called manifold. If a mesh has at least one edge
288 | that is shared by more than two faces, then that mesh is called non-manifold
289 | Parameters:
290 | object_id (guid): identifier of a mesh object
291 | Returns:
292 | bool: True if successful, otherwise False.
293 | Example:
294 | import rhinoscriptsyntax as rs
295 | obj = rs.GetObject("Select a mesh", rs.filter.mesh)
296 | if rs.IsMeshClosed(obj):
297 | print("The mesh is manifold.")
298 | else:
299 | print("The mesh is non-manifold.")
300 | See Also:
301 | IsMesh
302 | IsMeshClosed
303 | """
304 | mesh = rhutil.coercemesh(object_id, True)
305 | rc = mesh.IsManifold(True)
306 | return rc[0]
307 |
308 |
309 | def IsPointOnMesh(object_id, point):
310 | """Verifies a point is on a mesh
311 | Parameters:
312 | object_id (guid): identifier of a mesh object
313 | point (point): test point
314 | Returns:
315 | bool: True if successful, otherwise False.
316 | None: on error.
317 | Example:
318 | import rhinoscriptsyntax as rs
319 | obj = rs.GetObject("Select a mesh")
320 | if rs.IsMesh(obj):
321 | point = rs.GetPointOnMesh(strObject, "Pick a test point")
322 | if point:
323 | if rs.IsPointOnMesh(obj, point):
324 | print("The point is on the mesh")
325 | else:
326 | print("The point is not on the mesh")
327 | See Also:
328 | IsMesh
329 | MeshClosestPoint
330 | """
331 | mesh = rhutil.coercemesh(object_id, True)
332 | point = rhutil.coerce3dpoint(point, True)
333 | max_distance = Rhino.RhinoMath.SqrtEpsilon
334 | face, pt = mesh.ClosestPoint(point, max_distance)
335 | return face>=0
336 |
337 |
338 | def JoinMeshes(object_ids, delete_input=False):
339 | """Joins two or or more mesh objects together
340 | Parameters:
341 | object_ids ([guid, ...]): identifiers of two or more mesh objects
342 | delete_input (bool, optional): delete input after joining
343 | Returns:
344 | guid: identifier of newly created mesh on success
345 | Example:
346 | import rhinoscriptsyntax as rs
347 | objs = rs.GetObjects("Select meshes to join", rs.filter.mesh)
348 | if objs and len(objs)>1: rs.JoinMeshes(objs, True)
349 | See Also:
350 | JoinCurves
351 | JoinSurfaces
352 | """
353 | meshes = [rhutil.coercemesh(id,True) for id in object_ids]
354 | joined_mesh = Rhino.Geometry.Mesh()
355 | joined_mesh.Append(meshes)
356 | rc = scriptcontext.doc.Objects.AddMesh(joined_mesh)
357 | if delete_input:
358 | for id in object_ids:
359 | guid = rhutil.coerceguid(id)
360 | scriptcontext.doc.Objects.Delete(guid,True)
361 | scriptcontext.doc.Views.Redraw()
362 | return rc
363 |
364 |
365 | def MeshArea(object_ids):
366 | """Returns approximate area of one or more mesh objects
367 | Parameters:
368 | object_ids ([guid, ...]): identifiers of one or more mesh objects
369 | Returns:
370 | list(number, number, number): if successful where
371 | [0] = number of meshes used in calculation
372 | [1] = total area of all meshes
373 | [2] = the error estimate
374 | None: if not successful
375 | Example:
376 | import rhinoscriptsyntax as rs
377 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
378 | if obj:
379 | area_rc = rs.MeshArea(obj)
380 | if area_rc: print("Mesh area:{}".format(area_rc[1]))
381 | See Also:
382 | MeshVolume
383 | """
384 | id = rhutil.coerceguid(object_ids)
385 | if id: object_ids = [object_ids]
386 | meshes_used = 0
387 | total_area = 0.0
388 | error_estimate = 0.0
389 | for id in object_ids:
390 | mesh = rhutil.coercemesh(id, True)
391 | if mesh:
392 | mp = Rhino.Geometry.AreaMassProperties.Compute(mesh)
393 | if mp:
394 | meshes_used += 1
395 | total_area += mp.Area
396 | error_estimate += mp.AreaError
397 | if meshes_used==0: return scriptcontext.errorhandler()
398 | return meshes_used, total_area, error_estimate
399 |
400 |
401 | def MeshAreaCentroid(object_id):
402 | """Calculates the area centroid of a mesh object
403 | Parameters:
404 | object_id (guid): identifier of a mesh object
405 | Returns:
406 | point: representing the area centroid if successful
407 | None: on error
408 | Example:
409 | import rhinoscriptsyntax as rs
410 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
411 | rs.AddPoint( rs.MeshAreaCentroid(obj) )
412 | See Also:
413 | IsMesh
414 | MeshArea
415 | MeshVolume
416 | MeshVolumeCentroid
417 | """
418 | mesh = rhutil.coercemesh(object_id, True)
419 | mp = Rhino.Geometry.AreaMassProperties.Compute(mesh)
420 | if mp is None: return scriptcontext.errorhandler()
421 | return mp.Centroid
422 |
423 |
424 | def MeshBooleanDifference(input0, input1, delete_input=True, tolerance=None):
425 | """Performs boolean difference operation on two sets of input meshes
426 | Parameters:
427 | input0, input1 (guid): identifiers of meshes
428 | delete_input (bool, optional): delete the input meshes
429 | tolerance (float, optional): this value is ignored.
430 | The parameter is only there to keep the function signature the same,
431 | The build in tolerenace always is used.
432 | Returns:
433 | list(guid, ...): identifiers of newly created meshes
434 | Example:
435 | import rhinoscriptsyntax as rs
436 | input0 = rs.GetObjects("Select first set of meshes", rs.filter.mesh)
437 | if input0:
438 | input1 = rs.GetObjects("Select second set of meshes", rs.filter.mesh)
439 | if input1: rs.MeshBooleanDifference(input0, input1)
440 | See Also:
441 | MeshBooleanIntersection
442 | MeshBooleanSplit
443 | MeshBooleanUnion
444 | """
445 | id = rhutil.coerceguid(input0)
446 | if id: input0 = [id]
447 | id = rhutil.coerceguid(input1)
448 | if id: input1 = [id]
449 | meshes0 = [rhutil.coercemesh(id, True) for id in input0]
450 | meshes1 = [rhutil.coercemesh(id, True) for id in input1]
451 | if not meshes0 or not meshes1: raise ValueError("no meshes to work with")
452 | newmeshes = Rhino.Geometry.Mesh.CreateBooleanDifference(meshes0, meshes1)
453 | rc = []
454 | for mesh in newmeshes:
455 | id = scriptcontext.doc.Objects.AddMesh(mesh)
456 | if id!=System.Guid.Empty: rc.append(id)
457 | if rc and delete_input:
458 | input = input0 + input1
459 | for id in input:
460 | id = rhutil.coerceguid(id, True)
461 | scriptcontext.doc.Objects.Delete(id, True)
462 | scriptcontext.doc.Views.Redraw()
463 | return rc
464 |
465 |
466 | def MeshBooleanIntersection(input0, input1, delete_input=True):
467 | """Performs boolean intersection operation on two sets of input meshes
468 | Parameters:
469 | input0, input1 (guid): identifiers of meshes
470 | delete_input (bool, optional): delete the input meshes
471 | Returns:
472 | list(guid, ...): identifiers of new meshes on success
473 | Example:
474 | import rhinoscriptsyntax as rs
475 | input0 = rs.GetObjects("Select first set of meshes", rs.filter.mesh)
476 | if input0:
477 | input1 = rs.GetObjects("Select second set of meshes", rs.filter.mesh)
478 | if input1: rs.MeshBooleanIntersection(input0, input1)
479 | See Also:
480 | MeshBooleanDifference
481 | MeshBooleanSplit
482 | MeshBooleanUnion
483 | """
484 | id = rhutil.coerceguid(input0)
485 | if id: input0 = [id]
486 | id = rhutil.coerceguid(input1)
487 | if id: input1 = [id]
488 | meshes0 = [rhutil.coercemesh(id, True) for id in input0]
489 | meshes1 = [rhutil.coercemesh(id, True) for id in input1]
490 | if not meshes0 or not meshes1: raise ValueError("no meshes to work with")
491 | newmeshes = Rhino.Geometry.Mesh.CreateBooleanIntersection(meshes0, meshes1)
492 | rc = []
493 | for mesh in newmeshes:
494 | id = scriptcontext.doc.Objects.AddMesh(mesh)
495 | if id!=System.Guid.Empty: rc.append(id)
496 | if rc and delete_input:
497 | input = input0 + input1
498 | for id in input:
499 | id = rhutil.coerceguid(id, True)
500 | scriptcontext.doc.Objects.Delete(id, True)
501 | scriptcontext.doc.Views.Redraw()
502 | return rc
503 |
504 |
505 | def MeshBooleanSplit(input0, input1, delete_input=True):
506 | """Performs boolean split operation on two sets of input meshes
507 | Parameters:
508 | input0, input1 (guid): identifiers of meshes
509 | delete_input (bool, optional): delete the input meshes
510 | Returns:
511 | list(guid, ...): identifiers of new meshes on success
512 | None: on error
513 | Example:
514 | import rhinoscriptsyntax as rs
515 | input0 = rs.GetObjects("Select first set of meshes", rs.filter.mesh)
516 | if input0:
517 | input1 = rs.GetObjects("Select second set of meshes", rs.filter.mesh)
518 | if input1: rs.MeshBooleanSplit(input0, input1)
519 | See Also:
520 | MeshBooleanDifference
521 | MeshBooleanIntersection
522 | MeshBooleanUnion
523 | """
524 | id = rhutil.coerceguid(input0)
525 | if id: input0 = [id]
526 | id = rhutil.coerceguid(input1)
527 | if id: input1 = [id]
528 | meshes0 = [rhutil.coercemesh(id, True) for id in input0]
529 | meshes1 = [rhutil.coercemesh(id, True) for id in input1]
530 | if not meshes0 or not meshes1: raise ValueError("no meshes to work with")
531 | newmeshes = Rhino.Geometry.Mesh.CreateBooleanSplit(meshes0, meshes1)
532 | rc = []
533 | for mesh in newmeshes:
534 | id = scriptcontext.doc.Objects.AddMesh(mesh)
535 | if id!=System.Guid.Empty: rc.append(id)
536 | if rc and delete_input:
537 | input = input0 + input1
538 | for id in input:
539 | id = rhutil.coerceguid(id, True)
540 | scriptcontext.doc.Objects.Delete(id, True)
541 | scriptcontext.doc.Views.Redraw()
542 | return rc
543 |
544 |
545 | def MeshBooleanUnion(mesh_ids, delete_input=True):
546 | """Performs boolean union operation on a set of input meshes
547 | Parameters:
548 | mesh_ids ([guid, ...]): identifiers of meshes
549 | delete_input (bool, optional): delete the input meshes
550 | Returns:
551 | list(guid, ...): identifiers of new meshes
552 | Example:
553 | import rhinoscriptsyntax as rs
554 | input = rs.GetObjects("Select meshes to union", rs.filter.mesh)
555 | if input: rs.MeshBooleanUnion(input)
556 | See Also:
557 | MeshBooleanDifference
558 | MeshBooleanIntersection
559 | MeshBooleanSplit
560 | """
561 | if len(mesh_ids)<2: raise ValueError("mesh_ids must contain at least 2 meshes")
562 | meshes = [rhutil.coercemesh(id, True) for id in mesh_ids]
563 | newmeshes = Rhino.Geometry.Mesh.CreateBooleanUnion(meshes)
564 | rc = []
565 | for mesh in newmeshes:
566 | id = scriptcontext.doc.Objects.AddMesh(mesh)
567 | if id!=System.Guid.Empty: rc.append(id)
568 | if rc and delete_input:
569 | for id in mesh_ids:
570 | id = rhutil.coerceguid(id, True)
571 | scriptcontext.doc.Objects.Delete(id, True)
572 | scriptcontext.doc.Views.Redraw()
573 | return rc
574 |
575 |
576 | def MeshClosestPoint(object_id, point, maximum_distance=None):
577 | """Returns the point on a mesh that is closest to a test point
578 | Parameters:
579 | object_id (guid): identifier of a mesh object
580 | point (point): point to test
581 | maximum_distance (number, optional): upper bound used for closest point calculation.
582 | If you are only interested in finding a point Q on the mesh when
583 | point.DistanceTo(Q) < maximum_distance, then set maximum_distance to
584 | that value
585 | Returns:
586 | tuple(point, number): containing the results of the calculation where
587 | [0] = the 3-D point on the mesh
588 | [1] = the index of the mesh face on which the 3-D point lies
589 | None: on error
590 | Example:
591 | import rhinocriptsyntax as rs
592 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
593 | point = rs.GetPoint("Pick test point")
594 | intersect = rs.MeshClosestPoint(obj, point)
595 | if intersect: rs.AddPoint(intersect)
596 | See Also:
597 | MeshFaceCount
598 | MeshFaces
599 | """
600 | mesh = rhutil.coercemesh(object_id, True)
601 | point = rhutil.coerce3dpoint(point, True)
602 | tolerance=maximum_distance if maximum_distance else 0.0
603 | face, closest_point = mesh.ClosestPoint(point, tolerance)
604 | if face<0: return scriptcontext.errorhandler()
605 | return closest_point, face
606 |
607 |
608 | def MeshFaceCenters(mesh_id):
609 | """Returns the center of each face of the mesh object
610 | Parameters:
611 | mesh_id (guid): identifier of a mesh object
612 | Returns:
613 | list(point, ...): points defining the center of each face
614 | Example:
615 | import rhinoscriptsyntax as rs
616 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
617 | centers = rs.MeshFaceCenters(obj)
618 | if centers:
619 | for point in centers: rs.AddPoint(point)
620 | See Also:
621 | IsMesh
622 | MeshFaceCount
623 | MeshFaces
624 | """
625 | mesh = rhutil.coercemesh(mesh_id, True)
626 | return [mesh.Faces.GetFaceCenter(i) for i in range(mesh.Faces.Count)]
627 |
628 |
629 | def MeshFaceCount(object_id):
630 | """Returns total face count of a mesh object
631 | Parameters:
632 | object_id (guid): identifier of a mesh object
633 | Returns:
634 | number: the number of mesh faces if successful
635 | Example:
636 | import rhinoscriptsyntax as rs
637 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
638 | print("Quad faces:{}".format(rs.MeshQuadCount(obj)))
639 | print("Triangle faces:{}".format(rs.MeshTriangleCount(obj)))
640 | print("Total faces:{}".format(rs.MeshFaceCount(obj)))
641 | See Also:
642 | IsMesh
643 | MeshFaces
644 | MeshVertexCount
645 | MeshVertices
646 | """
647 | mesh = rhutil.coercemesh(object_id, True)
648 | return mesh.Faces.Count
649 |
650 |
651 | def MeshFaceNormals(mesh_id):
652 | """Returns the face unit normal for each face of a mesh object
653 | Parameters:
654 | mesh_id (guid): identifier of a mesh object
655 | Returns:
656 | list(vector, ...): 3D vectors that define the face unit normals of the mesh
657 | None: on error
658 | Example:
659 | import rhinoscriptsyntax as rs
660 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
661 | normals = rs.MeshFaceNormals(obj)
662 | if normals:
663 | for vector in normals: print(vector)
664 | See Also:
665 | MeshHasFaceNormals
666 | MeshFaceCount
667 | MeshFaces
668 | """
669 | mesh = rhutil.coercemesh(mesh_id, True)
670 | if mesh.FaceNormals.Count != mesh.Faces.Count:
671 | mesh.FaceNormals.ComputeFaceNormals()
672 | rc = []
673 | for i in compat.RANGE(mesh.FaceNormals.Count):
674 | normal = mesh.FaceNormals[i]
675 | rc.append(Rhino.Geometry.Vector3d(normal))
676 | return rc
677 |
678 |
679 | def MeshFaces(object_id, face_type=True):
680 | """Returns face vertices of a mesh
681 | Parameters:
682 | object_id (guid): identifier of a mesh object
683 | face_type (bool, optional): The face type to be returned. True = both triangles
684 | and quads. False = only triangles
685 | Returns:
686 | list([point, point, point, point], ...): 3D points that define the face vertices of the mesh. If
687 | face_type is True, then faces are returned as both quads and triangles
688 | (4 3D points). For triangles, the third and fourth vertex will be
689 | identical. If face_type is False, then faces are returned as only
690 | triangles(3 3D points). Quads will be converted to triangles.
691 | Example:
692 | import rhinoscriptsyntax as rs
693 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
694 | faces = rs.MeshFaces(obj, False)
695 | if faces:
696 | rs.EnableRedraw(False)
697 | i = 0
698 | while( i<=len(faces) ):
699 | face = faces[i], faces[i+1], faces[i+2], faces[i]
700 | rs.AddPolyline( face )
701 | i += 3
702 | rs.EnableRedraw(True)
703 | See Also:
704 | IsMesh
705 | MeshFaceCount
706 | MeshVertexCount
707 | MeshVertices
708 | """
709 | mesh = rhutil.coercemesh(object_id, True)
710 | rc = []
711 | for i in compat.RANGE(mesh.Faces.Count):
712 | getrc, p0, p1, p2, p3 = mesh.Faces.GetFaceVertices(i)
713 | p0 = Rhino.Geometry.Point3d(p0)
714 | p1 = Rhino.Geometry.Point3d(p1)
715 | p2 = Rhino.Geometry.Point3d(p2)
716 | p3 = Rhino.Geometry.Point3d(p3)
717 | rc.append( p0 )
718 | rc.append( p1 )
719 | rc.append( p2 )
720 | if face_type:
721 | rc.append(p3)
722 | else:
723 | if p2!=p3:
724 | rc.append( p2 )
725 | rc.append( p3 )
726 | rc.append( p0 )
727 | return rc
728 |
729 |
730 | def MeshFaceVertices(object_id):
731 | """Returns the vertex indices of all faces of a mesh object
732 | Parameters:
733 | object_id (guid): identifier of a mesh object
734 | Returns:
735 | list((number, number, number, number), ...): containing tuples of 4 numbers that define the vertex indices for
736 | each face of the mesh. Both quad and triangle faces are returned. If the
737 | third and fourth vertex indices are identical, the face is a triangle.
738 | Example:
739 | import rhinoscriptsyntax as rs
740 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
741 | faceVerts = rs.MeshFaceVertices( obj )
742 | if faceVerts:
743 | for count, face in enumerate(faceVerts):
744 | print("face({}) = ({}, {}, {}, {})".format(count, face[0], face[1], face[2], face[3]))
745 | See Also:
746 | IsMesh
747 | MeshFaceCount
748 | MeshFaces
749 | """
750 | mesh = rhutil.coercemesh(object_id, True)
751 | rc = []
752 | for i in compat.RANGE(mesh.Faces.Count):
753 | face = mesh.Faces.GetFace(i)
754 | rc.append( (face.A, face.B, face.C, face.D) )
755 | return rc
756 |
757 |
758 | def MeshHasFaceNormals(object_id):
759 | """Verifies a mesh object has face normals
760 | Parameters:
761 | object_id (guid): identifier of a mesh object
762 | Returns:
763 | bool: True if successful, otherwise False.
764 | Example:
765 | import rhinoscriptsyntax as rs
766 | obj = rs.GetObject("Select a mesh", rs.filter.mesh)
767 | if rs.MeshHasFaceNormals(obj):
768 | print("The mesh has face normal.")
769 | else:
770 | print("The mesh does not have face normals.")
771 | See Also:
772 | MeshFaceNormals
773 | """
774 | mesh = rhutil.coercemesh(object_id, True)
775 | return mesh.FaceNormals.Count>0
776 |
777 |
778 | def MeshHasTextureCoordinates(object_id):
779 | """Verifies a mesh object has texture coordinates
780 | Parameters:
781 | object_id (guid): identifier of a mesh object
782 | Returns:
783 | bool: True if successful, otherwise False.
784 | Example:
785 | import rhinoscriptsyntax as rs
786 | obj = rs.GetObject("Select a mesh", rs.filter.mesh)
787 | if rs.MeshHasTextureCoordinates(obj):
788 | print("The mesh has texture coordinates.")
789 | else:
790 | print("The mesh does not have texture coordinates.")
791 | See Also:
792 |
793 | """
794 | mesh = rhutil.coercemesh(object_id, True)
795 | return mesh.TextureCoordinates.Count>0
796 |
797 |
798 | def MeshHasVertexColors(object_id):
799 | """Verifies a mesh object has vertex colors
800 | Parameters:
801 | object_id (guid): identifier of a mesh object
802 | Returns:
803 | bool: True if successful, otherwise False.
804 | Example:
805 | import rhinoscriptsyntax as rs
806 | obj = rs.GetObject("Select a mesh", rs.filter.mesh)
807 | if rs.mesh.MeshHasVertexColors(obj):
808 | print("The mesh has vertex colors.")
809 | else:
810 | print("The mesh does not have vertex colors.")
811 | See Also:
812 | MeshVertexColors
813 | """
814 | mesh = rhutil.coercemesh(object_id, True)
815 | return mesh.VertexColors.Count>0
816 |
817 |
818 | def MeshHasVertexNormals(object_id):
819 | """Verifies a mesh object has vertex normals
820 | Parameters:
821 | object_id (guid): identifier of a mesh object
822 | Returns:
823 | bool: True if successful, otherwise False.
824 | Example:
825 | import rhinoscriptsyntax as rs
826 | obj = rs.GetObject("Select a mesh", rs.filter.mesh)
827 | if rs.MeshHasVertexNormals(obj):
828 | print("The mesh has vertex normals.")
829 | else:
830 | print("The mesh does not have vertex normals.")
831 | See Also:
832 | MeshVertexNormals
833 | """
834 | mesh = rhutil.coercemesh(object_id, True)
835 | return mesh.Normals.Count>0
836 |
837 |
838 | def MeshMeshIntersection(mesh1, mesh2, tolerance=None):
839 | """Calculates the intersections of a mesh object with another mesh object
840 | Parameters:
841 | mesh1, mesh2 (guid): identifiers of meshes
842 | tolerance (number, optional): the intersection tolerance. Defaults to ModelAbsoluteTolerance * MeshIntersectionsTolerancesCoefficient
843 | Returns:
844 | list(point, ...): of points that define the vertices of the intersection curves
845 | Example:
846 | import rhinoscriptsyntax as rs
847 | mesh1 = rs.GetObject("Select first mesh to intersect", rs.filter.mesh)
848 | mesh2 = rs.GetObject("Select second mesh to intersect", rs.filter.mesh)
849 | results = rs.MeshMeshIntersection(mesh1, mesh2)
850 | if results:
851 | for points in results: rs.AddPolyline(points)
852 | See Also:
853 | CurveMeshIntersection
854 | MeshClosestPoint
855 | """
856 | mesh1 = rhutil.coercemesh(mesh1, True)
857 | mesh2 = rhutil.coercemesh(mesh2, True)
858 | if tolerance is None:
859 | tolerance = scriptcontext.doc.ModelAbsoluteTolerance * Rhino.Geometry.Intersect.Intersection.MeshIntersectionsTolerancesCoefficient
860 | polylines = Rhino.Geometry.Intersect.Intersection.MeshMeshAccurate(mesh1, mesh2, tolerance)
861 | if polylines: return list(polylines)
862 |
863 |
864 | def MeshNakedEdgePoints(object_id):
865 | """Identifies the naked edge points of a mesh object. This function shows
866 | where mesh vertices are not completely surrounded by faces. Joined
867 | meshes, such as are made by MeshBox, have naked mesh edge points where
868 | the sub-meshes are joined
869 | Parameters:
870 | object_id (guid): identifier of a mesh object
871 | Returns:
872 | list(bool, ...): of boolean values that represent whether or not a mesh vertex is
873 | naked or not. The number of elements in the list will be equal to
874 | the value returned by MeshVertexCount. In which case, the list will
875 | identify the naked status for each vertex returned by MeshVertices
876 | None: on error
877 | Example:
878 | import rhinoscriptsyntax as rs
879 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
880 | vertices = rs.MeshVertices( obj )
881 | naked = rs.MeshNakedEdgePoints( obj )
882 | for i, vertex in enumerate(vertices):
883 | if naked[i]: rs.AddPoint(vertex)
884 | See Also:
885 | IsMesh
886 | MeshVertexCount
887 | MeshVertices
888 | """
889 | mesh = rhutil.coercemesh(object_id, True)
890 | rc = mesh.GetNakedEdgePointStatus()
891 | return rc
892 |
893 |
894 | def MeshOffset(mesh_id, distance):
895 | """Makes a new mesh with vertices offset at a distance in the opposite
896 | direction of the existing vertex normals
897 | Parameters:
898 | mesh_id (guid): identifier of a mesh object
899 | distance (number, optional): the distance to offset
900 | Returns:
901 | guid: identifier of the new mesh object if successful
902 | None: on error
903 | Example:
904 | import rhinoscriptsyntax as rs
905 | mesh = rs.GetObject("Select mesh to offset", rs.filter.mesh)
906 | rs.MeshOffset( mesh, 10.0 )
907 | See Also:
908 | IsMesh
909 | """
910 | mesh = rhutil.coercemesh(mesh_id, True)
911 | offsetmesh = mesh.Offset(distance)
912 | if offsetmesh is None: return scriptcontext.errorhandler()
913 | rc = scriptcontext.doc.Objects.AddMesh(offsetmesh)
914 | if rc==System.Guid.Empty: raise Exception("unable to add mesh to document")
915 | scriptcontext.doc.Views.Redraw()
916 | return rc
917 |
918 |
919 | def MeshOutline(object_ids, view=None):
920 | """Creates polyline curve outlines of mesh objects
921 | Parameters:
922 | objects_ids ([guid, ...]): identifiers of meshes to outline
923 | view (str, optional): view to use for outline direction
924 | Returns:
925 | list(guid, ...): polyline curve identifiers on success
926 | Example:
927 | import rhinoscriptsyntax as rs
928 | objs = rs.GetObjects("Select mesh objects to outline", rs.filter.mesh)
929 | if objs: rs.MeshOutline(objs)
930 | See Also:
931 | IsMesh
932 | """
933 | viewport = __viewhelper(view).MainViewport
934 | meshes = []
935 | mesh = rhutil.coercemesh(object_ids, False)
936 | if mesh: meshes.append(mesh)
937 | else: meshes = [rhutil.coercemesh(id,True) for id in object_ids]
938 | rc = []
939 | for mesh in meshes:
940 | polylines = mesh.GetOutlines(viewport)
941 | if not polylines: continue
942 | for polyline in polylines:
943 | id = scriptcontext.doc.Objects.AddPolyline(polyline)
944 | rc.append(id)
945 | scriptcontext.doc.Views.Redraw()
946 | return rc
947 |
948 |
949 | def MeshQuadCount(object_id):
950 | """Returns the number of quad faces of a mesh object
951 | Parameters:
952 | object_id (guid): identifier of a mesh object
953 | Returns:
954 | number: the number of quad mesh faces if successful
955 | Example:
956 | import rhinoscriptsyntax as rs
957 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
958 | print("Quad faces:{}".format(rs.MeshQuadCount(obj)))
959 | print("Triangle faces:{}".format(rs.MeshTriangleCount(obj)))
960 | print("Total faces:{}".format(rs.MeshFaceCount(obj)))
961 | See Also:
962 | MeshQuadCount
963 | """
964 | mesh = rhutil.coercemesh(object_id, True)
965 | return mesh.Faces.QuadCount
966 |
967 |
968 | def MeshQuadsToTriangles(object_id):
969 | """Converts a mesh object's quad faces to triangles
970 | Parameters:
971 | object_id (guid): identifier of a mesh object
972 | Returns:
973 | bool: True or False indicating success or failure
974 | Example:
975 | import rhinoscriptsyntax as rs
976 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
977 | if rs.MeshQuadCount(obj)>0:
978 | rs.MeshQuadsToTriangles(obj)
979 | See Also:
980 |
981 | """
982 | mesh = rhutil.coercemesh(object_id, True)
983 | rc = True
984 | if mesh.Faces.QuadCount>0:
985 | rc = mesh.Faces.ConvertQuadsToTriangles()
986 | if rc:
987 | id = rhutil.coerceguid(object_id, True)
988 | scriptcontext.doc.Objects.Replace(id, mesh)
989 | scriptcontext.doc.Views.Redraw()
990 | return rc
991 |
992 |
993 | def MeshToNurb(object_id, trimmed_triangles=True, delete_input=False):
994 | """Duplicates each polygon in a mesh with a NURBS surface. The resulting
995 | surfaces are then joined into a polysurface and added to the document
996 | Parameters:
997 | object_id (guid): identifier of a mesh object
998 | trimmed_triangles (bool, optional): if True, triangles in the mesh will be
999 | represented by a trimmed plane
1000 | delete_input (bool, optional): delete input object
1001 | Returns:
1002 | list(guid, ...): identifiers for the new breps on success
1003 | Example:
1004 | import rhinoscriptsyntax as rs
1005 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
1006 | if obj: rs.MeshToNurb(obj)
1007 | See Also:
1008 | IsMesh
1009 | MeshFaces
1010 | MeshVertices
1011 | """
1012 | mesh = rhutil.coercemesh(object_id, True)
1013 | pieces = mesh.SplitDisjointPieces()
1014 | breps = [Rhino.Geometry.Brep.CreateFromMesh(piece,trimmed_triangles) for piece in pieces]
1015 | rhobj = rhutil.coercerhinoobject(object_id, True, True)
1016 | attr = rhobj.Attributes
1017 | ids = [scriptcontext.doc.Objects.AddBrep(brep, attr) for brep in breps]
1018 | if delete_input: scriptcontext.doc.Objects.Delete(rhobj, True)
1019 | scriptcontext.doc.Views.Redraw()
1020 | return ids
1021 |
1022 |
1023 | def MeshTriangleCount(object_id):
1024 | """Returns number of triangular faces of a mesh
1025 | Parameters:
1026 | object_id (guid): identifier of a mesh object
1027 | Returns:
1028 | number: The number of triangular mesh faces if successful
1029 | Example:
1030 | import rhinoscriptsyntax as rs
1031 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
1032 | print("Quad faces:{}".format(rs.MeshQuadCount(obj)))
1033 | print("Triangle faces:{}".format(rs.MeshTriangleCount(obj)))
1034 | print("Total faces:{}".format(rs.MeshFaceCount(obj)))
1035 | See Also:
1036 | IsMesh
1037 | """
1038 | mesh = rhutil.coercemesh(object_id, True)
1039 | return mesh.Faces.TriangleCount
1040 |
1041 |
1042 | def MeshVertexColors(mesh_id, colors=0):
1043 | """Returns of modifies vertex colors of a mesh
1044 | Parameters:
1045 | mesh_id (guid): identifier of a mesh object
1046 | colors 9{color, ...], optional) A list of color values. Note, for each vertex, there must
1047 | be a corresponding vertex color. If the value is None, then any
1048 | existing vertex colors will be removed from the mesh
1049 | Returns:
1050 | color: if colors is not specified, the current vertex colors
1051 | color: if colors is specified, the previous vertex colors
1052 | Example:
1053 | import rhinoscriptsyntax as rs
1054 | import random
1055 |
1056 | def randomcolor():
1057 | r = random.randint(0,255)
1058 | g = random.randint(0,255)
1059 | b = random.randint(0,255)
1060 | return r,g,b
1061 |
1062 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
1063 | if obj:
1064 | colors = []
1065 | for i in range(rs.MeshVertexCount(obj)): colors.append( randomcolor() )
1066 | rs.MeshVertexColors( obj, colors )
1067 | See Also:
1068 | MeshHasVertexColors
1069 | MeshVertexCount
1070 | MeshVertices
1071 | """
1072 | mesh = rhutil.coercemesh(mesh_id, True)
1073 | rc = [mesh.VertexColors[i] for i in range(mesh.VertexColors.Count)]
1074 | if colors==0: return rc
1075 | if colors is None:
1076 | mesh.VertexColors.Clear()
1077 | else:
1078 | color_count = len(colors)
1079 | if color_count!=mesh.Vertices.Count:
1080 | raise ValueError("length of colors must match vertex count")
1081 | colors = [rhutil.coercecolor(c) for c in colors]
1082 | mesh.VertexColors.Clear()
1083 | for c in colors: mesh.VertexColors.Add(c)
1084 | id = rhutil.coerceguid(mesh_id, True)
1085 | scriptcontext.doc.Objects.Replace(id, mesh)
1086 | scriptcontext.doc.Views.Redraw()
1087 | return rc
1088 |
1089 |
1090 | def MeshVertexCount(object_id):
1091 | """Returns the vertex count of a mesh
1092 | Parameters:
1093 | object_id (guid): identifier of a mesh object
1094 | Returns:
1095 | number: The number of mesh vertices if successful.
1096 | Example:
1097 | import rhinoscriptsyntax as rs
1098 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
1099 | print("Vertex count: {}".format(rs.MeshVertexCount(obj)))
1100 | See Also:
1101 | IsMesh
1102 | MeshFaceCount
1103 | MeshFaces
1104 | MeshVertices
1105 | """
1106 | mesh = rhutil.coercemesh(object_id, True)
1107 | return mesh.Vertices.Count
1108 |
1109 |
1110 | def MeshVertexFaces(mesh_id, vertex_index):
1111 | """Returns the mesh faces that share a specified mesh vertex
1112 | Parameters:
1113 | mesh_id (guid): identifier of a mesh object
1114 | vertex_index (number): index of the mesh vertex to find faces for
1115 | Returns:
1116 | list(number, ...): face indices on success
1117 | None: on error
1118 | Example:
1119 | import rhinoscriptsyntax as rs
1120 | import random
1121 | def TestMeshVertexFaces():
1122 | mesh = rs.GetObject("Select mesh", rs.filter.mesh)
1123 | vertices = rs.MeshVertices(mesh)
1124 | meshfaces = rs.MeshFaceVertices(mesh)
1125 | vertex = random.randint(0, len(vertices)-1) #some random vertex
1126 | vertex_faces = rs.MeshVertexFaces(mesh, vertex )
1127 | if vertex_faces:
1128 | rs.AddPoint( vertices[vertex] )
1129 | for face_index in vertex_faces:
1130 | face = meshfaces[face_index]
1131 | polyline = []
1132 | polyline.append( vertices[face[0]] )
1133 | polyline.append( vertices[face[1]] )
1134 | polyline.append( vertices[face[2]] )
1135 | if face[2]!=face[3]:
1136 | polyline.append( vertices[face[3]] )
1137 | polyline.append( polyline[0] )
1138 | rs.AddPolyline(polyline)
1139 |
1140 | TestMeshVertexFaces()
1141 | See Also:
1142 | MeshFaces
1143 | MeshFaceVertices
1144 | MeshVertices
1145 | """
1146 | mesh = rhutil.coercemesh(mesh_id, True)
1147 | return mesh.Vertices.GetVertexFaces(vertex_index)
1148 |
1149 |
1150 | def MeshVertexNormals(mesh_id):
1151 | """Returns the vertex unit normal for each vertex of a mesh
1152 | Parameters:
1153 | mesh_id (guid): identifier of a mesh object
1154 | Returns:
1155 | list(vector, ...): of vertex normals, (empty list if no normals exist)
1156 | Example:
1157 | import rhinoscriptsyntax as rs
1158 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
1159 | normals = rs.MeshVertexNormals(obj)
1160 | if normals:
1161 | for normal in normals: print(normal)
1162 | See Also:
1163 | MeshHasVertexNormals
1164 | MeshVertexCount
1165 | MeshVertices
1166 | """
1167 | mesh = rhutil.coercemesh(mesh_id, True)
1168 | count = mesh.Normals.Count
1169 | if count<1: return []
1170 | return [Rhino.Geometry.Vector3d(mesh.Normals[i]) for i in compat.RANGE(count)]
1171 |
1172 |
1173 | def MeshVertices(object_id):
1174 | """Returns the vertices of a mesh
1175 | Parameters:
1176 | object_id (guid): identifier of a mesh object
1177 | Returns:
1178 | list(point, ...): vertex points in the mesh
1179 | Example:
1180 | import rhinoscriptsyntax as rs
1181 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
1182 | vertices = rs.MeshVertices(obj)
1183 | if vertices: rs.AddPointCloud(vertices)
1184 | See Also:
1185 | IsMesh
1186 | MeshFaceCount
1187 | MeshFaces
1188 | MeshVertexCount
1189 | """
1190 | mesh = rhutil.coercemesh(object_id, True)
1191 | count = mesh.Vertices.Count
1192 | rc = []
1193 | for i in compat.RANGE(count):
1194 | vertex = mesh.Vertices.Point3dAt(i)
1195 | rc.append(vertex)
1196 | return rc
1197 |
1198 |
1199 | def MeshVolume(object_ids):
1200 | """Returns the approximate volume of one or more closed meshes
1201 | Parameters:
1202 | object_ids ([guid, ...]): identifiers of one or more mesh objects
1203 | Returns:
1204 | tuple(number, number, number): containing 3 velues if successful where
1205 | [0] = number of meshes used in volume calculation
1206 | [1] = total volume of all meshes
1207 | [2] = the error estimate
1208 | None: if not successful
1209 | Example:
1210 | import rhinoscriptsyntax as rs
1211 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
1212 | if obj and rs.IsMeshClosed(obj):
1213 | volume = rs.MeshVolume(obj)
1214 | if volume: print("Mesh volume:{}".format(volume[1]))
1215 | See Also:
1216 | IsMeshClosed
1217 | MeshArea
1218 | """
1219 | id = rhutil.coerceguid(object_ids)
1220 | if id: object_ids = [id]
1221 | meshes_used = 0
1222 | total_volume = 0.0
1223 | error_estimate = 0.0
1224 | for id in object_ids:
1225 | mesh = rhutil.coercemesh(id, True)
1226 | mp = Rhino.Geometry.VolumeMassProperties.Compute(mesh)
1227 | if mp:
1228 | meshes_used += 1
1229 | total_volume += mp.Volume
1230 | error_estimate += mp.VolumeError
1231 | if meshes_used==0: return scriptcontext.errorhandler()
1232 | return meshes_used, total_volume, error_estimate
1233 |
1234 |
1235 | def MeshVolumeCentroid(object_id):
1236 | """Calculates the volume centroid of a mesh
1237 | Parameters:
1238 | object_id (guid): identifier of a mesh object
1239 | Returns:
1240 | point: Point3d representing the volume centroid
1241 | None: on error
1242 | Example:
1243 | import rhinoscriptsyntax as rs
1244 | obj = rs.GetObject("Select mesh", rs.filter.mesh )
1245 | centroid = rs.MeshVolumeCentroid(obj)
1246 | rs.AddPoint( centroid )
1247 | See Also:
1248 | IsMesh
1249 | MeshArea
1250 | MeshAreaCentroid
1251 | MeshVolume
1252 | """
1253 | mesh = rhutil.coercemesh(object_id, True)
1254 | mp = Rhino.Geometry.VolumeMassProperties.Compute(mesh)
1255 | if mp: return mp.Centroid
1256 | return scriptcontext.errorhandler()
1257 |
1258 |
1259 | def PullCurveToMesh(mesh_id, curve_id):
1260 | """Pulls a curve to a mesh. The function makes a polyline approximation of
1261 | the input curve and gets the closest point on the mesh for each point on
1262 | the polyline. Then it "connects the points" to create a polyline on the mesh
1263 | Parameters:
1264 | mesh_id (guid): identifier of mesh that pulls
1265 | curve_id (guid): identifier of curve to pull
1266 | Returns:
1267 | guid: identifier new curve on success
1268 | None: on error
1269 | Example:
1270 | import rhinoscriptsyntax as rs
1271 | mesh = rs.GetObject("Select mesh that pulls", rs.filter.mesh)
1272 | curve = rs.GetObject("Select curve to pull", rs.filter.curve)
1273 | rs.PullCurveToMesh( mesh, curve )
1274 | See Also:
1275 | IsMesh
1276 | """
1277 | mesh = rhutil.coercemesh(mesh_id, True)
1278 | curve = rhutil.coercecurve(curve_id, -1, True)
1279 | tol = scriptcontext.doc.ModelAbsoluteTolerance
1280 | polyline = curve.PullToMesh(mesh, tol)
1281 | if not polyline: return scriptcontext.errorhandler()
1282 | rc = scriptcontext.doc.Objects.AddCurve(polyline)
1283 | if rc==System.Guid.Empty: raise Exception("unable to add polyline to document")
1284 | scriptcontext.doc.Views.Redraw()
1285 | return rc
1286 |
1287 |
1288 | def SplitDisjointMesh(object_id, delete_input=False):
1289 | """Splits up a mesh into its unconnected pieces
1290 | Parameters:
1291 | object_id (guid): identifier of a mesh object
1292 | delete_input (bool, optional): delete the input object
1293 | Returns:
1294 | list(guid, ...): identifiers for the new meshes
1295 | Example:
1296 | import rhinoscriptsyntax as rs
1297 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
1298 | if rs.DisjointMeshCount(obj)>0: rs.SplitDisjointMesh(obj)
1299 | See Also:
1300 | IsMesh
1301 | DisjointMeshCount
1302 | """
1303 | mesh = rhutil.coercemesh(object_id, True)
1304 | pieces = mesh.SplitDisjointPieces()
1305 | rc = [scriptcontext.doc.Objects.AddMesh(piece) for piece in pieces]
1306 | if rc and delete_input:
1307 | id = rhutil.coerceguid(object_id, True)
1308 | scriptcontext.doc.Objects.Delete(id, True)
1309 | scriptcontext.doc.Views.Redraw()
1310 | return rc
1311 |
1312 |
1313 | def UnifyMeshNormals(object_id):
1314 | """Fixes inconsistencies in the directions of faces of a mesh
1315 | Parameters:
1316 | object_id (guid): identifier of a mesh object
1317 | Returns:
1318 | number: the number of faces that were modified
1319 | Example:
1320 | import rhinoscriptsyntax as rs
1321 | obj = rs.GetObject("Select mesh", rs.filter.mesh)
1322 | if rs.IsMesh(obj): rs.UnifyMeshNormals(obj)
1323 | See Also:
1324 | IsMesh
1325 | """
1326 | mesh = rhutil.coercemesh(object_id, True)
1327 | rc = mesh.UnifyNormals()
1328 | if rc>0:
1329 | id = rhutil.coerceguid(object_id, True)
1330 | scriptcontext.doc.Objects.Replace(id, mesh)
1331 | scriptcontext.doc.Views.Redraw()
1332 | return rc
1333 |
```
--------------------------------------------------------------------------------
/rhino_mcp_server/static/userinterface.py:
--------------------------------------------------------------------------------
```python
1 | import math
2 |
3 | import System
4 | import System.Drawing
5 | import System.Windows.Forms
6 |
7 | import Eto.Forms
8 |
9 | import Rhino
10 | import Rhino.UI
11 |
12 | import scriptcontext
13 |
14 | import rhinocompat as compat
15 | from rhinoscript import utility as rhutil
16 | from rhinoscript.view import __viewhelper
17 |
18 |
19 | def BrowseForFolder(folder=None, message=None, title=None):
20 | """Display browse-for-folder dialog allowing the user to select a folder
21 | Parameters:
22 | folder (str, optional): a default folder
23 | message (str, optional): a prompt or message
24 | title (str, optional): a dialog box title
25 | Returns:
26 | str: selected folder
27 | None: on error
28 | Example:
29 | import rhinoscriptsyntax as rs
30 | folder = rs.BrowseForFolder("C:\\Program Files\\" )
31 | if folder: print(folder)
32 | See Also:
33 | OpenFileName
34 | SaveFileName
35 | """
36 | dlg = Eto.Forms.SelectFolderDialog()
37 | if folder:
38 | if not isinstance(folder, str): folder = str(folder)
39 | dlg.Directory = folder
40 | if message:
41 | if not isinstance(message, str): message = str(message)
42 | dlg.Title = message
43 | if title:
44 | if not isinstance(title, str): title = str(title)
45 | dlg.Title = title
46 | if message and title:
47 | if not isinstance(message, str): message = str(message)
48 | if not isinstance(title, str): title = str(title)
49 | dlg.Title = title + ": " + message
50 | if dlg.ShowDialog(None)==Eto.Forms.DialogResult.Ok:
51 | return dlg.Directory
52 |
53 |
54 | def CheckListBox(items, message=None, title=None):
55 | """Displays a list of items in a checkable-style list dialog box
56 | Parameters:
57 | items ([[str, bool], ...]): a list of tuples containing a string and a boolean check state
58 | message (str, optional): a prompt or message
59 | title (str, optional): a dialog box title
60 | Returns:
61 | list((str, bool), ...): of tuples containing the input string in items along with their new boolean check value
62 | None: on error
63 | Example:
64 | import rhinoscriptsyntax as rs
65 | layers = rs.LayerNames()
66 | if layers:
67 | items = [(layer, rs.IsLayerOn(layer)) for layer in layers]
68 | results = rs.CheckListBox(items, "Turn layers on/off", "Layers")
69 | if results:
70 | for layer, state in results: rs.LayerVisible(layer, state)
71 | See Also:
72 | ComboListBox
73 | ListBox
74 | MultiListBox
75 | PropertyListBox
76 | """
77 | checkstates = [item[1] for item in items]
78 | itemstrs = [str(item[0]) for item in items]
79 | newcheckstates = Rhino.UI.Dialogs.ShowCheckListBox(title, message, itemstrs, checkstates)
80 | if newcheckstates:
81 | rc = compat.ITERATOR2LIST(zip(itemstrs, newcheckstates))
82 | return rc
83 | return scriptcontext.errorhandler()
84 |
85 |
86 | def ComboListBox(items, message=None, title=None):
87 | """Displays a list of items in a combo-style list box dialog.
88 | Parameters:
89 | items ([str, ...]): a list of string
90 | message (str, optional): a prompt of message
91 | title (str, optional): a dialog box title
92 | Returns:
93 | str: The selected item if successful
94 | None: if not successful or on error
95 | Example:
96 | import rhinoscriptsyntax as rs
97 | layers = rs.LayerNames()
98 | if layers:
99 | layer = rs.ComboListBox(layers, "Select current layer")
100 | if layer: rs.CurrentLayer(layer)
101 | See Also:
102 | CheckListBox
103 | ListBox
104 | MultiListBox
105 | PropertyListBox
106 | """
107 | return Rhino.UI.Dialogs.ShowComboListBox(title, message, items)
108 |
109 |
110 | def EditBox(default_string=None, message=None, title=None):
111 | """Display dialog prompting the user to enter a string. The
112 | string value may span multiple lines
113 | Parameters:
114 | default_string (str, optional): a default string value.
115 | message (str, optional): a prompt message.
116 | title (str, optional): a dialog box title.
117 | Returns:
118 | str: Multiple lines that are separated by carriage return-linefeed combinations if successful
119 | None: if not successful
120 | Example:
121 | import rhinoscriptsyntax as rs
122 | text = rs.EditBox(message="Enter some text")
123 | print(text)
124 | See Also:
125 | GetString
126 | StringBox
127 | """
128 | rc, text = Rhino.UI.Dialogs.ShowEditBox(title, message, default_string, True)
129 | return text
130 |
131 | def GetAngle(point=None, reference_point=None, default_angle_degrees=0, message=None):
132 | """Pause for user input of an angle
133 | Parameters:
134 | point (point): starting, or base point
135 | reference_point (point, optional): if specified, the reference angle is calculated
136 | from it and the base point
137 | default_angle_degrees (number, optional): a default angle value specified
138 | message (str, optional): a prompt to display
139 | Returns:
140 | number: angle in degree if successful
141 | None: on error
142 | Example:
143 | import rhinoscriptsyntax as rs
144 | point = rs.GetPoint("Base point")
145 | if point:
146 | reference = rs.GetPoint("Reference point", point)
147 | if reference:
148 | angle = rs.GetAngle(point, reference)
149 | if angle!=None: print("Angle:{}".format(angle))
150 | See Also:
151 | GetDistance
152 | """
153 | point = rhutil.coerce3dpoint(point)
154 | if not point: point = Rhino.Geometry.Point3d.Unset
155 | reference_point = rhutil.coerce3dpoint(reference_point)
156 | if not reference_point: reference_point = Rhino.Geometry.Point3d.Unset
157 | default_angle = math.radians(default_angle_degrees)
158 | rc, angle = Rhino.Input.RhinoGet.GetAngle(message, point, reference_point, default_angle)
159 | if rc==Rhino.Commands.Result.Success: return math.degrees(angle)
160 |
161 |
162 | def GetBoolean(message, items, defaults):
163 | """Pauses for user input of one or more boolean values. Boolean values are
164 | displayed as click-able command line option toggles
165 | Parameters:
166 | message (str): a prompt
167 | items ([str, str, str], ...): list or tuple of options. Each option is a tuple of three strings
168 | [n][1] description of the boolean value. Must only consist of letters
169 | and numbers. (no characters like space, period, or dash
170 | [n][2] string identifying the false value
171 | [n][3] string identifying the true value
172 | defaults ([bool, ...]): list of boolean values used as default or starting values
173 | Returns:
174 | list(bool, ...): a list of values that represent the boolean values if successful
175 | None: on error
176 | Example:
177 | import rhinoscriptsyntax as rs
178 | items = ("Lights", "Off", "On"), ("Cameras", "Disabled", "Enabled"), ("Action", "False", "True")
179 | results = rs.GetBoolean("Boolean options", items, (True, True, True) )
180 | if results:
181 | for val in results: print(val)
182 | See Also:
183 | GetString
184 | """
185 | go = Rhino.Input.Custom.GetOption()
186 | go.AcceptNothing(True)
187 | go.SetCommandPrompt( message )
188 | if type(defaults) is list or type(defaults) is tuple: pass
189 | else: defaults = [defaults]
190 | # special case for single list. Wrap items into a list
191 | if len(items)==3 and len(defaults)==1: items = [items]
192 | count = len(items)
193 | if count<1 or count!=len(defaults): return scriptcontext.errorhandler()
194 | toggles = []
195 | for i in compat.RANGE(count):
196 | initial = defaults[i]
197 | item = items[i]
198 | offVal = item[1]
199 | t = Rhino.Input.Custom.OptionToggle( initial, item[1], item[2] )
200 | toggles.append(t)
201 | go.AddOptionToggle(item[0], t)
202 | while True:
203 | getrc = go.Get()
204 | if getrc==Rhino.Input.GetResult.Option: continue
205 | if getrc!=Rhino.Input.GetResult.Nothing: return None
206 | break
207 | return [t.CurrentValue for t in toggles]
208 |
209 |
210 | def GetBox(mode=0, base_point=None, prompt1=None, prompt2=None, prompt3=None):
211 | """Pauses for user input of a box
212 | Parameters:
213 | mode (number): The box selection mode.
214 | 0 = All modes
215 | 1 = Corner. The base rectangle is created by picking two corner points
216 | 2 = 3-Point. The base rectangle is created by picking three points
217 | 3 = Vertical. The base vertical rectangle is created by picking three points.
218 | 4 = Center. The base rectangle is created by picking a center point and a corner point
219 | base_point (point, optional): optional 3D base point
220 | prompt1, prompt2, prompt3 (str, optional): optional prompts to set
221 | Returns:
222 | list(point, ...): list of eight Point3d that define the corners of the box on success
223 | None: is not successful, or on error
224 | Example:
225 | import rhinoscriptsyntax as rs
226 | box = rs.GetBox()
227 | if box:
228 | for i, pt in enumerate(box): rs.AddTextDot( i, pt )
229 | See Also:
230 | GetRectangle
231 | """
232 | base_point = rhutil.coerce3dpoint(base_point)
233 | if base_point is None: base_point = Rhino.Geometry.Point3d.Unset
234 | def intToEnum(m):
235 | if m not in compat.RANGE(1,5):
236 | m = 0
237 | return {
238 | 0 : Rhino.Input.GetBoxMode.All,
239 | 1 : Rhino.Input.GetBoxMode.Corner,
240 | 2 : Rhino.Input.GetBoxMode.ThreePoint,
241 | 3 : Rhino.Input.GetBoxMode.Vertical,
242 | 4 : Rhino.Input.GetBoxMode.Center
243 | }[m]
244 | rc, box = Rhino.Input.RhinoGet.GetBox(intToEnum(mode), base_point, prompt1, prompt2, prompt3)
245 | if rc==Rhino.Commands.Result.Success: return tuple(box.GetCorners())
246 |
247 |
248 | def GetColor(color=[0,0,0]):
249 | """Display the Rhino color picker dialog allowing the user to select an RGB color
250 | Parameters:
251 | color (color, optional): default RGB value. If omitted, the default color is black
252 | Returns:
253 | color: RGB tuple of three numbers on success
254 | None: on error
255 | Example:
256 | import rhinoscriptsyntax as rs
257 | color = rs.LayerColor("Default")
258 | rgb = rs.GetColor(color)
259 | if rgb: rs.LayerColor("Default", rgb)
260 | See Also:
261 |
262 | """
263 | color = rhutil.coercecolor(color)
264 | if color is None: color = System.Drawing.Color.Black
265 | rc, color = Rhino.UI.Dialogs.ShowColorDialog(color)
266 | if rc: return color.R, color.G, color.B
267 | return scriptcontext.errorhandler()
268 |
269 |
270 | def GetCursorPos():
271 | """Retrieves the cursor's position
272 | Returns:
273 | tuple(point, point, guid, point) containing the following information
274 | [0] cursor position in world coordinates
275 | [1] cursor position in screen coordinates
276 | [2] id of the active viewport
277 | [3] cursor position in client coordinates
278 | Example:
279 | import rhinoscriptsyntax as rs
280 | world, screen, view, client = rs.GetCursorPos()
281 | See Also:
282 | XformScreenToWorld
283 | XformWorldToScreen
284 | """
285 | view = scriptcontext.doc.Views.ActiveView
286 | screen_pt = Rhino.UI.MouseCursor.Location
287 | client_pt = view.ScreenToClient(screen_pt)
288 | viewport = view.ActiveViewport
289 | xf = viewport.GetTransform(Rhino.DocObjects.CoordinateSystem.Screen, Rhino.DocObjects.CoordinateSystem.World)
290 | world_pt = Rhino.Geometry.Point3d(client_pt.X, client_pt.Y, 0)
291 | world_pt.Transform(xf)
292 | return world_pt, screen_pt, viewport.Id, client_pt
293 |
294 |
295 | def GetDistance(first_pt=None, distance=None, first_pt_msg='First distance point', second_pt_msg='Second distance point'):
296 | """Pauses for user input of a distance.
297 | Parameters:
298 | first_pt (point, optional): First distance point
299 | distance (number, optional): Default distance
300 | first_pt_msg (str, optional): Prompt for the first distance point
301 | second_pt_msg (str, optional): Prompt for the second distance point
302 | Returns:
303 | number: The distance between the two points if successful.
304 | None: if not successful, or on error.
305 | Example:
306 | import rhinoscriptsyntax as rs
307 | dist = rs.GetDistance()
308 | if dist:
309 | print( dist)
310 | See Also:
311 | GetAngle
312 | """
313 | if distance is not None and first_pt is None:
314 | raise Exception("The 'first_pt' parameter needs a value if 'distance' is not None.")
315 | if distance is not None and not (isinstance(distance, int) or isinstance(distance, float)): return None
316 | if first_pt_msg is None or not isinstance(first_pt_msg, str): return None
317 | if second_pt_msg is None or not isinstance(second_pt_msg, str): return None
318 |
319 | if first_pt is not None:
320 | if first_pt == 0: first_pt = (0,0,0)
321 | first_pt = rhutil.coerce3dpoint(first_pt)
322 | if first_pt is None: return None
323 |
324 | if first_pt is None:
325 | first_pt = GetPoint(first_pt_msg)
326 | if first_pt is None: return None
327 |
328 | # cannot use GetPoint for 2nd point because of the need do differentiate
329 | # between the user accepting none vs cancelling to exactly mimic RhinoScript
330 | gp = Rhino.Input.Custom.GetPoint()
331 | if distance is not None:
332 | gp.AcceptNothing(True)
333 | second_pt_msg = "{0}<{1}>".format(second_pt_msg, distance)
334 | gp.SetCommandPrompt(second_pt_msg)
335 | gp.DrawLineFromPoint(first_pt,True)
336 | gp.EnableDrawLineFromPoint(True)
337 | r = gp.Get()
338 | if r not in [Rhino.Input.GetResult.Cancel, Rhino.Input.GetResult.Point,
339 | Rhino.Input.GetResult.Nothing]: return scriptcontext.errorHandler()
340 | if r == Rhino.Input.GetResult.Cancel: return None
341 | if r == Rhino.Input.GetResult.Point:
342 | second_pt = gp.Point()
343 | distance = second_pt.DistanceTo(first_pt)
344 | gp.Dispose()
345 |
346 | return distance
347 |
348 |
349 | def GetEdgeCurves(message=None, min_count=1, max_count=0, select=False):
350 | """Prompt the user to pick one or more surface or polysurface edge curves
351 | Parameters:
352 | message (str, optional): A prompt or message.
353 | min_count (number, optional): minimum number of edges to select.
354 | max_count (number, optional): maximum number of edges to select.
355 | select (bool, optional): Select the duplicated edge curves.
356 | Returns:
357 | list(tuple[guid, point, point], ...): of selection prompts (curve id, parent id, selection point)
358 | None: if not successful
359 | Example:
360 | import rhinoscriptsyntax as rs
361 | edges = rs.GetEdgeCurves()
362 | if edges:
363 | for edgeinfo in edges:
364 | print("Curve Id ={}".format(edgeinfo[0]))
365 | print("Parent Id ={}".format(edgeinfo[1]))
366 | print("Pick point ={}".format(edgeinfo[2]))
367 | See Also:
368 | DuplicateEdgeCurves
369 | """
370 | if min_count<0 or (max_count>0 and min_count>max_count): return
371 | if not message: message = "Select Edges"
372 | go = Rhino.Input.Custom.GetObject()
373 | go.SetCommandPrompt(message)
374 | go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve
375 | go.GeometryAttributeFilter = Rhino.Input.Custom.GeometryAttributeFilter.EdgeCurve
376 | go.EnablePreSelect(False, True)
377 | rc = go.GetMultiple(min_count, max_count)
378 | if rc!=Rhino.Input.GetResult.Object: return
379 | rc = []
380 | for i in compat.RANGE(go.ObjectCount):
381 | edge = go.Object(i).Edge()
382 | if not edge: continue
383 | edge = edge.Duplicate()
384 | curve_id = scriptcontext.doc.Objects.AddCurve(edge)
385 | parent_id = go.Object(i).ObjectId
386 | pt = go.Object(i).SelectionPoint()
387 | rc.append( (curve_id, parent_id, pt) )
388 | if select:
389 | for item in rc:
390 | rhobj = scriptcontext.doc.Objects.Find(item[0])
391 | rhobj.Select(True)
392 | scriptcontext.doc.Views.Redraw()
393 | return rc
394 |
395 |
396 | def GetInteger(message=None, number=None, minimum=None, maximum=None):
397 | """Pauses for user input of a whole number.
398 | Parameters:
399 | message (str, optional): A prompt or message.
400 | number (number, optional): A default whole number value.
401 | minimum (number, optional): A minimum allowable value.
402 | maximum (number, optional): A maximum allowable value.
403 | Returns:
404 | number: The whole number input by the user if successful.
405 | None: if not successful, or on error
406 | Example:
407 | import rhinoscriptsyntax as rs
408 | color = rs.LayerColor("Default")
409 | color = rs.GetInteger("Enter an RGB color value", color.ToArgb(), 0)
410 | if color: rs.LayerColor("Default", color)
411 | See Also:
412 |
413 | """
414 | gi = Rhino.Input.Custom.GetInteger()
415 | if message: gi.SetCommandPrompt(message)
416 | if number is not None: gi.SetDefaultInteger(number)
417 | if minimum is not None: gi.SetLowerLimit(minimum, False)
418 | if maximum is not None: gi.SetUpperLimit(maximum, False)
419 | if gi.Get()!=Rhino.Input.GetResult.Number: return scriptcontext.errorhandler()
420 | rc = gi.Number()
421 | gi.Dispose()
422 | return rc
423 |
424 |
425 | def GetLayer(title="Select Layer", layer=None, show_new_button=False, show_set_current=False):
426 | """Displays dialog box prompting the user to select a layer
427 | Parameters:
428 | title (str, optional): dialog box title
429 | layer (str, optional): name of a layer to preselect. If omitted, the current layer will be preselected
430 | show_new_button, show_set_current (bool, optional): Optional buttons to show on the dialog
431 | Returns:
432 | str: name of selected layer if successful
433 | None: on error
434 | Example:
435 | import rhinoscriptsyntax as rs
436 | obj = rs.GetObject("Select object")
437 | if obj:
438 | layer = rs.GetLayer("Select Layer", rs.ObjectLayer(obj), True, True)
439 | if layer: rs.ObjectLayer( obj, layer )
440 | See Also:
441 |
442 | """
443 | layer_index = scriptcontext.doc.Layers.CurrentLayerIndex
444 | if layer:
445 | if "::" in layer:
446 | idx = scriptcontext.doc.Layers.FindByFullPath(layer,-1)
447 | if idx != -1:
448 | layer_index = idx
449 | else:
450 | # layer name could have embedded '::'
451 | layer_instance = scriptcontext.doc.Layers.FindName(layer)
452 | if layer_instance is not None: layer_index = layer_instance.Index
453 | else:
454 | layer_instance = scriptcontext.doc.Layers.FindName(layer)
455 | if layer_instance is not None: layer_index = layer_instance.Index
456 | rc = Rhino.UI.Dialogs.ShowSelectLayerDialog(layer_index, title, show_new_button, show_set_current, True)
457 | if rc[0]!=True: return None
458 | layer = scriptcontext.doc.Layers[rc[1]]
459 | return layer.FullPath
460 |
461 |
462 | def GetLayers(title="Select Layers", show_new_button=False):
463 | """Displays a dialog box prompting the user to select one or more layers
464 | Parameters:
465 | title (str, optional): dialog box title
466 | show_new_button (bool, optional): Optional button to show on the dialog
467 | Returns:
468 | str: The names of selected layers if successful
469 | Example:
470 | import rhinoscriptsyntax as rs
471 | layers = rs.GetLayers("Select Layers")
472 | if layers:
473 | for layer in layers: print(layer)
474 | See Also:
475 | GetLayer
476 | """
477 | rc, layer_indices = Rhino.UI.Dialogs.ShowSelectMultipleLayersDialog(None, title, show_new_button)
478 | if rc:
479 | return [scriptcontext.doc.Layers[index].FullPath for index in layer_indices]
480 |
481 |
482 | def GetLine(mode=0, point=None, message1=None, message2=None, message3=None):
483 | """Prompts the user to pick points that define a line
484 | Parameters:
485 | mode (number, optional): line definition mode.
486 | 0 Default - Show all modes, start in two-point mode
487 | 1 Two-point - Defines a line from two points.
488 | 2 Normal - Defines a line normal to a location on a surface.
489 | 3 Angled - Defines a line at a specified angle from a reference line.
490 | 4 Vertical - Defines a line vertical to the construction plane.
491 | 5 Four-point - Defines a line using two points to establish direction and two points to establish length.
492 | 6 Bisector - Defines a line that bisects a specified angle.
493 | 7 Perpendicular - Defines a line perpendicular to or from a curve
494 | 8 Tangent - Defines a line tangent from a curve.
495 | 9 Extension - Defines a line that extends from a curve.
496 | point (point, optional): optional starting point
497 | message1, message2, message3 (str, optional): optional prompts
498 | Returns:
499 | line: Tuple of two points on success
500 | None: on error
501 | Example:
502 | import rhinoscriptsyntax as rs
503 | line = rs.GetLine()
504 | if line: rs.AddLine( line[0], line[1] )
505 | See Also:
506 | GetBox
507 | GetPoint
508 | GetPolyline
509 | GetRectangle
510 | """
511 | gl = Rhino.Input.Custom.GetLine()
512 | if mode==0: gl.EnableAllVariations(True)
513 | else: gl.GetLineMode = System.Enum.ToObject( Rhino.Input.Custom.GetLineMode, mode-1 )
514 | if point:
515 | point = rhutil.coerce3dpoint(point)
516 | gl.SetFirstPoint(point)
517 | if message1: gl.FirstPointPrompt = message1
518 | if message2: gl.MidPointPrompt = message2
519 | if message3: gl.SecondPointPrompt = message3
520 | rc, line = gl.Get()
521 | if rc==Rhino.Commands.Result.Success: return line.From, line.To
522 |
523 |
524 | def GetLinetype(default_linetype=None, show_by_layer=False):
525 | """Displays a dialog box prompting the user to select one linetype
526 | Parameters:
527 | default_linetype (str, optional): Optional. The name of the linetype to select. If omitted, the current linetype will be selected.
528 | show_by_layer (bool, optional): If True, the "by Layer" linetype will show. Defaults to False.
529 | Returns:
530 | str: The names of selected linetype if successful
531 | Example:
532 | import rhinoscriptsyntax as rs
533 | linetype = rs.GetLinetype()
534 | if linetype: print(linetype)
535 | See Also:
536 | GetLayer
537 | """
538 | lt_instance = scriptcontext.doc.Linetypes.CurrentLinetype
539 | if default_linetype:
540 | lt_new = scriptcontext.doc.Linetypes.FindName(default_linetype)
541 | if lt_new is not None: lt_instance = lt_new
542 | id = Rhino.UI.Dialogs.ShowLineTypes("Select Linetype", "", scriptcontext.doc)
543 | if id == System.Guid.Empty: return None
544 | linetype = scriptcontext.doc.Linetypes.FindId(id)
545 | return linetype.Name
546 |
547 | def GetMeshFaces(object_id, message="", min_count=1, max_count=0):
548 | """Prompts the user to pick one or more mesh faces
549 | Parameters:
550 | object_id (guid): the mesh object's identifier
551 | message (str, optional): a prompt of message
552 | min_count (number, optional): the minimum number of faces to select
553 | max_count (number, optional): the maximum number of faces to select.
554 | If 0, the user must press enter to finish selection.
555 | If -1, selection stops as soon as there are at least min_count faces selected.
556 | Returns:
557 | list(number, ...): of mesh face indices on success
558 | None: on error
559 | Example:
560 | import rhinoscriptsyntax as rs
561 | mesh = rs.GetObject("Select mesh", rs.filter.mesh)
562 | if mesh:
563 | indices = rs.GetMeshFaces(mesh)
564 | if indices:
565 | for index in indices: print(index)
566 | See Also:
567 | GetMeshVertices
568 | MeshFaces
569 | MeshFaceVertices
570 | MeshVertices
571 | """
572 | scriptcontext.doc.Objects.UnselectAll()
573 | scriptcontext.doc.Views.Redraw()
574 | object_id = rhutil.coerceguid(object_id, True)
575 | def FilterById( rhino_object, geometry, component_index ):
576 | return object_id == rhino_object.Id
577 | go = Rhino.Input.Custom.GetObject()
578 | go.SetCustomGeometryFilter(FilterById)
579 | if message: go.SetCommandPrompt(message)
580 | go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshFace
581 | go.AcceptNothing(True)
582 | if go.GetMultiple(min_count,max_count)!=Rhino.Input.GetResult.Object: return None
583 | objrefs = go.Objects()
584 | rc = [item.GeometryComponentIndex.Index for item in objrefs]
585 | go.Dispose()
586 | return rc
587 |
588 |
589 | def GetMeshVertices(object_id, message="", min_count=1, max_count=0):
590 | """Prompts the user to pick one or more mesh vertices
591 | Parameters:
592 | object_id (guid): the mesh object's identifier
593 | message (str, optional): a prompt of message
594 | min_count (number, optional): the minimum number of vertices to select
595 | max_count (number, optional): the maximum number of vertices to select. If 0, the user must
596 | press enter to finish selection. If -1, selection stops as soon as there
597 | are at least min_count vertices selected.
598 | Returns:
599 | list(number, ...): of mesh vertex indices on success
600 | None: on error
601 | Example:
602 | import rhinoscriptsyntax as rs
603 | mesh = rs.GetObject("Select mesh", rs.filter.mesh)
604 | if mesh:
605 | indices = rs.GetMeshVertices(mesh)
606 | if indices:
607 | for index in indices: print(index)
608 | See Also:
609 | GetMeshFaces
610 | MeshFaces
611 | MeshFaceVertices
612 | MeshVertices
613 | """
614 | scriptcontext.doc.Objects.UnselectAll()
615 | scriptcontext.doc.Views.Redraw()
616 | object_id = rhutil.coerceguid(object_id, True)
617 | class CustomGetObject(Rhino.Input.Custom.GetObject):
618 | def CustomGeometryFilter( self, rhino_object, geometry, component_index ):
619 | return object_id == rhino_object.Id
620 | go = CustomGetObject()
621 | if message: go.SetCommandPrompt(message)
622 | go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshVertex
623 | go.AcceptNothing(True)
624 | if go.GetMultiple(min_count,max_count)!=Rhino.Input.GetResult.Object: return None
625 | objrefs = go.Objects()
626 | rc = [item.GeometryComponentIndex.Index for item in objrefs]
627 | go.Dispose()
628 | return rc
629 |
630 |
631 | def GetPoint(message=None, base_point=None, distance=None, in_plane=False):
632 | """Pauses for user input of a point.
633 | Parameters:
634 | message (str, optional): A prompt or message.
635 | base_point (point, optional): list of 3 numbers or Point3d identifying a starting, or base point
636 | distance (number, optional): constraining distance. If distance is specified, basePoint must also be specified.
637 | in_plane (bool, optional): constrains the point selections to the active construction plane.
638 | Returns:
639 | point: point on success
640 | None: if no point picked or user canceled
641 | Example:
642 | import rhinoscriptsyntax as rs
643 | point1 = rs.GetPoint("Pick first point")
644 | if point1:
645 | rs.AddPoint(point1)
646 | point2 = rs.GetPoint("Pick second point", point1)
647 | if point2:
648 | rs.AddPoint(point2)
649 | distance = (point1-point2).Length
650 | point3 = rs.GetPoint("Pick third point", point2, distance)
651 | if point3: rs.AddPoint(point3)
652 | See Also:
653 | GetPointOnCurve
654 | GetPointOnSurface
655 | GetPoints
656 | GetRectangle
657 | """
658 | gp = Rhino.Input.Custom.GetPoint()
659 | if message: gp.SetCommandPrompt(message)
660 | base_point = rhutil.coerce3dpoint(base_point)
661 | if base_point:
662 | gp.DrawLineFromPoint(base_point,True)
663 | gp.EnableDrawLineFromPoint(True)
664 | if distance: gp.ConstrainDistanceFromBasePoint(distance)
665 | if in_plane: gp.ConstrainToConstructionPlane(True)
666 | gp.Get()
667 | if gp.CommandResult()!=Rhino.Commands.Result.Success:
668 | return scriptcontext.errorhandler()
669 | pt = gp.Point()
670 | gp.Dispose()
671 | return pt
672 |
673 |
674 | def GetPointOnCurve(curve_id, message=None):
675 | """Pauses for user input of a point constrainted to a curve object
676 | Parameters:
677 | curve_id (guid): identifier of the curve to get a point on
678 | message (str, optional): a prompt of message
679 | Returns:
680 | point: 3d point if successful
681 | None: on error
682 | Example:
683 | import rhinoscriptsyntax as rs
684 | obj = rs.GetObject("Pick a curve")
685 | if rs.IsCurve(obj):
686 | point = rs.GetPointOnCurve(obj, "Point on curve")
687 | if point: rs.AddPoint(point)
688 | See Also:
689 | GetPoint
690 | GetPointOnMesh
691 | GetPointOnSurface
692 | GetPoints
693 | """
694 | curve = rhutil.coercecurve(curve_id, -1, True)
695 | gp = Rhino.Input.Custom.GetPoint()
696 | if message: gp.SetCommandPrompt(message)
697 | gp.Constrain(curve, False)
698 | gp.Get()
699 | if gp.CommandResult()!=Rhino.Commands.Result.Success:
700 | return scriptcontext.errorhandler()
701 | pt = gp.Point()
702 | gp.Dispose()
703 | return pt
704 |
705 |
706 | def GetPointOnMesh(mesh_id, message=None):
707 | """Pauses for user input of a point constrained to a mesh object
708 | Parameters:
709 | mesh_id (guid): identifier of the mesh to get a point on
710 | message (str, optional): a prompt or message
711 | Returns:
712 | point: 3d point if successful
713 | None: on error
714 | Example:
715 | import rhinoscriptsyntax as rs
716 | mesh = rs.GetObject("Pick a mesh", rs.filter.mesh)
717 | if mesh:
718 | point = rs.GetPointOnMesh(mesh, "Point on mesh")
719 | if point: rs.AddPoint( point )
720 | See Also:
721 | GetPoint
722 | GetPointOnCurve
723 | GetPointOnSurface
724 | GetPoints
725 | """
726 | mesh_id = rhutil.coerceguid(mesh_id, True)
727 | if not message: message = "Point"
728 | cmdrc, point = Rhino.Input.RhinoGet.GetPointOnMesh(mesh_id, message, False)
729 | if cmdrc==Rhino.Commands.Result.Success: return point
730 |
731 |
732 | def GetPointOnSurface(surface_id, message=None):
733 | """Pauses for user input of a point constrained to a surface or polysurface
734 | object
735 | Parameters:
736 | surface_id (guid): identifier of the surface to get a point on
737 | message (str, optional): a prompt or message
738 | Returns:
739 | point: 3d point if successful
740 | None: on error
741 | Example:
742 | import rhinoscriptsyntax as rs
743 | surface = rs.GetObject("Pick a surface")
744 | if surface:
745 | point = rs.GetPointOnSurface(surface, "Point on surface")
746 | if point: rs.AddPoint(point)
747 | See Also:
748 | GetPoint
749 | GetPointOnCurve
750 | GetPointOnMesh
751 | GetPoints
752 | """
753 | surfOrBrep = rhutil.coercesurface(surface_id)
754 | if not surfOrBrep:
755 | surfOrBrep = rhutil.coercebrep(surface_id, True)
756 | gp = Rhino.Input.Custom.GetPoint()
757 | if message: gp.SetCommandPrompt(message)
758 | if isinstance(surfOrBrep,Rhino.Geometry.Surface):
759 | gp.Constrain(surfOrBrep,False)
760 | else:
761 | gp.Constrain(surfOrBrep, -1, -1, False)
762 | gp.Get()
763 | if gp.CommandResult()!=Rhino.Commands.Result.Success:
764 | return scriptcontext.errorhandler()
765 | pt = gp.Point()
766 | gp.Dispose()
767 | return pt
768 |
769 |
770 | def GetPoints(draw_lines=False, in_plane=False, message1=None, message2=None, max_points=None, base_point=None):
771 | """Pauses for user input of one or more points
772 | Parameters:
773 | draw_lines (bool, optional): Draw lines between points
774 | in_plane (bool, optional): Constrain point selection to the active construction plane
775 | message1 (str, optional): A prompt or message for the first point
776 | message2 (str, optional): A prompt or message for the next points
777 | max_points (number, optional): maximum number of points to pick. If not specified, an
778 | unlimited number of points can be picked.
779 | base_point (point, optional): a starting or base point
780 | Returns:
781 | list(point, ...): of 3d points if successful
782 | None: if not successful or on error
783 | Example:
784 | import rhinoscriptsyntax as rs
785 | points = rs.GetPoints(True)
786 | if points: rs.AddPointCloud(points)
787 | See Also:
788 | GetPoint
789 | GetPointOnCurve
790 | GetPointOnSurface
791 | GetRectangle
792 | """
793 | gp = Rhino.Input.Custom.GetPoint()
794 | if message1: gp.SetCommandPrompt(message1)
795 | gp.EnableDrawLineFromPoint( draw_lines )
796 | if in_plane:
797 | gp.ConstrainToConstructionPlane(True)
798 | plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
799 | gp.Constrain(plane, False)
800 | getres = gp.Get()
801 | if gp.CommandResult()!=Rhino.Commands.Result.Success: return None
802 | prevPoint = gp.Point()
803 | rc = [prevPoint]
804 | if max_points is None or max_points>1:
805 | current_point = 1
806 | if message2: gp.SetCommandPrompt(message2)
807 | def GetPointDynamicDrawFunc( sender, args ):
808 | if len(rc)>1:
809 | c = Rhino.ApplicationSettings.AppearanceSettings.FeedbackColor
810 | args.Display.DrawPolyline(rc, c)
811 | if draw_lines: gp.DynamicDraw += GetPointDynamicDrawFunc
812 | while True:
813 | if max_points and current_point>=max_points: break
814 | if draw_lines: gp.DrawLineFromPoint(prevPoint, True)
815 | gp.SetBasePoint(prevPoint, True)
816 | current_point += 1
817 | getres = gp.Get()
818 | if getres==Rhino.Input.GetResult.Cancel: break
819 | if gp.CommandResult()!=Rhino.Commands.Result.Success: return None
820 | prevPoint = gp.Point()
821 | rc.append(prevPoint)
822 | return rc
823 |
824 | def GetPolyline(flags=3, message1=None, message2=None, message3=None, message4=None, min=2, max=0):
825 | """Prompts the user to pick points that define a polyline.
826 | Parameters:
827 | flags (number, optional) The options are bit coded flags. Values can be added together to specify more than one option. The default is 3.
828 | value description
829 | 1 Permit close option. If specified, then after 3 points have been picked, the user can type "Close" and a closed polyline will be returned.
830 | 2 Permit close snap. If specified, then after 3 points have been picked, the user can pick near the start point and a closed polyline will be returned.
831 | 4 Force close. If specified, then the returned polyline is always closed. If specified, then intMax must be 0 or >= 4.
832 | Note: the default is 3, or "Permit close option = True", "Permit close snap = True", and "Force close = False".
833 | message1 (str, optional): A prompt or message for the first point.
834 | message2 (str, optional): A prompt or message for the second point.
835 | message3 (str, optional): A prompt or message for the third point.
836 | message4 (str, optional): A prompt or message for the 'next' point.
837 | min (number, optional): The minimum number of points to require. The default is 2.
838 | max (number, optional): The maximum number of points to require; 0 for no limit. The default is 0.
839 | Returns:
840 | list(point, ...): A list of 3-D points that define the polyline if successful.
841 | None: if not successful or on error
842 | Example:
843 | import rhinoscriptsyntax as rs
844 | from scriptcontext import doc
845 | arr = rs.GetPolyline()
846 | if arr is not None:
847 | doc.AddPolyline(arr)
848 | See Also:
849 | GetBox
850 | GetLine
851 | GetRectangle
852 | """
853 | gpl = Rhino.Input.Custom.GetPolyline()
854 | if message1: gpl.FirstPointPrompt = message1
855 | if message2: gpl.SecondPointPrompt = message2
856 | if message3: gpl.ThirdPointPrompt = message3
857 | if message4: gpl.FourthPointPrompt = message4
858 | if min: gpl.MinPointCount = min
859 | if max: gpl.MaxPointCount = max
860 | rc, polyline = gpl.Get()
861 | scriptcontext.doc.Views.Redraw()
862 | if rc==Rhino.Commands.Result.Success: return polyline
863 | return None
864 |
865 | def GetReal(message="Number", number=None, minimum=None, maximum=None):
866 | """Pauses for user input of a number.
867 | Parameters:
868 | message (str, optional): A prompt or message.
869 | number (number, optional): A default number value.
870 | minimum (number, optional): A minimum allowable value.
871 | maximum (number, optional): A maximum allowable value.
872 | Returns:
873 | number: The number input by the user if successful.
874 | None: if not successful, or on error
875 | Example:
876 | import rhinoscriptsyntax as rs
877 | radius = rs.GetReal("Radius of new circle", 3.14, 1.0)
878 | if radius: rs.AddCircle( (0,0,0), radius )
879 | See Also:
880 | RealBox
881 | """
882 | gn = Rhino.Input.Custom.GetNumber()
883 | if message: gn.SetCommandPrompt(message)
884 | if number is not None: gn.SetDefaultNumber(number)
885 | if minimum is not None: gn.SetLowerLimit(minimum, False)
886 | if maximum is not None: gn.SetUpperLimit(maximum, False)
887 | if gn.Get()!=Rhino.Input.GetResult.Number: return None
888 | rc = gn.Number()
889 | gn.Dispose()
890 | return rc
891 |
892 |
893 | def GetRectangle(mode=0, base_point=None, prompt1=None, prompt2=None, prompt3=None):
894 | """Pauses for user input of a rectangle
895 | Parameters:
896 | mode (number, optional): The rectangle selection mode. The modes are as follows
897 | 0 = All modes
898 | 1 = Corner - a rectangle is created by picking two corner points
899 | 2 = 3Point - a rectangle is created by picking three points
900 | 3 = Vertical - a vertical rectangle is created by picking three points
901 | 4 = Center - a rectangle is created by picking a center point and a corner point
902 | base_point (point, optional): a 3d base point
903 | prompt1, prompt2, prompt3 (str, optional): optional prompts
904 | Returns:
905 | tuple(point, point, point, point): four 3d points that define the corners of the rectangle
906 | None: on error
907 | Example:
908 | import rhinoscriptsyntax as rs
909 | rect = rs.GetRectangle()
910 | if rect:
911 | for i, corner in enumerate(rect):
912 | rs.AddTextDot( i, corner )
913 | See Also:
914 | GetPoint
915 | GetPoints
916 | """
917 | mode = System.Enum.ToObject( Rhino.Input.GetBoxMode, mode )
918 | base_point = rhutil.coerce3dpoint(base_point)
919 | if( base_point==None ): base_point = Rhino.Geometry.Point3d.Unset
920 | prompts = ["", "", ""]
921 | if prompt1: prompts[0] = prompt1
922 | if prompt2: prompts[1] = prompt2
923 | if prompt3: prompts[2] = prompt3
924 | rc, corners = Rhino.Input.RhinoGet.GetRectangle(mode, base_point, prompts)
925 | if rc==Rhino.Commands.Result.Success: return corners
926 | return None
927 |
928 |
929 | def GetString(message=None, defaultString=None, strings=None):
930 | """Pauses for user input of a string value
931 | Parameters:
932 | message (str, optional): a prompt or message
933 | defaultString (str, optional): a default value
934 | strings ([str, ...], optional): list of strings to be displayed as a click-able command options.
935 | Note, strings cannot begin with a numeric character
936 | Returns:
937 | str: The string either input or selected by the user if successful.
938 | If the user presses the Enter key without typing in a string, an empty string "" is returned.
939 | None: if not successful, on error, or if the user pressed cancel.
940 | Example:
941 | import rhinoscriptsyntax as rs
942 | layer = rs.CurrentLayer()
943 | layer = rs.GetString("Layer to set current", layer)
944 | if layer: rs.CurrentLayer(layer)
945 | See Also:
946 | GetBoolean
947 | StringBox
948 | """
949 | gs = Rhino.Input.Custom.GetString()
950 | gs.AcceptNothing(True)
951 | if message: gs.SetCommandPrompt(message)
952 | if defaultString: gs.SetDefaultString(defaultString)
953 | if strings:
954 | for s in strings: gs.AddOption(s)
955 | result = gs.Get()
956 | if result==Rhino.Input.GetResult.Cancel: return None
957 | if( result == Rhino.Input.GetResult.Option ):
958 | return gs.Option().EnglishName
959 | return gs.StringResult()
960 |
961 |
962 | def ListBox(items, message=None, title=None, default=None):
963 | """Display a list of items in a list box dialog.
964 | Parameters:
965 | items ([str, ...]): a list of values to select
966 | message (str, optional): a prompt of message
967 | title (str, optional): a dialog box title
968 | default (str, optional): selected item in the list
969 | Returns:
970 | str: he selected item if successful
971 | None: if not successful or on error
972 | Example:
973 | import rhinoscriptsyntax as rs
974 | layers = rs.LayerNames()
975 | if layers:
976 | result = rs.ListBox(layers, "Layer to set current")
977 | if result: rs.CurrentLayer( result )
978 | See Also:
979 | CheckListBox
980 | ComboListBox
981 | MultiListBox
982 | PropertyListBox
983 | """
984 | return Rhino.UI.Dialogs.ShowListBox(title, message, items, default)
985 |
986 |
987 | def MessageBox(message, buttons=0, title=""):
988 | """Displays a message box. A message box contains a message and
989 | title, plus any combination of predefined icons and push buttons.
990 | Parameters:
991 | message (str): A prompt or message.
992 | buttons (number, optional): buttons and icon to display as a bit coded flag. Can be a combination of the
993 | following flags. If omitted, an OK button and no icon is displayed
994 | 0 Display OK button only.
995 | 1 Display OK and Cancel buttons.
996 | 2 Display Abort, Retry, and Ignore buttons.
997 | 3 Display Yes, No, and Cancel buttons.
998 | 4 Display Yes and No buttons.
999 | 5 Display Retry and Cancel buttons.
1000 | 16 Display Critical Message icon.
1001 | 32 Display Warning Query icon.
1002 | 48 Display Warning Message icon.
1003 | 64 Display Information Message icon.
1004 | 0 First button is the default.
1005 | 256 Second button is the default.
1006 | 512 Third button is the default.
1007 | 768 Fourth button is the default.
1008 | 0 Application modal. The user must respond to the message box
1009 | before continuing work in the current application.
1010 | 4096 System modal. The user must respond to the message box
1011 | before continuing work in any application.
1012 | title(str, optional): the dialog box title
1013 | Returns:
1014 | number: indicating which button was clicked:
1015 | 1 OK button was clicked.
1016 | 2 Cancel button was clicked.
1017 | 3 Abort button was clicked.
1018 | 4 Retry button was clicked.
1019 | 5 Ignore button was clicked.
1020 | 6 Yes button was clicked.
1021 | 7 No button was clicked.
1022 | Example:
1023 | import rhinoscriptsyntax as rs
1024 | rs.MessageBox("Hello Rhino!")
1025 | rs.MessageBox("Hello Rhino!", 4 | 32)
1026 | rs.MessageBox("Hello Rhino!", 2 | 48)
1027 | See Also:
1028 |
1029 | """
1030 | buttontype = buttons & 0x00000007 #111 in binary
1031 | btn = Rhino.UI.ShowMessageButton.OK
1032 | if buttontype==1: btn = Rhino.UI.ShowMessageButton.OKCancel
1033 | elif buttontype==2: btn = Rhino.UI.ShowMessageButton.AbortRetryIgnore
1034 | elif buttontype==3: btn = Rhino.UI.ShowMessageButton.YesNoCancel
1035 | elif buttontype==4: btn = Rhino.UI.ShowMessageButton.YesNo
1036 | elif buttontype==5: btn = Rhino.UI.ShowMessageButton.RetryCancel
1037 |
1038 | icontype = buttons & 0x00000070
1039 | icon = compat.ENUM_NONE(Rhino.UI.ShowMessageIcon)
1040 | if icontype==16: icon = Rhino.UI.ShowMessageIcon.Error
1041 | elif icontype==32: icon = Rhino.UI.ShowMessageIcon.Question
1042 | elif icontype==48: icon = Rhino.UI.ShowMessageIcon.Warning
1043 | elif icontype==64: icon = Rhino.UI.ShowMessageIcon.Information
1044 |
1045 | ### 15 Sep 2014 Alain - default button not supported in new version of RC
1046 | ### that isn't tied to Windows.Forms but it probably will so I'm commenting
1047 | ### the old code instead of deleting it.
1048 | #defbtntype = buttons & 0x00000300
1049 | #defbtn = System.Windows.Forms.MessageDefaultButton.Button1
1050 | #if defbtntype==256:
1051 | # defbtn = System.Windows.Forms.MessageDefaultButton.Button2
1052 | #elif defbtntype==512:
1053 | # defbtn = System.Windows.Forms.MessageDefaultButton.Button3
1054 |
1055 | if not isinstance(message, str): message = str(message)
1056 | dlg_result = Rhino.UI.Dialogs.ShowMessage(message, title, btn, icon)
1057 | if dlg_result==Rhino.UI.ShowMessageResult.OK: return 1
1058 | if dlg_result==Rhino.UI.ShowMessageResult.Cancel: return 2
1059 | if dlg_result==Rhino.UI.ShowMessageResult.Abort: return 3
1060 | if dlg_result==Rhino.UI.ShowMessageResult.Retry: return 4
1061 | if dlg_result==Rhino.UI.ShowMessageResult.Ignore: return 5
1062 | if dlg_result==Rhino.UI.ShowMessageResult.Yes: return 6
1063 | if dlg_result==Rhino.UI.ShowMessageResult.No: return 7
1064 |
1065 |
1066 | def PropertyListBox(items, values, message=None, title=None):
1067 | """Displays list of items and their values in a property-style list box dialog
1068 | Parameters:
1069 | items, values ([str, ...]): list of string items and their corresponding values
1070 | message (str, optional): a prompt or message
1071 | title (str, optional): a dialog box title
1072 | Returns:
1073 | list(str, ..): of new values on success
1074 | None: on error
1075 | Example:
1076 | import rhinoscriptsyntax as rs
1077 | objs = rs.GetObjects("Select Objects")
1078 | if objs:
1079 | names = []
1080 | for obj in objs:
1081 | name = rs.ObjectName(obj)
1082 | if name is None: name=""
1083 | names.append(name)
1084 | results = rs.PropertyListBox(objs, names, "Modify object name(s)")
1085 | if results:
1086 | for i in compat.RANGE(len(objs)):
1087 | rs.ObjectName( objs[i], results[i] )
1088 | See Also:
1089 | CheckListBox
1090 | ComboListBox
1091 | ListBox
1092 | MultiListBox
1093 | """
1094 | values = [str(v) for v in values]
1095 | return Rhino.UI.Dialogs.ShowPropertyListBox(title, message, items, values)
1096 |
1097 |
1098 | def MultiListBox(items, message=None, title=None, defaults=None):
1099 | """Displays a list of items in a multiple-selection list box dialog
1100 | Parameters:
1101 | items ([str, ...]) a zero-based list of string items
1102 | message (str, optional): a prompt or message
1103 | title (str, optional): a dialog box title
1104 | defaults (str|[str,...], optional): either a string representing the pre-selected item in the list
1105 | or a list if multiple items are pre-selected
1106 | Returns:
1107 | list(str, ...): containing the selected items if successful
1108 | None: on error
1109 | Example:
1110 | import rhinoscriptsyntax as rs
1111 | layers = rs.LayerNames()
1112 | if layers:
1113 | layers = rs.MultiListBox(layers, "Layers to lock")
1114 | if layers:
1115 | for layer in layers:
1116 | rs.LayerLocked(layer, True)
1117 | See Also:
1118 | CheckListBox
1119 | ComboListBox
1120 | ListBox
1121 | PropertyListBox
1122 | """
1123 | if isinstance(defaults, str):
1124 | defaults = [defaults]
1125 | return Rhino.UI.Dialogs.ShowMultiListBox(title, message, items, defaults)
1126 |
1127 |
1128 | def OpenFileName(title=None, filter=None, folder=None, filename=None, extension=None):
1129 | """Displays file open dialog box allowing the user to enter a file name.
1130 | Note, this function does not open the file.
1131 | Parameters:
1132 | title (str, optional): A dialog box title.
1133 | filter (str, optional): A filter string. The filter must be in the following form:
1134 | "Description1|Filter1|Description2|Filter2||", where "||" terminates filter string.
1135 | If omitted, the filter (*.*) is used.
1136 | folder (str, optional): A default folder.
1137 | filename (str, optional): a default file name
1138 | extension (str, optional): a default file extension
1139 | Returns:
1140 | str: file name is successful
1141 | None: if not successful, or on error
1142 | Example:
1143 | import rhinoscriptsyntax as rs
1144 | filename = rs.OpenFileName()
1145 | if filename: rs.MessageBox(filename)
1146 | filename = rs.OpenFileName("Open", "Text Files (*.txt)|*.txt||")
1147 | if filename: rs.MessageBox(filename)
1148 | filename = rs.OpenFileName("Open", "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||")
1149 | if filename: rs.MessageBox(filename)
1150 | See Also:
1151 | BrowseForFolder
1152 | OpenFileNames
1153 | SaveFileName
1154 | """
1155 | fd = Rhino.UI.OpenFileDialog()
1156 | if title: fd.Title = title
1157 | if filter: fd.Filter = filter
1158 | if folder: fd.InitialDirectory = folder
1159 | if filename: fd.FileName = filename
1160 | if extension: fd.DefaultExt = extension
1161 | if fd.ShowOpenDialog(): return fd.FileName
1162 |
1163 |
1164 | def OpenFileNames(title=None, filter=None, folder=None, filename=None, extension=None):
1165 | """Displays file open dialog box allowing the user to select one or more file names.
1166 | Note, this function does not open the file.
1167 | Parameters:
1168 | title (str, optional): A dialog box title.
1169 | filter (str, optional): A filter string. The filter must be in the following form:
1170 | "Description1|Filter1|Description2|Filter2||", where "||" terminates filter string.
1171 | If omitted, the filter (*.*) is used.
1172 | folder (str, optional): A default folder.
1173 | filename (str, optional): a default file name
1174 | extension (str, optional): a default file extension
1175 | Returns:
1176 | list(str, ...): of selected file names
1177 | Example:
1178 | import rhinoscriptsyntax as rs
1179 | filenames = rs.OpenFileNames("Open", "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||")
1180 | for filename in filenames: print(filename)
1181 | See Also:
1182 | BrowseForFolder
1183 | OpenFileName
1184 | SaveFileName
1185 | """
1186 | fd = Rhino.UI.OpenFileDialog()
1187 | if title: fd.Title = title
1188 | if filter: fd.Filter = filter
1189 | if folder: fd.InitialDirectory = folder
1190 | if filename: fd.FileName = filename
1191 | if extension: fd.DefaultExt = extension
1192 | fd.MultiSelect = True
1193 | if fd.ShowOpenDialog(): return fd.FileNames
1194 | return []
1195 |
1196 |
1197 | def PopupMenu(items, modes=None, point=None, view=None):
1198 | """Display a context-style popup menu. The popup menu can appear almost
1199 | anywhere, and can be dismissed by clicking the left or right mouse buttons
1200 | Parameters:
1201 | items ([str, ...]): list of strings representing the menu items. An empty string or None
1202 | will create a separator
1203 | modes ([number, ...]): List of numbers identifying the display modes. If omitted, all
1204 | modes are enabled.
1205 | 0 = menu item is enabled
1206 | 1 = menu item is disabled
1207 | 2 = menu item is checked
1208 | 3 = menu item is disabled and checked
1209 | point (point, optional): a 3D point where the menu item will appear. If omitted, the menu
1210 | will appear at the current cursor position
1211 | view (str, optional): if point is specified, the view in which the point is computed.
1212 | If omitted, the active view is used
1213 | Returns:
1214 | number: index of the menu item picked or -1 if no menu item was picked
1215 | Example:
1216 | import rhinoscriptsyntax as rs
1217 | items = "Line", "", "Circle", "Arc"
1218 | modes = 2,0,0,0
1219 | result = rs.PopupMenu(items, modes)
1220 | if result>=0: rs.MessageBox(items[result])
1221 | See Also:
1222 |
1223 | """
1224 | screen_point = System.Windows.Forms.Cursor.Position
1225 | if point:
1226 | point = rhutil.coerce3dpoint(point)
1227 | view = __viewhelper(view)
1228 | viewport = view.ActiveViewport
1229 | point2d = viewport.WorldToClient(point)
1230 | screen_point = viewport.ClientToScreen(point2d)
1231 | return Rhino.UI.Dialogs.ShowContextMenu(items, screen_point, modes);
1232 |
1233 |
1234 | def RealBox(message="", default_number=None, title="", minimum=None, maximum=None):
1235 | """Display a dialog box prompting the user to enter a number
1236 | Parameters:
1237 | message (str, optional): a prompt message.
1238 | default_number (number, optional): a default number.
1239 | title (str, optional): a dialog box title.
1240 | minimum (number, optional): a minimum allowable value.
1241 | maximum (number, optional): a maximum allowable value.
1242 | Returns:
1243 | number: The newly entered number on success
1244 | None: on error
1245 | Example:
1246 | import rhinoscriptsyntax as rs
1247 | radius = rs.RealBox("Enter a radius value", 5.0 )
1248 | if radius:
1249 | point = (0,0,0)
1250 | rs.AddCircle( point, radius )
1251 | See Also:
1252 | GetReal
1253 | """
1254 | if default_number is None: default_number = Rhino.RhinoMath.UnsetValue
1255 | if minimum is None: minimum = Rhino.RhinoMath.UnsetValue
1256 | if maximum is None: maximum = Rhino.RhinoMath.UnsetValue
1257 | rc, number = Rhino.UI.Dialogs.ShowNumberBox(title, message, default_number, minimum, maximum)
1258 | if rc: return number
1259 |
1260 |
1261 | def SaveFileName(title=None, filter=None, folder=None, filename=None, extension=None):
1262 | """Display a save dialog box allowing the user to enter a file name.
1263 | Note, this function does not save the file.
1264 | Parameters:
1265 | title (str, optional): A dialog box title.
1266 | filter(str, optional): A filter string. The filter must be in the following form:
1267 | "Description1|Filter1|Description2|Filter2||", where "||" terminates filter string.
1268 | If omitted, the filter (*.*) is used.
1269 | folder (str, optional): A default folder.
1270 | filename (str, optional): a default file name
1271 | extension (str, optional): a default file extension
1272 | Returns:
1273 | str: the file name is successful
1274 | None: if not successful, or on error
1275 | Example:
1276 | import rhinoscriptsyntax as rs
1277 | filename = rs.SaveFileName()
1278 | if filename: rs.MessageBox(filename)
1279 | filename = rs.SaveFileName ("Save", "Text Files (*.txt)|*.txt||")
1280 | if filename: rs.MessageBox(filename)
1281 | filename = rrshui.SaveFileName ("Save", "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||")
1282 | if filename: rs.MessageBox(filename)
1283 | See Also:
1284 | BrowseForFolder
1285 | OpenFileName
1286 | """
1287 | fd = Rhino.UI.SaveFileDialog()
1288 | if title: fd.Title = title
1289 | if filter: fd.Filter = filter
1290 | if folder: fd.InitialDirectory = folder
1291 | if filename: fd.FileName = filename
1292 | if extension: fd.DefaultExt = extension
1293 | if fd.ShowSaveDialog(): return fd.FileName
1294 |
1295 |
1296 | def StringBox(message=None, default_value=None, title=None):
1297 | """Display a dialog box prompting the user to enter a string value.
1298 | Parameters:
1299 | message (str, optional): a prompt message
1300 | default_value (str, optional): a default string value
1301 | title (str, optional): a dialog box title
1302 | Returns:
1303 | str: the newly entered string value if successful
1304 | None: if not successful
1305 | Example:
1306 | import rhinoscriptsyntax as rs
1307 | layer = rs.StringBox("New layer name" )
1308 | if layer: rs.AddLayer( layer )
1309 | See Also:
1310 | GetString
1311 | """
1312 | rc, text = Rhino.UI.Dialogs.ShowEditBox(title, message, default_value, False)
1313 | if rc: return text
1314 |
1315 |
1316 | def TextOut(message=None, title=None):
1317 | """Display a text dialog box similar to the one used by the _What command.
1318 | Parameters:
1319 | message (str): a message
1320 | title (str, optional): the message title
1321 | Returns:
1322 | None: in any case
1323 | Example:
1324 | import rhinoscriptsyntax as rs
1325 | rs.TextOut("This is a long string..." )
1326 | See Also:
1327 | MessagBox
1328 | """
1329 | Rhino.UI.Dialogs.ShowTextDialog(message, title)
1330 |
```