#
tokens: 45182/50000 4/82 files (page 4/7)
lines: off (toggle) GitHub
raw markdown copy
This is page 4 of 7. Use http://codebase.md/jingcheng-chen/rhinomcp?page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/rhino_mcp_server/static/application.py:
--------------------------------------------------------------------------------

```python
import datetime

import System
import System.Windows.Forms

import Rhino
from Rhino.ApplicationSettings import ModelAidSettings as modelaid
from Rhino.Commands import Command as rhcommand

import scriptcontext

import rhinocompat as compat
from rhinoscript import utility as rhutil


# global tuple as (start,end) of command serial numbers
__command_serial_numbers = None


def AddAlias(alias, macro):
    """Add new command alias to Rhino. Command aliases can be added manually by
    using Rhino's Options command and modifying the contents of the Aliases tab.
    Parameters:
      alias (str): Name of new command alias. Cannot match command names or existing
              aliases.
      macro (str): The macro to run when the alias is executed.
    Returns:
      bool: True or False indicating success or failure.
    Example:
      import rhinoscriptsyntax as  rs
      rs.AddAlias("OriginLine",  "!_Line 0,0,0")
    See Also:
      AliasCount
      AliasMacro
      AliasNames
      DeleteAlias
      IsAlias
    """
    return Rhino.ApplicationSettings.CommandAliasList.Add(alias, macro)


def AddSearchPath(folder, index=-1):
    """Add new path to Rhino's search path list. Search paths can be added by
    using Rhino's Options command and modifying the contents of the files tab.
    Parameters:
      folder (str): A valid folder, or path, to add.
      index (number, optional): Zero-based position in the search path list to insert.
                             If omitted, path will be appended to the end of the
                             search path list.
    Returns:
      number: The index where the item was inserted if success.
           -1 on failure.
    Example:
      import rhinoscriptsyntax as rs
      rs.AddSearchPath("C:\\My Python Scripts")
    See Also:
      DeleteSearchPath
      SearchPathCount
      SearchPathList
    """
    return Rhino.ApplicationSettings.FileSettings.AddSearchPath(folder, index)


def AliasCount():
    """Returns number of command aliases in Rhino.
    Returns:
      number: the number of command aliases in Rhino.
    Example:
      import rhinoscriptsyntax as rs
      print("alias count = {}".format(rs.AliasCount()))
    See Also:
      AddAlias
      AliasMacro
      AliasNames
      DeleteAlias
      IsAlias
    """
    return Rhino.ApplicationSettings.CommandAliasList.Count


def AliasMacro(alias, macro=None):
    """Returns or modifies the macro of a command alias.
    Parameters:
      alias (str): The name of an existing command alias.
      macro (str, optional): The new macro to run when the alias is executed. If omitted, the current alias macro is returned.
    Returns:
      str:  If a new macro is not specified, the existing macro if successful.
      str:  If a new macro is specified, the previous macro if successful.
      null:  None on error
    Example:
      import rhinoscriptsyntax as rs
      aliases = rs.AliasNames()
      for alias in aliases:
          print("{} -> {}".format(alias, rs.AliasMacro(alias)))
    See Also:
      AddAlias
      AliasCount
      AliasNames
      DeleteAlias
      IsAlias
    """
    rc = Rhino.ApplicationSettings.CommandAliasList.GetMacro(alias)
    if macro:
        Rhino.ApplicationSettings.CommandAliasList.SetMacro(alias, macro)
    if rc is None: return scriptcontext.errorhandler()
    return rc


def AliasNames():
    """Returns a list of command alias names.
    Returns:
      str: a list of command alias names.
    Example:
      import rhinoscriptsyntax as rs
      aliases = rs.AliasNames()
      for alias in aliases: print(alias)
    See Also:
      AddAlias
      AliasCount
      AliasMacro
      DeleteAlias
      IsAlias
    """
    return Rhino.ApplicationSettings.CommandAliasList.GetNames()


def AppearanceColor(item, color=None):
    """Returns or modifies an application interface item's color.
    Parameters:
      item (number): Item number to either query or modify
             0  = View background
             1  = Major grid line
             2  = Minor grid line
             3  = X-Axis line
             4  = Y-Axis line
             5  = Selected Objects
             6  = Locked Objects
             7  = New layers
             8  = Feedback
             9  = Tracking
             10 = Crosshair
             11 = Text
             12 = Text Background
             13 = Text hover
      color ([r255,g255,b255], optional): The new color value in (r255,g255,b255). If omitted, the current item color is returned.
    Returns:
      tuple (r255,g255,b255): if color is not specified, the current item color.
      tuple (r255,g255,b255): if color is specified, the previous item color.
    Example:
      import rhinoscriptsyntax as rs
      oldColor = rs.AppearanceColor(0)
      newColor = rs.GetColor(oldColor)
      if newColor is not None:
          rs.AppearanceColor(0, newColor)
          rs.Redraw()
    See Also:
      GetColor
    """
    rc = None
    color = rhutil.coercecolor(color)
    appearance = Rhino.ApplicationSettings.AppearanceSettings
    if item==0:
        rc = appearance.ViewportBackgroundColor
        if color: appearance.ViewportBackgroundColor = color
    elif item==1:
        rc = appearance.GridThickLineColor
        if color: appearance.GridThickLineColor = color
    elif item==2:
        rc = appearance.GridThinLineColor
        if color: appearance.GridThinLineColor = color
    elif item==3:
        rc = appearance.GridXAxisLineColor
        if color: appearance.GridXAxisLineColor = color
    elif item==4:
        rc = appearance.GridYAxisLineColor
        if color: appearance.GridYAxisLineColor = color
    elif item==5:
        rc = appearance.SelectedObjectColor
        if color: appearance.SelectedObjectColor = color
    elif item==6:
        rc = appearance.LockedObjectColor
        if color: appearance.LockedObjectColor = color
    elif item==7:
        rc = appearance.DefaultLayerColor
        if color: appearance.DefaultLayerColor = color
    elif item==8:
        rc = appearance.FeedbackColor
        if color: appearance.FeedbackColor = color
    elif item==9:
        rc = appearance.TrackingColor
        if color: appearance.TrackingColor = color
    elif item==10:
        rc = appearance.CrosshairColor
        if color: appearance.CrosshairColor = color
    elif item==11:
        rc = appearance.CommandPromptTextColor
        if color: appearance.CommandPromptTextColor = color
    elif item==12:
        rc = appearance.CommandPromptBackgroundColor
        if color: appearance.CommandPromptBackgroundColor = color
    elif item==13:
        rc = appearance.CommandPromptHypertextColor
        if color: appearance.CommandPromptHypertextColor = color
    if rc is None: raise ValueError("item is out of range")
    scriptcontext.doc.Views.Redraw()
    return rc


def AutosaveFile(filename=None):
    """Returns or changes the file name used by Rhino's automatic file saving
    Parameters:
      filename (str, optional): Name of the new autosave file
    Returns:
      str: if filename is not specified, the name of the current autosave file
      str: if filename is specified, the name of the previous autosave file
    Example:
      import rhinoscriptsyntax as rs
      file = rs.AutosaveFile()
      print("The current autosave file is {}".format(file))
    See Also:
      AutosaveInterval
      EnableAutosave
    """
    rc = Rhino.ApplicationSettings.FileSettings.AutoSaveFile
    if filename: Rhino.ApplicationSettings.FileSettings.AutoSaveFile = filename
    return rc


def AutosaveInterval(minutes=None):
    """Returns or changes how often the document will be saved when Rhino's
    automatic file saving mechanism is enabled
    Parameters:
      minutes (number, optional): The number of minutes between saves
    Returns:
      number: if minutes is not specified, the current interval in minutes
      number: if minutes is specified, the previous interval in minutes
    Example:
      import rhinoscriptsyntax as rs
      minutes = rs.AutosaveInterval()
      if minutes>20: rs.AutosaveInterval(20)
    See Also:
      AutosaveFile
      EnableAutosave
    """
    rc = Rhino.ApplicationSettings.FileSettings.AutoSaveInterval.TotalMinutes
    if minutes:
        timespan = System.TimeSpan.FromMinutes(minutes)
        Rhino.ApplicationSettings.FileSettings.AutoSaveInterval = timespan
    return rc


def BuildDate():
    """Returns the build date of Rhino
    Returns:
      Datetime.date: the build date of Rhino. Will be converted to a string by most functions.
    Example:
      import rhinoscriptsyntax as rs
      build = rs.BuildDate()
      print("Rhino Build:{}".format(build)
    See Also:

    """
    build = Rhino.RhinoApp.BuildDate
    return datetime.date(build.Year, build.Month, build.Day)


def ClearCommandHistory():
    """Clears contents of Rhino's command history window. You can view the
    command history window by using the CommandHistory command in Rhino.
    Returns:
      none
    Example:
      import rhinoscriptsyntax as rs
      rs.ClearCommandHistory()
    See Also:
      CommandHistory
    """
    Rhino.RhinoApp.ClearCommandHistoryWindow()


def Command(commandString, echo=True):
    """Runs a Rhino command script. All Rhino commands can be used in command
    scripts. The command can be a built-in Rhino command or one provided by a
    3rd party plug-in.
    Parameters:
      commandString (str): A Rhino command including any arguments
      echo (bool, optional): The command echo mode True will display the commands on the commandline. If omitted, command prompts are echoed (True)
    Returns:
      bool: True or False indicating success or failure

    Write command scripts just as you would type the command sequence at the
    command line. A space or a new line acts like pressing <Enter> at the
    command line. For more information, see "Scripting" in Rhino help.

    Note, this function is designed to run one command and one command only.
    Do not combine multiple Rhino commands into a single call to this method.
      WRONG:
        rs.Command("_Line _SelLast _Invert")
      CORRECT:
        rs.Command("_Line")
        rs.Command("_SelLast")
        rs.Command("_Invert")

    Also, the exclamation point and space character ( ! ) combination used by
    button macros and batch-driven scripts to cancel the previous command is
    not valid.
      WRONG:
        rs.Command("! _Line _Pause _Pause")
      CORRECT:
        rs.Command("_Line _Pause _Pause")
    After the command script has run, you can obtain the identifiers of most
    recently created or changed object by calling LastCreatedObjects.
    Example:
      import rhinoscriptsyntax as rs
      rs.Command("_Line 0,0,0 2,2,2")
      rs.Command("_Line _Pause _Pause")
    See Also:
      IsCommand
      LastCommandName
      LastCommandResult
      LastCreatedObjects
      Prompt
    """
    start = Rhino.DocObjects.RhinoObject.NextRuntimeSerialNumber
    rc = Rhino.RhinoApp.RunScript(commandString, echo)
    end = Rhino.DocObjects.RhinoObject.NextRuntimeSerialNumber
    global __command_serial_numbers
    __command_serial_numbers = None
    if start!=end: __command_serial_numbers = (start,end)
    return rc


def CommandHistory():
    """Returns the contents of Rhino's command history window
    Returns:
      str: the contents of Rhino's command history window
    Example:
      import rhinoscriptsyntax as rs
      print(rs.CommandHistory())
    See Also:
      ClearCommandHistory
    """
    return Rhino.RhinoApp.CommandHistoryWindowText


def DefaultRenderer(renderer=None):
    """Returns or changes the default render plug-in
    Parameters:
      renderer (str, optional): The name of the renderer to set as default renderer.  If omitted the Guid of the current renderer is returned.
    Returns:
      guid: Unique identifier of default renderer
    Example:
      import rhinoscriptsyntax as rs
      rs.DefaultRenderer("MyRenderPlugIn")
    See Also:
      PlugIns
    """
    id = Rhino.Render.Utilities.DefaultRenderPlugInId
    plugins = Rhino.PlugIns.PlugIn.GetInstalledPlugIns()
    rc = plugins[id]
    if renderer:
        id = Rhino.PlugIns.PlugIn.IdFromName(renderer)
        Rhino.Render.Utilities.SetDefaultRenderPlugIn(id)
    return rc


def DeleteAlias(alias):
    """Delete an existing alias from Rhino.
    Parameters:
      alias (str): The name of an existing alias.
    Returns:
      bool: True or False indicating success
    Example:
      import rhinoscriptsyntax as rs
      print(rs.DeleteAlias("Hello"))
    See Also:
      AddAlias
      AliasCount
      AliasMacro
      AliasNames
      IsAlias
    """
    return Rhino.ApplicationSettings.CommandAliasList.Delete(alias)


def DeleteSearchPath(folder):
    """Removes existing path from Rhino's search path list. Search path items
    can be removed manually by using Rhino's options command and modifying the
    contents of the files tab
    Parameters:
      folder (str): A folder to remove
    Returns:
      bool: True or False indicating success
    Example:
      import rhinoscriptsyntax as rs
      rs.DeleteSearchPath("C:\\My RhinoScripts")
    See Also:
      AddSearchPath
      SearchPathCount
      SearchPathList
    """
    return Rhino.ApplicationSettings.FileSettings.DeleteSearchPath(folder)


def DisplayOleAlerts(enable):
    """Enables/disables OLE Server Busy/Not Responding dialog boxes
    Parameters:
      enable (bool): Whether alerts should be visible (True or False)
    Returns:
      none
    Example:
      import System
      import rhinoscriptsyntax as rs
      rs.DisplayOleAlerts( False )
      t = System.Type.GetTypeFromProgID("Excel.Application")
      objExcel = System.Activator.CreateObject(t)
      ...
    See Also:

    """
    Rhino.Runtime.HostUtils.DisplayOleAlerts( enable )


def EdgeAnalysisColor(color=None):
    """Returns or modifies edge analysis color displayed by the ShowEdges command
    Parameters:
      color (tuple (r255,g255,b255), optional): The new color for the analysis.
    Returns:
      tuple (r255,g255,b255): if color is not specified, the current edge analysis color
      tuple (r255,g255,b255): if color is specified, the previous edge analysis color
    Example:
      import rhinoscriptsyntax as rs
      oldcolor = rs.EdgeAnalysisColor()
      newcolor = rs.GetColor(oldcolor)
      if newcolor is not None:
          rs.EdgeAnalysisColor(newcolor)
    See Also:
      EdgeAnalysisMode
    """
    rc = Rhino.ApplicationSettings.EdgeAnalysisSettings.ShowEdgeColor
    if color:
        color = rhutil.coercecolor(color, True)
        Rhino.ApplicationSettings.EdgeAnalysisSettings.ShowEdgeColor = color
    return rc


def EdgeAnalysisMode(mode=None):
    """Returns or modifies edge analysis mode displayed by the ShowEdges command
    Parameters:
      mode (number, optional): The new display mode. The available modes are
                   0 - display all edges
                   1 - display naked edges
    Returns:
      number: if mode is not specified, the current edge analysis mode
      number: if mode is specified, the previous edge analysis mode
    Example:
      import rhinoscriptsyntax as rs
      previous_mode = rs.EdgeAnalysisMode(1)
    See Also:
      EdgeAnalysisColor
    """
    rc = Rhino.ApplicationSettings.EdgeAnalysisSettings.ShowEdges
    if mode==1 or mode==2:
        Rhino.ApplicationSettings.EdgeAnalysisSettings.ShowEdges = mode
    return rc


def EnableAutosave(enable=True):
    """Enables or disables Rhino's automatic file saving mechanism
    Parameters:
      enable (bool, optional): The autosave state. If omitted automatic saving is enabled (True)
    Returns:
      bool: the previous autosave state
    Example:
      import rhinoscriptsyntax as rs
      prevstate = rs.EnableAutosave()
    See Also:
      AutosaveFile
      AutosaveInterval
    """
    rc = Rhino.ApplicationSettings.FileSettings.AutoSaveEnabled
    if rc!=enable: Rhino.ApplicationSettings.FileSettings.AutoSaveEnabled = enable
    return rc


def EnablePlugIn(plugin, enable=None):
    """Enables or disables a Rhino plug-in
      Parameters:
        plugin (guid): The unique Guid id of the plugin.
        enable (bool, optional): Load silently if True. If omitted Load silently is False.
      Returns:
        bool: True if set to load silently otherwise False
      Example:
        import rhinoscriptsyntax as rs
        print(rs.EnablePlugIn("RhinoCrasher", False))
    See Also:
        IsPlugIn
        PlugInId
        PlugIns
    """
    id = rhutil.coerceguid(plugin)
    if not id: id = Rhino.PlugIns.PlugIn.IdFromName(plugin)
    rc, loadSilent = Rhino.PlugIns.PlugIn.GetLoadProtection(id)
    if enable is not None:
        Rhino.PlugIns.PlugIn.SetLoadProtection(id, enable)
    return loadSilent


def ExeFolder():
    """Returns the full path to Rhino's executable folder.
    Returns:
      str: the full path to Rhino's executable folder.
    Example:
      import rhinoscriptsyntax as rs
      folder = rs.ExeFolder()
      print(folder)
    See Also:
      InstallFolder
    """
    return Rhino.ApplicationSettings.FileSettings.ExecutableFolder


def ExePlatform():
    """Returns the platform of the Rhino executable
    Returns:
      str: the platform of the Rhino executable
    Example:
      import rhinoscriptsyntax as rs
      if rs.ExePlatform() == 1:
          print("You are using a 64-bit version of Rhino.")
      else:
          print("You are using a 32-bit version of Rhino.")
    See Also:
      BuildDate
      ExeVersion
      SdkVersion
    """
    if System.Environment.Is64BitProcess: return 1
    return 0


def ExeServiceRelease():
    """Returns the service release number of the Rhino executable
    Returns:
      str: the service release number of the Rhino executable
    Example:
      import rhinoscriptsyntax as rs
      print("Build date:{}".format(rs.BuildDate())
      print("SDK Version:{}".format(rs.SdkVersion())
      print("SDK Service Release:{}".format(rs.SdkServiceRelease())
      print("Executable Version:{}".format(rs.ExeVersion())
      print("Executable Service Release:{}".format(rs.ExeServiceRelease())
      print("Serial Number:{}".format(rs.SerialNumber())
      print("Node Type:{}".format(rs.NodeType())
      print("Install Type:{}".format(rs.InstallType())
    See Also:
      BuildDate
      ExeVersion
      SdkVersion
    """
    return Rhino.RhinoApp.ExeServiceRelease


def ExeVersion():
    """Returns the major version number of the Rhino executable
    Returns:
      str: the major version number of the Rhino executable
    Example:
      import rhinoscriptsyntax as rs
      print("Build date:{}".format(rs.BuildDate()))
      print("SDK Version:{}".format(rs.SdkVersion()))
      print("SDK Service Release:{}".format(rs.SdkServiceRelease()))
      print("Executable Version:{}".format(rs.ExeVersion()))
      print("Executable Service Release:{}".format(rs.ExeServiceRelease()))
      print("Serial Number:{}".format(rs.SerialNumber()))
      print("Node Type:{}".format(rs.NodeType()))
      print("Install Type:{}".format(rs.InstallType()))
    See Also:
      BuildDate
      ExeServiceRelease
      SdkVersion
    """
    return Rhino.RhinoApp.ExeVersion


def Exit():
    """Closes the rhino application
    Returns:
      none
    Example:
      import rhinoscriptsyntax as rs
      rs.Exit()
    See Also:

    """
    Rhino.RhinoApp.Exit()


def FindFile(filename):
    """Searches for a file using Rhino's search path. Rhino will look for a
    file in the following locations:
      1. The current document's folder.
      2. Folder's specified in Options dialog, File tab.
      3. Rhino's System folders
    Parameters:
      filename (str): A short file name to search for
    Returns:
      str: full path on success
    Example:
      import rhinoscriptsyntax as rs
      path = rs.FindFile("Rhino.exe")
      print(path)
    See Also:

    """
    return Rhino.ApplicationSettings.FileSettings.FindFile(filename)


def GetPlugInObject(plug_in):
    """Returns a scriptable object from a specified plug-in. Not all plug-ins
    contain scriptable objects. Check with the manufacturer of your plug-in
    to see if they support this capability.
    Parameters:
      plug_in (str or guid): The name or Id of a registered plug-in that supports scripting.
                             If the plug-in is registered but not loaded, it will be loaded
    Returns:
      guid: scriptable object if successful
      null: None on error
    Example:
      import rhinoscriptsyntax as rs
      objPlugIn = rs.GetPlugInObject("SomePlugIn")
      if objPlugIn is not None:
          print(objPlugIn.About())
    See Also:

    """
    return Rhino.RhinoApp.GetPlugInObject(plug_in)


def InCommand(ignore_runners=True):
    """Determines if Rhino is currently running a command. Because Rhino allows
    for transparent commands (commands run from inside of other commands), this
    method returns the total number of active commands.
    Parameters:
      ignore_runners (bool, optional): If True, script running commands, such as
                                       LoadScript, RunScript, and ReadCommandFile will not counted.
                                       If omitted the default is not to count script running command (True).
    Returns:
      number: the number of active commands
    Example:
      import rhinoscriptsyntax as rs
      commands = rs.InCommand()
      if commands > 0:
          print("Rhino is running", commands, "command(s).")
      else:
          print("Rhino is not running any command(s).")
    See Also:
      Command
      IsCommand
    """
    ids = rhcommand.GetCommandStack()
    return len(ids)


def InstallFolder():
    """The full path to Rhino's installation folder
    Returns:
      str: the full path to Rhino's installation folder
    Example:
      import rhinoscriptsyntax as rs
      print(rs.InstallFolder())
    See Also:
      ExeFolder
    """
    return Rhino.ApplicationSettings.FileSettings.InstallFolder


def IsAlias(alias):
    """Verifies that a command alias exists in Rhino
    Parameters:
      alias (str): The name of an existing command alias
    Returns:
      bool: True if exists or False if the alias does not exist.
    Example:
      import rhinoscriptsyntax as rs
      print(rs.IsAlias("Hello"))
    See Also:
      AddAlias
      AliasCount
      AliasMacro
      AliasNames
      DeleteAlias
    """
    return Rhino.ApplicationSettings.CommandAliasList.IsAlias(alias)


def IsCommand(command_name):
    """Verifies that a command exists in Rhino. Useful when scripting commands
    found in 3rd party plug-ins.
    Parameters:
      command_name (str): The command name to test
    Returns:
      bool: True if the string is a command or False if it is not a command.
    Example:
      import rhinoscriptsyntax as rs
      cmdname = rs.GetString("Command name to test")
      if cmdname is not None:
          iscmd = rs.IsCommand(cmdname)
          if iscmd:
              print("The", cmdname, "command exists.")
          else:
              print("The", cmdname, "command does not exist.")
    See Also:
      Command
      InCommand
    """
    return rhcommand.IsCommand(command_name)


def IsPlugIn(plugin):
    """Verifies that a plug-in is registered
    Parameters:
      plugin (guid): The unique id of the plug-in
    Returns:
      bool: True if the Guid is registered or False if it is not.
    Example:
      import rhinoscriptsyntax as rs
      plugin = rs.GetString("Plug-in name")
      if rs.IsPlugIn(plugin): print("The  plug-in is registered.")
      else: print("The  plug-in is not registered.")
    See Also:
      EnablePlugIn
      PlugInId
      PlugIns
    """
    id = rhutil.coerceguid(plugin)
    if not id: id = Rhino.PlugIns.PlugIn.IdFromName(plugin)
    if id:
        rc, loaded, loadprot = Rhino.PlugIns.PlugIn.PlugInExists(id)
        return rc


def IsRunningOnWindows():
    """Returns True if this script is being executed on a Windows platform
    Returns:
      bool: True if currently running on the Widows platform. False if it is not Windows.
    Example:
      import rhinoscriptsyntax as rs
      if rs.IsRunngingOnWindows():
          print("Running on Windows")
      else:
          print("Running on Mac")
    See Also:

    """
    return Rhino.Runtime.HostUtils.RunningOnWindows


def LastCommandName():
    """Returns the name of the last executed command
    Returns:
      str: the name of the last executed command
    Example:
      import rhinoscriptsyntax as rs
      rs.Command( "Line" )
      print("The last command was the {} {}".format(rs.LastCommandName(), "command."))
    See Also:
      Command
      IsCommand
      LastCommandResult
    """
    id = rhcommand.LastCommandId
    return rhcommand.LookupCommandName(id, True)


def LastCommandResult():
    """Returns the result code for the last executed command
    Returns:
      number: the result code for the last executed command.
                0 = success (command successfully completed)
                1 = cancel (command was cancelled by the user)
                2 = nothing (command did nothing, but was not cancelled)
                3 = failure (command failed due to bad input, computational problem...)
                4 = unknown command (the command was not found)
    Example:
      import rhinoscriptsyntax as rs
      rs.Command( "Line" )
      result = rs.LastCommandResult()
      if result==0:
          print("The command completed.")
      else:
          print("The command did not complete.")
    See Also:
      Command
      IsCommand
      LastCommandName
    """
    return int(rhcommand.LastCommandResult)


def LocaleID():
    """Returns the current language used for the Rhino interface.  The current
    language is returned as a locale ID, or LCID, value.
    Returns:
      number: the current language used for the Rhino interface as a locale ID, or LCID.
                1029  Czech
                1031  German-Germany
                1033  English-United States
                1034  Spanish-Spain
                1036  French-France
                1040  Italian-Italy
                1041  Japanese
                1042  Korean
                1045  Polish
    Example:
      import rhinoscriptsyntax as rs
      lcid = rs.LocaleID()
      if lcid==1029:
          print("message in Czech")
      elif lcid==1031:
          print("message in German")
      elif lcid==1033:
          print("message in English")
      elif lcid==1034:
          print("message in Spanish")
      elif lcid==1036:
          print("message in Italian")
      elif lcid==1040:
          print("message in Japanese")
      elif lcid==1042:
          print("message in Korean")
      elif lcid==1045:
          print("message in Polish")
    See Also:

    """
    return Rhino.ApplicationSettings.AppearanceSettings.LanguageIdentifier


def Ortho(enable=None):
    """Enables or disables Rhino's ortho modeling aid.
    Parameters:
      enable (bool, optional): The new enabled status (True or False). If omitted the current state is returned.
    Returns:
      bool: if enable is not specified, then the current ortho status
      bool: if enable is specified, then the previous ortho status
    Example:
      import rhinoscriptsyntax as rs
      if not rs.Ortho(): rs.Ortho(True)
    See Also:
      Osnap
      Planar
      Snap
    """
    rc = modelaid.Ortho
    if enable!=None: modelaid.Ortho = enable
    return rc


def Osnap(enable=None):
    """Enables or disables Rhino's object snap modeling aid.
    Object snaps are tools for specifying points on existing objects.
    Parameters:
      enable (bool, optional): The new enabled status.
    Returns:
      bool: if enable is not specified, then the current osnap status
      bool: if enable is specified, then the previous osnap status
    Example:
      import rhinoscriptsyntax as rs
      if not rs.Osnap(): rs.Osnap(True)
    See Also:
      Ortho
      OsnapMode
      Planar
      Snap
    """
    rc = modelaid.Osnap
    if enable!=None: modelaid.Osnap = enable
    return rc


def OsnapDialog(visible=None):
    """Shows or hides Rhino's dockable object snap bar
    Parameters:
      visible (bool, optional): The new visibility state. If omitted then the current state is returned.
    Returns:
      bool: if visible is not specified, then the current visible state
      bool: if visible is specified, then the previous visible state
    Example:
      import rhinoscriptsyntax as rs
      if not rs.OsnapDialog(): rs.OsnapDialog(True)
    See Also:
      Osnap
      OsnapMode
      ProjectOsnaps
    """
    rc = modelaid.UseHorizontalDialog
    if visible is not None: modelaid.UseHorizontalDialog = visible
    return rc


def OsnapMode(mode=None):
    """Returns or sets the object snap mode. Object snaps are tools for
    specifying points on existing objects
    Parameters:
      mode (number, optional): The object snap mode or modes to set. Object snap modes
                     can be added together to set multiple modes
                     0          None
                     2          Near
                     8          Focus
                     32         Center
                     64         Vertex
                     128        Knot
                     512        Quadrant
                     2048       Midpoint
                     8192       Intersection
                     131072     End
                     524288     Perpendicular
                     2097152    Tangent
                     134217728  Point
    Returns:
      number: if mode is not specified, then the current object snap mode(s)
      number: if mode is specified, then the previous object snap mode(s)
    Example:
      import rhinoscriptsyntax as rs
      rhOsnapModeEnd = 131072
      #add 'End' mode while keeping the ones that are already set
      mode = rs.OsnapMode()
      rs.OsnapMode(mode + rhOsnapModeEnd)
      #add 'End' mode while clearing the others
      rs.OsnapMode(rhOsnapModeEnd)
    See Also:
      Osnap
      OsnapDialog
      ProjectOsnaps
    """
    rc = int(modelaid.OsnapModes)
    # RH-39062 reverts RH-31758
    #m = [(0,0), (1,2), (2,8), (4,0x20), (8,0x80), (16,0x200), (32,0x800), (64,0x2000),
    #      (128,0x20000), (256,0x80000), (512,0x200000), (1024,0x8000000), (2048, 0x40)]
    #rc = sum([x[0] for x in m if x[1] & rc])
    if mode is not None:
        #mode = sum([x[1] for x in m if x[0] & int(mode)])
        modelaid.OsnapModes = System.Enum.ToObject(Rhino.ApplicationSettings.OsnapModes, mode)
    return rc

def Planar(enable=None):
    """Enables or disables Rhino's planar modeling aid
    Parameters:
      enable (bool, optional): The new enable status.  If omitted the current state is returned.
    Returns:
      bool: if enable is not specified, then the current planar status
      bool: if enable is secified, then the previous planar status
    Example:
      import rhinoscriptsyntax as rs
      if not rs.Planar(): rs.Planar(True)
    See Also:
      Ortho
      Osnap
      Snap
    """
    rc = modelaid.Planar
    if enable is not None: modelaid.Planar = enable
    return rc


def PlugInId(plugin):
    """Returns the identifier of a plug-in given the plug-in name
    Parameters:
      plugin (guid): Unique id of the plug-in
    Returns:
      guid: the id of the plug-in
      None: None if the plug-in isn't valid
    Example:
      import rhinoscriptsyntax as rs
      plugins = rs.PlugIns(0, 1)
      if plugins:
          for plugin in plugins: print(rs.PlugInId(plugin))
    See Also:
      EnablePlugIn
      IsPlugIn
      PlugIns
    """
    id = Rhino.PlugIns.PlugIn.IdFromName(plugin)
    if id!=System.Guid.Empty: return id


def PlugIns(types=0, status=0):
    """Returns a list of registered Rhino plug-ins
    Parameters:
      types (number, optional): The type of plug-ins to return.
                                0=all
                                1=render
                                2=file export
                                4=file import
                                8=digitizer
                                16=utility.
                                If omitted, all are returned.
      status (number, optional): 0=both loaded and unloaded, 1=loaded, 2=unloaded.  If omitted both status is returned.
    Returns:
      list of str: list of registered Rhino plug-ins
    Example:
      import rhinoscriptsyntax as rs
      plugins = rs.PlugIns(0, 1)
      for plugin in plugins: print(plugin)
    See Also:

    """
    search_filter = compat.ENUM_NONE(Rhino.PlugIns.PlugInType)
    if types&1: search_filter |= Rhino.PlugIns.PlugInType.Render
    if types&2: search_filter |= Rhino.PlugIns.PlugInType.FileExport
    if types&4: search_filter |= Rhino.PlugIns.PlugInType.FileImport
    if types&8: search_filter |= Rhino.PlugIns.PlugInType.Digitiger
    if types&16: search_filter |= Rhino.PlugIns.PlugInType.Utility
    if types==0: search_filter = Rhino.PlugIns.PlugInType.Any
    loaded = (status==0 or status==1)
    unloaded = (status==0 or status==2)
    names = Rhino.PlugIns.PlugIn.GetInstalledPlugInNames(search_filter, loaded, unloaded)
    return list(names)


def ProjectOsnaps(enable=None):
    """Enables or disables object snap projection
    Parameters:
      enable (bool, optional): The new enabled status.  If omitted the current status is returned.
    Returns:
      bool: the current object snap projection status
    Example:
      import rhinoscriptsyntax as rs
      if not rs.ProjectOsnaps(): rs.ProjectOsnaps(True)
    See Also:
      Osnap
      OsnapDialog
      OsnapMode
    """
    rc = modelaid.ProjectSnapToCPlane
    if enable is not None: modelaid.ProjectSnapToCPlane = enable
    return rc


def Prompt(message=None):
    """Change Rhino's command window prompt
    Parameters:
      message (str, optional): The new prompt on the commandline.  If omitted the prompt will be blank.
    Returns:
      none
    Example:
      import rhinoscriptsyntax as rs
      rs.Prompt("Hello Rhino!")
    See Also:
      Command
    """
    if message and type(message) is not str:
        strList = [str(item) for item in message]
        message = "".join(strList)
    Rhino.RhinoApp.SetCommandPrompt(message)


def ScreenSize():
    """Returns current width and height, of the screen of the primary monitor.
    Returns:
      tuple (width, height): containing two numbers identifying the width and height in pixels
    Example:
      import rhinoscriptsyntax as rs
      size = rs.ScreenSize()
      print("Screen Width: {} pixels".format(size[0]))
      print("Screen Height: {} pixels".format(size[1]))
    See Also:

    """
    sz = System.Windows.Forms.Screen.PrimaryScreen.Bounds
    return sz.Width, sz.Height


def SdkVersion():
    """Returns version of the Rhino SDK supported by the executing Rhino.
    Returns:
      str: the version of the Rhino SDK supported by the executing Rhino. Rhino SDK versions are 9 digit numbers in the form of YYYYMMDDn.
    Example:
      import rhinoscriptsyntax as rs
      print("Required SDK Version: {}".format(rs.SdkVersion()))
    See Also:

    """
    return Rhino.RhinoApp.SdkVersion


def SearchPathCount():
    """Returns the number of path items in Rhino's search path list.
    See "Options Files settings" in the Rhino help file for more details.
    Returns:
      number: the number of path items in Rhino's search path list
    Example:
      import rhinoscriptsyntax as rs
      count = rs.SearchPathCount()
      if count>0:
          paths = rs.SearchPathList()
          for path in paths: print(path)
    See Also:
      AddSearchPath
      DeleteSearchPath
      SearchPathList
    """
    return Rhino.ApplicationSettings.FileSettings.SearchPathCount


def SearchPathList():
    """Returns all of the path items in Rhino's search path list.
    See "Options Files settings" in the Rhino help file for more details.
    Returns:
      list of str: list of search paths
    Example:
      import rhinoscriptsyntax as rs
      count = rs.SearchPathCount()
      if count>0:
          paths = rs.SearchPathList()
          for path in paths: print(path)
    See Also:
      AddSearchPath
      DeleteSearchPath
      SearchPathCount
    """
    return Rhino.ApplicationSettings.FileSettings.GetSearchPaths()


def SendKeystrokes(keys=None, add_return=True):
    """Sends a string of printable characters to Rhino's command line
    Parameters:
      keys (str, optional): A string of characters to send to the command line.
      add_return (bool, optional): Append a return character to the end of the string. If omitted an return character will be added (True)
    Returns:
      none
    Example:
      import rhinoscriptsyntax as rs
      rs.SendKeystroke( "Hello Rhino!" )
      rs.SendKeystrokes( 25/4 )
    See Also:
      Command
    """
    Rhino.RhinoApp.SendKeystrokes(keys, add_return)


def Snap(enable=None):
    """Enables or disables Rhino's grid snap modeling aid
    Parameters:
      enable (bool, optional): The new enabled status. If omitted the current status is returned.
    Returns:
      bool: the current grid snap status
    Example:
      import rhinoscriptsyntax as rs
      if not rs.Snap(): rs.Snap(True)
    See Also:
      Ortho
      Osnap
      Planar
    """
    rc = modelaid.GridSnap
    if enable is not None and enable != rc:
        modelaid.GridSnap = enable
    return rc


def StatusBarDistance(distance=0):
    """Sets Rhino's status bar distance pane
    Parameters:
      distance (number, optional): The distance to set the status bar.  If omitted the distance will be set to 0.
    Returns:
      none
    Example:
      import rhinoscriptsyntax as rs
      rs.StatusBarDistance(3.14159)
    See Also:
      StatusBarMessage
      StatusBarPoint
    """
    Rhino.UI.StatusBar.SetDistancePane(distance)


def StatusBarMessage(message=None):
    """Sets Rhino's status bar message pane
      Parameters:
        message (str, optional): The message to display.
      Returns:
        none
      Example:
      import rhinoscriptsyntax as rs
      rs.StatusBarMessage("Hello Rhino!")
    See Also:
        StatusBarDistance
        StatusBarPoint
    """
    Rhino.UI.StatusBar.SetMessagePane(message)


def StatusBarPoint(point=None):
    """Sets Rhino's status bar point coordinate pane
    Parameters:
      point (point3d, optional): The 3d coordinates of the status bar.  If omitted the current poition is set to (0,0,0).
    Returns:
      none
    Example:
      import rhinoscriptsyntax as rs
      pt = (1.1, 2.2, 3.3)
      rs.StatusBarPoint(pt)
    See Also:
      StatusBarDistance
      StatusBarMessage
    """
    point = rhutil.coerce3dpoint(point)
    if not point: point = Rhino.Geometry.Point3d(0,0,0)
    Rhino.UI.StatusBar.SetPointPane(point)


def StatusBarProgressMeterShow(label, lower, upper, embed_label=True, show_percent=True):
    """Start the Rhino status bar progress meter
    Parameters:
      label (str): Short description of the progesss
      lower (str): Lower limit of the progress meter's range
      upper (str): Upper limit of the progress meter's range
      embed_label (bool, optional): If True, the label will show inside the meter.
                                    If false, the label will show to the left of the meter.
                                    If omitted the label will show inside the meter (True)
      show_percent (bool): Show the percent complete if True. If omitted the percnetage will be shown (True)
    Returns:
      bool: True or False indicating success or failure
    Example:
    See Also:
    """
    rc = Rhino.UI.StatusBar.ShowProgressMeter(lower, upper, label, embed_label, show_percent)
    if rc==1:
        Rhino.RhinoApp.Wait()
        return True
    return False


def StatusBarProgressMeterUpdate(position, absolute=True):
    """Set the current position of the progress meter
    Parameters:
      position (number): The new position in the progress meter
      absolute (bool, optional): The position is set absolute (True) or relative (False) to its current position. If omitted the absolute (True) is used.
    Returns:
      number: previous position setting.
    Example:
    See Also:
    """
    res = Rhino.UI.StatusBar.UpdateProgressMeter(position, absolute)
    Rhino.RhinoApp.Wait()
    return res


def StatusBarProgressMeterHide():
    """Hide the progress meter
    Returns:
      none
    Example:
    See Also:
    """
    Rhino.UI.StatusBar.HideProgressMeter()
    Rhino.RhinoApp.Wait()


def TemplateFile(filename=None):
    """Returns or sets Rhino's default template file. This is the file used
    when Rhino starts.
    Parameters:
      filename (str, optional): The name of the new default template file. If omitted the current default template name is returned.
    Returns:
      str: if filename is not specified, then the current default template file
      str: if filename is specified, then the previous default template file
    Example:
      import rhinoscriptsyntax as rs
      folder = rs.TemplateFolder()
      filename = folder + "\\Millimeters.3dm"
      rs.TemplateFile(filename)
    See Also:
      TemplateFolder
    """
    rc = Rhino.ApplicationSettings.FileSettings.TemplateFile
    if filename: Rhino.ApplicationSettings.FileSettings.TemplateFile = filename
    return rc


def TemplateFolder(folder=None):
    """Returns or sets the location of Rhino's template folder
    Parameters:
      folder (str, optional): The location of Rhino's template files. Note, the location must exist.
    Returns:
      str: if folder is not specified, then the current template file folder
      str: if folder is specified, then the previous template file folder
    Example:
      import rhinoscriptsyntax as rs
      folder = rs.TemplateFolder()
      filename = folder + "\\Millimeters.3dm"
      rs.TemplateFile(filename)
    See Also:
      TemplateFile
    """
    rc = Rhino.ApplicationSettings.FileSettings.TemplateFolder
    if folder is not None: Rhino.ApplicationSettings.FileSettings.TemplateFolder = folder
    return rc


def WindowHandle():
    """Returns the windows handle of Rhino's main window
    Returns:
      IntPt: the Window's handle of Rhino's main window. IntPtr is a platform-specific type that is used to represent a pointer or a handle.
    Example:
      import rhinoscriptsyntax as rs
      handle = rs.WindowHandle()
      print(handle)
    See Also:

    """
    return Rhino.RhinoApp.MainWindowHandle()


def WorkingFolder(folder=None):
    """Returns or sets Rhino's working folder (directory).
    The working folder is the default folder for all file operations.
    Parameters:
      folder (str, optional): The new working folder for the current Rhino session.
    Returns:
      str: if folder is not specified, then the current working folder
      str: if folder is specified, then the previous working folder
    Example:
      import rhinoscriptsyntax as  rs
      folder = rs.WorkingFolder()
      folder = rs.BrowseForFolder(folder,  "Directory", "Select Directory")
      if folder is not None:
          rs.WorkingFolder(folder)
    See Also:
      BrowseForFolder
    """
    rc = Rhino.ApplicationSettings.FileSettings.WorkingFolder
    if folder is not None: Rhino.ApplicationSettings.FileSettings.WorkingFolder = folder
    return rc

```

--------------------------------------------------------------------------------
/rhino_mcp_server/static/selection.py:
--------------------------------------------------------------------------------

```python
import System.Drawing

import Rhino

import scriptcontext

import rhinocompat as compat
from rhinoscript import utility as rhutil
from rhinoscript import application as rhapp
from rhinoscript.layer import __getlayer
from rhinoscript.view import __viewhelper


class filter:
    allobjects = 0
    point = 1
    pointcloud = 2
    curve = 4
    surface = 8
    polysurface = 16
    mesh = 32
    light = 256
    annotation = 512
    instance = 4096
    textdot = 8192
    grip = 16384
    detail = 32768
    hatch = 65536
    morph = 131072
    subd = 262144
    cage = 134217728
    phantom = 268435456
    clippingplane = 536870912
    extrusion = 1073741824


def AllObjects(select=False, include_lights=False, include_grips=False, include_references=False):
    """Returns identifiers of all objects in the document.
    Parameters:
      select(bool, optional): Select the objects
      include_lights (bool, optional): Include light objects
      include_grips (bool, optional): Include grips objects
    Returns:
      list(guid, ...): identifiers for all the objects in the document
    Example:
      import rhinoscriptsyntax as rs
      objs = rs.AllObjects()
      for obj in objs: print("Object identifier: {}".format(obj))
    See Also:
      HiddenObjects
      LockedObjects
      NormalObjects
    """
    it = Rhino.DocObjects.ObjectEnumeratorSettings()
    it.IncludeLights = include_lights
    it.IncludeGrips = include_grips
    it.NormalObjects = True
    it.LockedObjects = True
    it.HiddenObjects = True
    it.ReferenceObjects = include_references
    e = scriptcontext.doc.Objects.GetObjectList(it)
    object_ids = []
    for object in e:
        if select: object.Select(True)
        object_ids.append(object.Id)
    if object_ids and select: scriptcontext.doc.Views.Redraw()
    return object_ids


def FirstObject(select=False, include_lights=False, include_grips=False):
    """Returns identifier of the first object in the document. The first
    object is the last object created by the user.
    Parameters:
      select (bool, optional): Select the object.  If omitted (False), the object is not selected.
      include_lights (bool, optional): Include light objects.  If omitted (False), light objects are not returned.
      include_grips (bool, optional): Include grips objects.  If omitted (False), grips objects are not returned.
    Returns:
      guid: The identifier of the object if successful.
    Example:
      import rhinoscriptsyntax as rs
      rs.AddLine( (0,0,0), (5,5,0) )
      rs.AddLine( (0,0,0), (5,0,0) )
      rs.AddLine( (0,0,0), (0,5,0) )
      objectId = rs.FirstObject()
      print("Object identifier: {}".format(objectId))
      rs.SelectObject(objectId)
    See Also:
      LastObject
      NextObject
    """
    it = Rhino.DocObjects.ObjectEnumeratorSettings()
    it.IncludeLights = include_lights
    it.IncludeGrips = include_grips
    e = scriptcontext.doc.Objects.GetObjectList(it).GetEnumerator()
    if not e.MoveNext(): return None
    object = e.Current
    if object:
        if select: object.Select(True)
        return object.Id


def __FilterHelper(input_filter):
    geometry_filter = compat.ENUM_NONE(Rhino.DocObjects.ObjectType)
    if input_filter & 1:
        geometry_filter |= Rhino.DocObjects.ObjectType.Point
    if input_filter & 16384:
        geometry_filter |= Rhino.DocObjects.ObjectType.Grip
    if input_filter & 2:
        geometry_filter |= Rhino.DocObjects.ObjectType.PointSet
    if input_filter & 4:
        geometry_filter |= Rhino.DocObjects.ObjectType.Curve
    if input_filter & 8:
        geometry_filter |= Rhino.DocObjects.ObjectType.Surface
    if input_filter & 16:
        geometry_filter |= Rhino.DocObjects.ObjectType.Brep
    if input_filter & 32:
        geometry_filter |= Rhino.DocObjects.ObjectType.Mesh
    if input_filter & 512:
        geometry_filter |= Rhino.DocObjects.ObjectType.Annotation
    if input_filter & 256:
        geometry_filter |= Rhino.DocObjects.ObjectType.Light
    if input_filter & 4096:
        geometry_filter |= Rhino.DocObjects.ObjectType.InstanceReference
    if input_filter & 134217728:
        geometry_filter |= Rhino.DocObjects.ObjectType.Cage
    if input_filter & 65536:
        geometry_filter |= Rhino.DocObjects.ObjectType.Hatch
    if input_filter & 131072:
        geometry_filter |= Rhino.DocObjects.ObjectType.MorphControl
    if input_filter & 262144:
        geometry_filter |= Rhino.DocObjects.ObjectType.SubD
    if input_filter & 2097152:
        geometry_filter |= Rhino.DocObjects.ObjectType.PolysrfFilter
    if input_filter & 268435456:
        geometry_filter |= Rhino.DocObjects.ObjectType.Phantom
    if input_filter & 8192:
        geometry_filter |= Rhino.DocObjects.ObjectType.TextDot
    if input_filter & 32768:
        geometry_filter |= Rhino.DocObjects.ObjectType.Detail
    if input_filter & 536870912:
        geometry_filter |= Rhino.DocObjects.ObjectType.ClipPlane
    if input_filter & 1073741824:
        geometry_filter |= Rhino.DocObjects.ObjectType.Extrusion
    return geometry_filter


def GetCurveObject(message=None, preselect=False, select=False):
    """Prompts user to pick or select a single curve object
    Parameters:
      message (str, optional): a prompt or message.
      preselect (bool,, optional): Allow for the selection of pre-selected objects.
      select (bool, optional): Select the picked objects. If False, objects that
        are picked are not selected.
    Returns:
      Tuple containing the following information
        [0]  guid     identifier of the curve object
        [1]  bool     True if the curve was preselected, otherwise False
        [2]  number   selection method
                         0 = selected by non-mouse method (SelAll, etc.).
                         1 = selected by mouse click on the object.
                         2 = selected by being inside of a mouse window.
                         3 = selected by intersecting a mouse crossing window.
        [3]  point    selection point
        [4]  number   the curve parameter of the selection point
        [5]  str      name of the view selection was made
      None: if no object picked
    Example:
      import rhinoscriptsyntax as rs
      select_result = rs.GetCurveObject("Select curve")
      if select_result:
          print("Curve identifier: {}".format(select_result[0]))
    See Also:
      GetObject
      GetObjects
      GetSurfaceObject
    """
    if not preselect:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    go = Rhino.Input.Custom.GetObject()
    if message: go.SetCommandPrompt(message)
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve
    go.SubObjectSelect = False
    go.GroupSelect = False
    go.AcceptNothing(True)
    if go.Get()!=Rhino.Input.GetResult.Object: return None
 
    objref = go.Object(0)
    id = objref.ObjectId
    presel = go.ObjectsWerePreselected
    selmethod = 0
    sm = objref.SelectionMethod()
    if Rhino.DocObjects.SelectionMethod.MousePick==sm: selmethod = 1
    elif Rhino.DocObjects.SelectionMethod.WindowBox==sm: selmethod = 2
    elif Rhino.DocObjects.SelectionMethod.CrossingBox==sm: selmethod = 3
    point = objref.SelectionPoint()
    crv, curve_parameter = objref.CurveParameter()
    viewname = go.View().ActiveViewport.Name
    obj = go.Object(0).Object()
    go.Dispose()
    if not select and not presel:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    obj.Select(select)
    return id, presel, selmethod, point, curve_parameter, viewname


def GetObject(message=None, filter=0, preselect=False, select=False, custom_filter=None, subobjects=False):
    """Prompts user to pick, or select, a single object.
    Parameters:
      message(str, optional): a prompt or message.
      filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
          that can be selected. Object types can be added together to filter
          several different kinds of geometry. use the filter class to get values
      preselect (bool, optional): Allow for the selection of pre-selected objects.
      select (bool, optional): Select the picked objects.  If False, the objects that are
          picked are not selected.
      subobjects (bool, optional): If True, subobjects can be selected. When this is the
          case, an ObjRef is returned instead of a Guid to allow for tracking
          of the subobject when passed into other functions
    Returns:
      guid: Identifier of the picked object
      None: if user did not pick an object
    Example:
      import rhinoscriptsyntax as rs
      objectId = rs.GetObject("Pick any object")
      if objectId:
          print("Object identifier: {}".format(objectId))
      objectId = rs.GetObject("Pick a curve or surface", rs.filter.curve | rs.filter.surface)
      if objectId:
          print("Object identifier: {}".format(objectId))
    See Also:
      GetCurveObject
      GetObjectEx
      GetObjects
      GetSurfaceObject
    """
    if not preselect:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    
    class CustomGetObject(Rhino.Input.Custom.GetObject):
        def __init__(self, filter_function):
            super(CustomGetObject, self).__init__()
            self.m_filter_function = filter_function
        def CustomGeometryFilter( self, rhino_object, geometry, component_index ):
            rc = True
            if self.m_filter_function is not None:
                try:
                    rc = self.m_filter_function(rhino_object, geometry, component_index)
                except:
                    rc = True
            return rc
    go = CustomGetObject(custom_filter)
    if message: go.SetCommandPrompt(message)
    geometry_filter = __FilterHelper(filter)
    if filter>0: go.GeometryFilter = geometry_filter
    go.SubObjectSelect = subobjects
    go.GroupSelect = False
    go.AcceptNothing(True)      
    if go.Get()!=Rhino.Input.GetResult.Object: return None
    objref = go.Object(0)
    obj = objref.Object()
    presel = go.ObjectsWerePreselected
    go.Dispose()
    if not select and not presel:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    if subobjects: return objref
    obj.Select(select)
    return obj.Id


class CustomGetObjectEx(Rhino.Input.Custom.GetObject):
    def __init__(self, allowable_geometry):
        super(CustomGetObjectEx, self).__init__()
        self.m_allowable = allowable_geometry
    def CustomGeometryFilter(self, rhino_object, geometry, component_index):
        for id in self.m_allowable:
            if id==rhino_object.Id: return True
        return False


def GetObjectEx(message=None, filter=0, preselect=False, select=False, objects=None):
    """Prompts user to pick, or select a single object
    Parameters:
      message (str, optional): a prompt or message.
      filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
          that can be selected. Object types can be added together to filter
          several different kinds of geometry. use the filter class to get values
      preselect (bool, optional):  Allow for the selection of pre-selected objects.
      select (bool, optional): Select the picked objects.  If False, the objects that are
          picked are not selected.
      objects ([guid, ...]): list of object identifiers specifying objects that are
          allowed to be selected
    Returns:
      tuple(guid, bool, number, point, str): containing the following information
          [0] identifier of the object
          [1] True if the object was preselected, otherwise False
          [2] selection method (see help)
          [3] selection point
          [4] name of the view selection was made
      None: if no object selected
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObjectEx("Select object", 0, True)
      if obj:
          print("Object id = {}".format(obj[0]))
          print("Object was preselected = {}".format(obj[1]))
          if obj[2]==0:
              print("Selection method = 0 (non-mouse)")
          elif obj[2]==1:
              print("Selection method = 1 (mouse)")
              print("Pick point = {}".format(obj[3]))
          elif obj[2]==2:
              print("Selection method = 2 (window)")
          elif obj[2]==3:
              print("Selection method = 3 (crossing)")
          print("Active view = {}".format(obj[4]))
    See Also:
      GetCurveObject
      GetObject
      GetObjects
      GetObjectsEx
      GetSurfaceObject
    """
    if not preselect:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    go = None
    if objects:
        ids = [rhutil.coerceguid(id, True) for id in objects]
        if ids: go = CustomGetObjectEx(ids)
    if not go: go = Rhino.Input.Custom.GetObject()
    if message: go.SetCommandPrompt(message)
    geometry_filter = __FilterHelper(filter)
    if filter>0: go.GeometryFilter = geometry_filter
    go.SubObjectSelect = False
    go.GroupSelect = False
    go.AcceptNothing(True)      
    if go.Get()!=Rhino.Input.GetResult.Object: return None
    objref = go.Object(0)
    id = objref.ObjectId
    presel = go.ObjectsWerePreselected
    selmethod = 0
    sm = objref.SelectionMethod()
    if Rhino.DocObjects.SelectionMethod.MousePick==sm: selmethod = 1
    elif Rhino.DocObjects.SelectionMethod.WindowBox==sm: selmethod = 2
    elif Rhino.DocObjects.SelectionMethod.CrossingBox==sm: selmethod = 3
    point = objref.SelectionPoint()
    viewname = go.View().ActiveViewport.Name
    obj = go.Object(0).Object()
    go.Dispose()
    if not select and not presel:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    obj.Select(select)
    return id, presel, selmethod, point, viewname


def GetObjects(message=None, filter=0, group=True, preselect=False, select=False, objects=None, minimum_count=1, maximum_count=0, custom_filter=None):
    """Prompts user to pick or select one or more objects.
    Parameters:
      message (str, optional): a prompt or message.
      filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
          that can be selected. Object types can be added together to filter
          several different kinds of geometry. use the filter class to get values
              Value         Description
              0             All objects (default)
              1             Point
              2             Point cloud
              4             Curve
              8             Surface or single-face brep
              16            Polysurface or multiple-face
              32            Mesh
              256           Light
              512           Annotation
              4096          Instance or block reference
              8192          Text dot object
              16384         Grip object
              32768         Detail
              65536         Hatch
              131072        Morph control
              262144        SubD
              134217728     Cage
              268435456     Phantom
              536870912     Clipping plane
              1073741824    Extrusion
      group (bool, optional): Honor object grouping.  If omitted and the user picks a group,
          the entire group will be picked (True). Note, if filter is set to a
          value other than 0 (All objects), then group selection will be disabled.
      preselect (bool, optional):  Allow for the selection of pre-selected objects.
      select (bool, optional): Select the picked objects.  If False, the objects that are
          picked are not selected.
      objects ([guid, ...]): list of objects that are allowed to be selected
      minimum_count, maximum_count(number): limits on number of objects allowed to be selected
      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
    Returns:
      list(guid, ...): identifiers of the picked objects
    Example:
      import rhinoscriptsyntax as rs
      objectIds = rs.GetObjects("Pick some curves", rs.filter.curve)
      for id in objectIds: print("Object identifier:{}".format(id))
    See Also:
      GetCurveObject
      GetObject
      GetSurfaceObject
    """
    if not preselect:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()

    objects = rhutil.coerceguidlist(objects)
    class CustomGetObject(Rhino.Input.Custom.GetObject):
        def __init__(self, filter_function):
            super(CustomGetObject, self).__init__()
            self.m_filter_function = filter_function
        def CustomGeometryFilter( self, rhino_object, geometry, component_index ):
            if objects and not rhino_object.Id in objects: return False
            rc = True
            if self.m_filter_function is not None:
                try:
                    rc = self.m_filter_function(rhino_object, geometry, component_index)
                except:
                    rc = True
            return rc
    go = CustomGetObject(custom_filter)
    go.SetCommandPrompt(message or "Select objects")
    geometry_filter = __FilterHelper(filter)
    if filter>0: go.GeometryFilter = geometry_filter
    go.SubObjectSelect = False
    go.GroupSelect = group
    go.AcceptNothing(True)
    if go.GetMultiple(minimum_count,maximum_count)!=Rhino.Input.GetResult.Object: return None
    if not select and not go.ObjectsWerePreselected:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    rc = []
    count = go.ObjectCount
    for i in compat.RANGE(count):
        objref = go.Object(i)
        rc.append(objref.ObjectId)
        obj = objref.Object()
        if select and obj is not None: obj.Select(select)
    go.Dispose()
    return rc


def GetObjectsEx(message=None, filter=0, group=True, preselect=False, select=False, objects=None):
    """Prompts user to pick, or select one or more objects
    Parameters:
      message (str, optional):  a prompt or message.
      filter (number, optional): The type(s) of geometry (points, curves, surfaces, meshes,...)
          that can be selected. Object types can be added together to filter
          several different kinds of geometry. use the filter class to get values
      group (bool, optional): Honor object grouping.  If omitted and the user picks a group,
          the entire group will be picked (True). Note, if filter is set to a
          value other than 0 (All objects), then group selection will be disabled.
      preselect (bool, optional):  Allow for the selection of pre-selected objects.
      select (bool, optional): Select the picked objects. If False, the objects that are
          picked are not selected.
      objects ([guid, ...]): list of object identifiers specifying objects that are
          allowed to be selected
    Returns:
      list(tuple(guid, bool, number, point, str), ...): containing the following information
        [n][0]  identifier of the object
        [n][1]  True if the object was preselected, otherwise False
        [n][2]  selection method (see help)
        [n][3]  selection point
        [n][4]  name of the view selection was made
    Example:
      import rhinoscriptsyntax as rs
      objects = rs.GetObjectsEx("Select objects", 0, True)
      for obj in objects:
          print("Object id = {}".format(obj[0]))
          print("Object was preselected = {}".format(obj[1]))
          if obj[2]==0:
              print("Selection method = 0 (non-mouse)")
          elif obj[2]==1:
              print("Selection method = 1 (mouse)")
              print("Pick point = {}".format(obj[3]))
          elif obj[2]==2:
              print("Selection method = 2 (window)")
          elif obj[2]==3:
              print("Selection method = 3 (crossing)")
          print("Active view = {}".format(obj[4]))
    See Also:
      GetCurveObject
      GetObject
      GetObjectEx
      GetObjects
      GetSurfaceObject
    """
    if not preselect:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    go = None
    if objects:
        ids = [rhutil.coerceguid(id) for id in objects]
        if ids: go = CustomGetObjectEx(ids)
    if not go: go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt(message or "Select objects")
    geometry_filter = __FilterHelper(filter)
    if filter>0: go.GeometryFilter = geometry_filter
    go.SubObjectSelect = False
    go.GroupSelect = group
    go.AcceptNothing(True)      
    if go.GetMultiple(1,0)!=Rhino.Input.GetResult.Object: return []
    if not select and not go.ObjectsWerePreselected:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    rc = []
    count = go.ObjectCount
    for i in compat.RANGE(count):
        objref = go.Object(i)
        id = objref.ObjectId
        presel = go.ObjectsWerePreselected
        selmethod = 0
        sm = objref.SelectionMethod()
        if Rhino.DocObjects.SelectionMethod.MousePick==sm: selmethod = 1
        elif Rhino.DocObjects.SelectionMethod.WindowBox==sm: selmethod = 2
        elif Rhino.DocObjects.SelectionMethod.CrossingBox==sm: selmethod = 3
        point = objref.SelectionPoint()
        viewname = go.View().ActiveViewport.Name
        rc.append( (id, presel, selmethod, point, viewname) )
        obj = objref.Object()
        if select and obj is not None: obj.Select(select)
    go.Dispose()
    return rc


def GetPointCoordinates(message="Select points", preselect=False):
    """Prompts the user to select one or more point objects.
    Parameters:
      message (str, optional): a prompt message.
      preselect (bool, optional): Allow for the selection of pre-selected objects.  If omitted (False), pre-selected objects are not accepted.
    Returns:
      list(point, ...): 3d coordinates of point objects on success
    Example:
      import rhinoscriptsyntax as rs
      points = rs.GetPointCoordinates()
      for point in points: print(point)
    See Also:
      GetObject
      GetObjects
      GetPoint
      GetPoints
      PointCoordinates
    """
    ids = GetObjects(message, filter.point, preselect=preselect)
    rc = []
    for id in ids:
        rhobj = scriptcontext.doc.Objects.Find(id)
        rc.append(rhobj.Geometry.Location)
    return rc


def GetSurfaceObject(message="Select surface", preselect=False, select=False):
    """Prompts the user to select a single surface
    Parameters:
      message(str, optional): prompt displayed
      preselect (bool, optional): allow for preselected objects
      select (bool, optional):  select the picked object
    Returns:
      tuple(guid, bool, number, point, (number, number), str): of information on success
        [0]  identifier of the surface
        [1]  True if the surface was preselected, otherwise False
        [2]  selection method ( see help )
        [3]  selection point
        [4]  u,v surface parameter of the selection point
        [5]  name of the view in which the selection was made
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      select = rs.GetSurfaceObject("Select surface")
      if select:
          print("Surface identifier: {}".format(select[0]))
    See Also:
      GetCurveObject
      GetObject
      GetObjects
    """
    if not preselect:
        scriptcontext.doc.Objects.UnselectAll()
        scriptcontext.doc.Views.Redraw()
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt(message)
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Surface
    go.SubObjectSelect = False
    go.GroupSelect = False
    go.AcceptNothing(True)
    if go.Get()!=Rhino.Input.GetResult.Object:
        return scriptcontext.errorhandler()
    objref = go.Object(0)
    rhobj = objref.Object()
    rhobj.Select(select)
    scriptcontext.doc.Views.Redraw()

    id = rhobj.Id
    prepicked = go.ObjectsWerePreselected
    selmethod = objref.SelectionMethod()
    point = objref.SelectionPoint()
    surf, u, v = objref.SurfaceParameter()
    uv = (u,v)
    if not point.IsValid:
        point = None
        uv = None
    view = go.View()
    name = view.ActiveViewport.Name
    go.Dispose()
    if not select and not prepicked:
      scriptcontext.doc.Objects.UnselectAll()
      scriptcontext.doc.Views.Redraw()
    return id, prepicked, selmethod, point, uv, name


def LockedObjects(include_lights=False, include_grips=False, include_references=False):
    """Returns identifiers of all locked objects in the document. Locked objects
    cannot be snapped to, and cannot be selected
    Parameters:
      include_lights (bool, optional): include light objects
      include_grips (bool, optional): include grip objects
    Returns:
      list(guid, ...): identifiers the locked objects if successful.
    Example:
      import rhinoscriptsyntax as  rs
      objs = rs.LockedObjects()
      for obj in objs: print("Object  identifier:{}".format(obj))
    See Also:
      AllObjects
      HiddenObjects
      NormalObjects
    """
    settings = Rhino.DocObjects.ObjectEnumeratorSettings()
    settings.ActiveObjects = True
    settings.NormalObjects = True
    settings.LockedObjects = True
    settings.HiddenObjects = True
    settings.IncludeLights = include_lights
    settings.IncludeGrips = include_grips
    settings.ReferenceObjects = include_references
    return [i.Id for i in scriptcontext.doc.Objects.GetObjectList(settings)
        if i.IsLocked or (scriptcontext.doc.Layers[i.Attributes.LayerIndex]).IsLocked]


def HiddenObjects(include_lights=False, include_grips=False, include_references=False):
    """Returns identifiers of all hidden objects in the document. Hidden objects
    are not visible, cannot be snapped to, and cannot be selected
    Parameters:
      include_lights (bool, optional): include light objects
      include_grips (bool, optional): include grip objects
    Returns:
      list(guid, ...): identifiers of the hidden objects if successful.
    Example:
      import rhinoscriptsyntax as rs
      hidden = rs.HiddenObjects()
      for obj in hidden: print("Object identifier{}".format(obj))
    See Also:
      AllObjects
      LockedObjects
      NormalObjects
    """
    settings = Rhino.DocObjects.ObjectEnumeratorSettings()
    settings.ActiveObjects = True
    settings.NormalObjects = True
    settings.LockedObjects = True
    settings.HiddenObjects = True
    settings.IncludeLights = include_lights
    settings.IncludeGrips = include_grips
    settings.ReferenceObjects = include_references
    return [i.Id for i in scriptcontext.doc.Objects.GetObjectList(settings)
        if i.IsHidden or not (scriptcontext.doc.Layers[i.Attributes.LayerIndex]).IsVisible]


def InvertSelectedObjects(include_lights=False, include_grips=False, include_references=False):
    """Inverts the current object selection. The identifiers of the newly
    selected objects are returned
    Parameters:
      include_lights (bool, optional): Include light objects.  If omitted (False), light objects are not returned.
      include_grips (bool, optional): Include grips objects.  If omitted (False), grips objects are not returned.
      include_references (bool, optional): Include reference objects.  If omitted (False), reference objects are not returned.
    Returns:
      list(guid, ...): identifiers of the newly selected objects if successful.
    Example:
      import rhinoscriptsyntax as rs
      rs.GetObjects("Select some objects", select=True)
      objs = rs.InvertSelectedObjects()
      for id in objs: print("Object identifier:{}".format(id))
    See Also:
      SelectedObjects
      UnselectAllObjects
    """
    settings = Rhino.DocObjects.ObjectEnumeratorSettings()
    settings.IncludeLights = include_lights
    settings.IncludeGrips = include_grips
    settings.IncludePhantoms = True
    settings.ReferenceObjects = include_references
    rhobjs = scriptcontext.doc.Objects.GetObjectList(settings)
    rc = []
    for obj in rhobjs:
        if not obj.IsSelected(False) and obj.IsSelectable():
            rc.append(obj.Id)
            obj.Select(True)
        else:
            obj.Select(False)
    scriptcontext.doc.Views.Redraw()
    return rc


def LastCreatedObjects(select=False):
    """Returns identifiers of the objects that were most recently created or changed
    by scripting a Rhino command using the Command function. It is important to
    call this function immediately after calling the Command function as only the
    most recently created or changed object identifiers will be returned
    Parameters:
      select (bool, optional): Select the object.  If omitted (False), the object is not selected.
    Returns:
      list(guid, ...): identifiers of the most recently created or changed objects if successful.
    Example:
      import rhinoscriptsyntax as rs
      rs.Command( "_-Circle 0,0,0 10" )
      rs.Command( "_-Circle 10,0,0 10" )
      rs.Command( "_-Circle 20,0,0 10" )
      objs = rs.LastCreatedObjects()
      if objs:
          # Only the last circle will be selected
          rs.SelectObjects( objs )
    See Also:
      Command
    """
    serial_numbers = rhapp.__command_serial_numbers
    if serial_numbers is None: return scriptcontext.errorhandler()
    serial_number = serial_numbers[0]
    end = serial_numbers[1]
    rc = []
    while serial_number<end:
        obj = scriptcontext.doc.Objects.Find(serial_number)
        if obj and not obj.IsDeleted:
            rc.append(obj.Id)
            if select: obj.Select(True)
        serial_number += 1
    if select==True and rc: scriptcontext.doc.Views.Redraw()
    return rc


def LastObject(select=False, include_lights=False, include_grips=False):
    """Returns the identifier of the last object in the document. The last object
    in the document is the first object created by the user
    Parameters:
      select (bool, optional): select the object
      include_lights (bool, optional): include lights in the potential set
      include_grips (bool, optional): include grips in the potential set
    Returns:
      guid: identifier of the object on success
    Example:
      import rhinoscriptsyntax as rs
      rs.AddLine((0,0,0), (5,5,0))
      rs.AddCircle((0,0,0), 5)
      print("Object identifier: {}".format(rs.LastObject()))
    See Also:
      FirstObject
      NextObject
    """
    settings = Rhino.DocObjects.ObjectEnumeratorSettings()
    settings.IncludeLights = include_lights
    settings.IncludeGrips = include_grips
    settings.DeletedObjects = False
    rhobjs = scriptcontext.doc.Objects.GetObjectList(settings)
    firstobj = None
    for obj in rhobjs: firstobj = obj
    if firstobj is None: return scriptcontext.errorhandler()
    rc = firstobj.Id
    if select:
        firstobj.Select(True)
        scriptcontext.doc.Views.Redraw()
    return rc


def NextObject(object_id, select=False, include_lights=False, include_grips=False):
    """Returns the identifier of the next object in the document
    Parameters:
      object_id (guid): the identifier of the object from which to get the next object
      select (bool, optional): select the object
      include_lights (bool, optional): include lights in the potential set
      include_grips (bool, optional): include grips in the potential set
    Returns:
      guid: identifier of the object on success
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.FirstObject()
      while obj:
          print("Object identifier:{}".format(obj))
          obj = rs.NextObject(obj)
    See Also:
      FirstObject
      LastObject
    """
    current_obj = rhutil.coercerhinoobject(object_id, True)
    settings = Rhino.DocObjects.ObjectEnumeratorSettings()
    settings.IncludeLights = include_lights
    settings.IncludeGrips = include_grips
    settings.DeletedObjects = False
    rhobjs = scriptcontext.doc.Objects.GetObjectList(settings)
    found = False
    for obj in rhobjs:
        if found and obj: 
            if select: obj.Select(True)
            return obj.Id
        if obj.Id == current_obj.Id: found = True


def NormalObjects(include_lights=False, include_grips=False):
    """Returns identifiers of all normal objects in the document. Normal objects
    are visible, can be snapped to, and are independent of selection state
    Parameters:
      include_lights (bool, optional): Include light objects.  If omitted (False), light objects are not returned.
      include_gripts (bool, optional): Include grips objects.  If omitted (False), grips objects are not returned.
    Returns:
      list(guid, ...): identifier of normal objects if successful.
    Example:
      import rhinoscriptsyntax as rs
      objs = rs.NormalObjects()
      for obj in objs: print("Object identifier:{}".format(obj))
    See Also:
      AllObjects
      HiddenObjects
      LockedObjects
    """
    iter = Rhino.DocObjects.ObjectEnumeratorSettings()
    iter.NormalObjects = True
    iter.LockedObjects = False
    iter.IncludeLights = include_lights
    iter.IncludeGrips = include_grips
    return [obj.Id for obj in scriptcontext.doc.Objects.GetObjectList(iter)]


def ObjectsByColor(color, select=False, include_lights=False):
    """Returns identifiers of all objects based on color
    Parameters:
      color (color): color to get objects by
      select (bool, optional): select the objects
      include_lights (bool, optional): include lights in the set
    Returns:
      list(guid, ...): identifiers of objects of the selected color.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Pick any object")
      if obj:
          color = rs.ObjectColor(obj)
          rs.ObjectsByColor(color, True)
    See Also:
      
    """
    color = rhutil.coercecolor(color, True)
    rhino_objects = scriptcontext.doc.Objects.FindByDrawColor(color, include_lights)
    if select:
        for obj in rhino_objects: obj.Select(True)
        scriptcontext.doc.Views.Redraw()
    return [obj.Id for obj in rhino_objects]


def ObjectsByGroup(group_name, select=False):
    """Returns identifiers of all objects based on the objects' group name
    Parameters:
      group_name (str): name of the group
      select (bool, optional): select the objects
    Returns:
      list(guid, ...):identifiers for objects in the group on success
    Example:
      import rhinoscriptsyntax as rs
      group = rs.GetString("Group to select")
      if group: rs.ObjectsByGroup( group, True )
    See Also:
      
    """
    group_instance = scriptcontext.doc.Groups.FindName(group_name)
    if group_instance is None: raise ValueError("%s does not exist in GroupTable"%group_name)
    rhino_objects = scriptcontext.doc.Groups.GroupMembers(group_instance.Index)
    if not rhino_objects: return []
    if select:
        for obj in rhino_objects: obj.Select(True)
        scriptcontext.doc.Views.Redraw()
    return [obj.Id for obj in rhino_objects]


def ObjectsByLayer(layer_name, select=False):
    """Returns identifiers of all objects based on the objects' layer name
    Parameters:
      layer_name (str): name of the layer
      select (bool, optional): select the objects
    Returns:
      list(guid, ...): identifiers for objects in the specified layer
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Pick any object")
      if obj:
          layer = rs.ObjectLayer(obj)
          rs.ObjectsByLayer(layer, True)
    See Also:
      
    """
    layer = __getlayer(layer_name, True)
    rhino_objects = scriptcontext.doc.Objects.FindByLayer(layer)
    if not rhino_objects: return []
    if select:
        for rhobj in rhino_objects: rhobj.Select(True)
        scriptcontext.doc.Views.Redraw()
    return [rhobj.Id for rhobj in rhino_objects]


def ObjectsByName(name, select=False, include_lights=False, include_references=False):
    """Returns identifiers of all objects based on user-assigned name
    Parameters:
      name (str): name of the object or objects
      select (bool, optional): select the objects
      include_lights (bool, optional): include light objects
    Returns:
      list(guid, ...): identifiers for objects with the specified name.
    Example:
      import rhinoscriptsyntax as rs
      name = rs.GetString("Name to select")
      if name: rs.ObjectsByName(name,True)
    See Also:
      
    """
    settings = Rhino.DocObjects.ObjectEnumeratorSettings()
    settings.HiddenObjects = True
    settings.DeletedObjects = False
    settings.IncludeGrips = False
    settings.IncludePhantoms = True
    settings.IncludeLights = include_lights
    settings.NameFilter = name
    settings.ReferenceObjects = include_references
    objects = scriptcontext.doc.Objects.GetObjectList(settings)
    ids = [rhobj.Id for rhobj in objects]
    if ids and select:
        objects = scriptcontext.doc.Objects.GetObjectList(settings)
        for rhobj in objects: rhobj.Select(True)
        scriptcontext.doc.Views.Redraw()
    return ids
   

def ObjectsByType(geometry_type, select=False, state=0):
    """Returns identifiers of all objects based on the objects' geometry type.
    Parameters:
      geometry_type (number): The type(s) of geometry objects (points, curves, surfaces,
             meshes, etc.) that can be selected. Object types can be
             added together as bit-coded flags to filter several different kinds of geometry.
              Value        Description
               0           All objects
               1           Point
               2           Point cloud
               4           Curve
               8           Surface or single-face brep
               16          Polysurface or multiple-face
               32          Mesh
               256         Light
               512         Annotation
               4096        Instance or block reference
               8192        Text dot object
               16384       Grip object
               32768       Detail
               65536       Hatch
               131072      Morph control
               262144      SubD
               134217728   Cage
               268435456   Phantom
               536870912   Clipping plane
               1073741824  Extrusion
      select (bool, optional): Select the objects
      state (bool, optional): The object state (normal, locked, and hidden). Object states can be 
        added together to filter several different states of geometry.
              Value     Description
              0         All objects
              1         Normal objects
              2         Locked objects
              4         Hidden objects
    Returns:
      list(guid, ...): identifiers of object that fit the specified type(s).
    Example:
      import rhinoscriptsyntax as rs
      objs = rs.ObjectsByType(4 | 8, True)
    See Also:
      
    """
    if not state: state = 7
    bSurface = False
    bPolySurface = False
    bLights = False
    bGrips = False
    bPhantoms = False
    geometry_filter = __FilterHelper(geometry_type)
    if type(geometry_type) is int and geometry_type==0:
        geometry_filter = Rhino.DocObjects.ObjectType.AnyObject
    if geometry_filter & Rhino.DocObjects.ObjectType.Surface: bSurface = True
    if geometry_filter & Rhino.DocObjects.ObjectType.Brep: bPolySurface = True
    if geometry_filter & Rhino.DocObjects.ObjectType.Light: bLights = True
    if geometry_filter & Rhino.DocObjects.ObjectType.Grip: bGrips = True
    if geometry_filter & Rhino.DocObjects.ObjectType.Phantom: bPhantoms = True

    it = Rhino.DocObjects.ObjectEnumeratorSettings()
    it.DeletedObjects = False
    it.ActiveObjects = True
    it.ReferenceObjects = True
    it.IncludeLights = bLights
    it.IncludeGrips = bGrips
    it.IncludePhantoms = bPhantoms

    if state:
        it.NormalObjects = False
        it.LockedObjects = False
    if state & 1: it.NormalObjects = True
    if state & 2: it.LockedObjects = True
    if state & 4: it.HiddenObjects = True

    object_ids = []
    e = scriptcontext.doc.Objects.GetObjectList(it)
    for object in e:
        bFound = False
        object_type = object.ObjectType
        if object_type==Rhino.DocObjects.ObjectType.Brep and (bSurface or bPolySurface):
            brep = rhutil.coercebrep(object.Id)
            if brep:
                if brep.Faces.Count==1:
                    if bSurface: bFound = True
                else:
                    if bPolySurface: bFound = True
        elif object_type==Rhino.DocObjects.ObjectType.Extrusion and (bSurface or bPolySurface):
            extrusion = object.Geometry
            profile_count = extrusion.ProfileCount
            cap_count = extrusion.CapCount
            if profile_count==1 and cap_count==0 and bSurface:
                bFound = True
            elif profile_count>0 and cap_count>0 and bPolySurface:
                bFound = True
        elif object_type & geometry_filter:
            bFound = True

        if bFound:
            if select: object.Select(True)
            object_ids.append(object.Id)

    if object_ids and select: scriptcontext.doc.Views.Redraw()
    return object_ids
  

def SelectedObjects(include_lights=False, include_grips=False):
    """Returns the identifiers of all objects that are currently selected
    Parameters:
      include_lights (bool, optional): include light objects
      include_grips (bool, optional): include grip objects
    Returns:
      list(guid, ...) identifiers of selected objects
    Example:
      import rhinoscriptsyntax as rs
      objects = rs.SelectedObjects()
      for obj in objects: print("Object identifier: {}".format(obj))
    See Also:
      InvertSelectedObjects
      UnselectAllObjects
    """
    selobjects = scriptcontext.doc.Objects.GetSelectedObjects(include_lights, include_grips)
    return [obj.Id for obj in selobjects]


def UnselectAllObjects():
    """Unselects all objects in the document
    Returns:
      number: the number of objects that were unselected
    Example:
      import rhinoscriptsyntax as rs
      count = rs.UnselectAllObjects()
      print("{} objects were unselected".format(count))
    See Also:
      InvertSelectedObjects
      SelectedObjects
    """
    rc = scriptcontext.doc.Objects.UnselectAll()
    if rc>0: scriptcontext.doc.Views.Redraw()
    return rc


def VisibleObjects(view=None, select=False, include_lights=False, include_grips=False):
    """Return identifiers of all objects that are visible in a specified view
    Parameters:
      view (bool, optional): the view to use. If omitted, the current active view is used
      select (bool, optional): Select the objects
      include_lights (bool, optional): include light objects
      include_grips (bool, optional): include grip objects
    Returns:
      list(guid, ...): identifiers of the visible objects
    Example:
      import rhinoscriptsyntax as rs
      object_ids = rs.VisibleObjects("Top")
      if object_ids:
          for id in object_ids: print("Object identifier:{}".format(id))
    See Also:
      IsView
      IsVisibleInView
    """
    it = Rhino.DocObjects.ObjectEnumeratorSettings()
    it.DeletedObjects = False
    it.ActiveObjects = True
    it.ReferenceObjects = True
    it.IncludeLights = include_lights
    it.IncludeGrips = include_grips
    it.VisibleFilter = True
    viewport = __viewhelper(view).MainViewport
    it.ViewportFilter = viewport

    object_ids = []
    e = scriptcontext.doc.Objects.GetObjectList(it)
    for object in e:
        bbox = object.Geometry.GetBoundingBox(True)
        if viewport.IsVisible(bbox):
            if select: object.Select(True)
            object_ids.append(object.Id)

    if object_ids and select: scriptcontext.doc.Views.Redraw()
    return object_ids


def WindowPick(corner1, corner2, view=None, select=False, in_window=True):
    """Picks objects using either a window or crossing selection
    Parameters:
      corner1, corner2 (point): corners of selection window
      view (bool, optional): view to perform the selection in
      select (bool, optional): select picked objects
      in_window (bool, optional): if False, then a crossing window selection is performed
    Returns:
      list(guid, ...): identifiers of selected objects on success
    Example:
      import rhinoscriptsyntax as  rs
      rs.WindowPick((0,0,0), (0,0,0),  None, True)
    See Also:
      
    """
    view = __viewhelper(view)
    viewport = view.MainViewport

    screen1 = rhutil.coerce3dpoint(corner1, True)
    screen2 = rhutil.coerce3dpoint(corner2, True)
    xf = viewport.GetTransform(Rhino.DocObjects.CoordinateSystem.World, Rhino.DocObjects.CoordinateSystem.Screen)
    screen1.Transform(xf)
    screen2.Transform(xf)

    pc = Rhino.Input.Custom.PickContext()
    pc.View = view
    pc.PickStyle = Rhino.Input.Custom.PickStyle.WindowPick if in_window else Rhino.Input.Custom.PickStyle.CrossingPick
    pc.PickGroupsEnabled = True if in_window else False
    _, frustumLine = viewport.GetFrustumLine((screen1.X + screen2.X) / 2.0, (screen1.Y + screen2.Y) / 2.0)
    pc.PickLine = frustumLine
    
    leftX = min(screen1.X, screen2.X)
    topY = min(screen1.Y, screen2.Y)
    w = abs(screen1.X - screen2.X)
    h = abs(screen1.Y - screen2.Y)
    rec = System.Drawing.Rectangle(leftX, topY, w, h)
 
    pc.SetPickTransform(viewport.GetPickTransform(rec))
    pc.UpdateClippingPlanes()
    
    objects = scriptcontext.doc.Objects.PickObjects(pc)

    if objects:
        rc = []
        for rhobj in objects:
            o = rhobj.Object()
            rc.append(o.Id)
            if select: o.Select(True)
        if select: scriptcontext.doc.Views.Redraw()
        return rc

```

--------------------------------------------------------------------------------
/rhino_mcp_server/static/mesh.py:
--------------------------------------------------------------------------------

```python
import System
import System.Drawing

import Rhino

import scriptcontext

import rhinocompat as compat
from rhinoscript import utility as rhutil
from rhinoscript.view import __viewhelper


def AddMesh(vertices, face_vertices, vertex_normals=None, texture_coordinates=None, vertex_colors=None):
    """Add a mesh object to the document
    Parameters:
      vertices ([point, ...]) list of 3D points defining the vertices of the mesh
      face_vertices ([[number, number, number], [number, number, number, number], ...]) list containing lists of 3 or 4 numbers that define the
                    vertex indices for each face of the mesh. If the third a fourth vertex
                     indices of a face are identical, a triangular face will be created.
      vertex_normals ([vector, ...], optional) list of 3D vectors defining the vertex normals of
        the mesh. Note, for every vertex, there must be a corresponding vertex
        normal
      texture_coordinates ([[number, number], [number, number], [number, number]], ...], optional): list of 2D texture coordinates. For every
        vertex, there must be a corresponding texture coordinate
      vertex_colors ([color, ...]) a list of color values. For every vertex,
        there must be a corresponding vertex color
    Returns:
      guid: Identifier of the new object if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      vertices = []
      vertices.append((0.0,0.0,0.0))
      vertices.append((5.0, 0.0, 0.0))
      vertices.append((10.0, 0.0, 0.0))
      vertices.append((0.0, 5.0, 0.0))
      vertices.append((5.0, 5.0, 0.0))
      vertices.append((10.0, 5.0, 0.0))
      vertices.append((0.0, 10.0, 0.0))
      vertices.append((5.0, 10.0, 0.0))
      vertices.append((10.0, 10.0, 0.0))
      faceVertices = []
      faceVertices.append((0,1,4,4))
      faceVertices.append((2,4,1,1))
      faceVertices.append((0,4,3,3))
      faceVertices.append((2,5,4,4))
      faceVertices.append((3,4,6,6))
      faceVertices.append((5,8,4,4))
      faceVertices.append((6,4,7,7))
      faceVertices.append((8,7,4,4))
      rs.AddMesh( vertices, faceVertices )
    See Also:
      MeshFaces
      MeshFaceVertices
      MeshVertexNormals
      MeshVertices
    """
    mesh = Rhino.Geometry.Mesh()
    for a, b, c in vertices: mesh.Vertices.Add(a, b, c)
    for face in face_vertices:
        if len(face)<4:
            mesh.Faces.AddFace(face[0], face[1], face[2])
        else:
            mesh.Faces.AddFace(face[0], face[1], face[2], face[3])
    if vertex_normals:
        count = len(vertex_normals)
        normals = System.Array.CreateInstance(Rhino.Geometry.Vector3f, count)
        for i, normal in enumerate(vertex_normals):
            normals[i] = Rhino.Geometry.Vector3f(normal[0], normal[1], normal[2])
        mesh.Normals.SetNormals(normals)
    if texture_coordinates:
        count = len(texture_coordinates)
        tcs = System.Array.CreateInstance(Rhino.Geometry.Point2f, count)
        for i, tc in enumerate(texture_coordinates):
            tcs[i] = Rhino.Geometry.Point2f(tc[0], tc[1])
        mesh.TextureCoordinates.SetTextureCoordinates(tcs)
    if vertex_colors:
        count = len(vertex_colors)
        colors = System.Array.CreateInstance(System.Drawing.Color, count)
        for i, color in enumerate(vertex_colors):
            colors[i] = rhutil.coercecolor(color)
        mesh.VertexColors.SetColors(colors)
    rc = scriptcontext.doc.Objects.AddMesh(mesh)
    if rc==System.Guid.Empty: raise Exception("unable to add mesh to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def AddPlanarMesh(object_id, delete_input=False):
    """Creates a planar mesh from a closed, planar curve
    Parameters:
      object_id (guid): identifier of a closed, planar curve
      delete_input (bool, optional) if True, delete the input curve defined by object_id
    Returns:
      guid: id of the new mesh on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select planar curves to build mesh", rs.filter.curve)
      if obj: rs.AddPlanarMesh(obj)
    See Also:
      IsCurveClosed
      IsCurvePlanar
    """
    curve = rhutil.coercecurve(object_id, -1, True)
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    mesh = Rhino.Geometry.Mesh.CreateFromPlanarBoundary(curve, Rhino.Geometry.MeshingParameters.Default, tolerance)
    if not mesh: return scriptcontext.errorhandler()
    if delete_input:
        id = rhutil.coerceguid(object_id, True)
        rc = scriptcontext.doc.Objects.Replace(id, mesh)
    else:
        rc = scriptcontext.doc.Objects.AddMesh(mesh)
    if rc==System.Guid.Empty: raise Exception("unable to add mesh to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def CurveMeshIntersection(curve_id, mesh_id, return_faces=False):
    """Calculates the intersection of a curve object and a mesh object
    Parameters:
      curve_id (guid): identifier of a curve object
      mesh_id (guid): identifier or a mesh object
      return_faces (bool, optional): return both intersection points and face indices.
        If False, then just the intersection points are returned
    Returns:
      list(point, ...): if return_false is omitted or False, then a list of intersection points
      list([point, number], ...): if return_false is True, the a one-dimensional list containing information
        about each intersection. Each element contains the following two elements
          [0] = point of intersection
          [1] = mesh face index where intersection lies
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      curve = rs.GetObject("Select curve to intersect", rs.filter.curve)
      if curve:
          mesh = rs.GetObject("Select mesh to intersect", rs.filter.mesh)
          if mesh:
              cmx = rs.CurveMeshIntersection(curve, mesh, True)
              if cmx:
                  for element in cmx:
                      print("{}, Face index = {}".format(element[0], element[1]))
                      rs.AddPoint(element[0])
    See Also:
      MeshClosestPoint
      MeshMeshIntersection
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    mesh = rhutil.coercemesh(mesh_id, True)
    tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    polylinecurve = curve.ToPolyline(0,0,0,0,0.0,tolerance,0.0,0.0,True)
    pts, faceids = Rhino.Geometry.Intersect.Intersection.MeshPolyline(mesh, polylinecurve)
    if not pts: return scriptcontext.errorhandler()
    pts = list(pts)
    if return_faces:
        faceids = list(faceids)
        return compat.ITERATOR2LIST(zip(pts, faceids))
    return pts


def DisjointMeshCount(object_id):
    """Returns number of meshes that could be created by calling SplitDisjointMesh
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      number: The number of meshes that could be created
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      if rs.DisjointMeshCount(obj)>1: rs.SplitDisjointMesh(obj)
    See Also:
      IsMesh
      SplitDisjointMesh
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.DisjointMeshCount


def DuplicateMeshBorder(mesh_id):
    """Creates curves that duplicates a mesh border
    Parameters:
      mesh_id (guid): identifier of a mesh object
    Returns:
      list(guid, ...): list of curve ids on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      if obj: rs.DuplicateMeshBorder(obj)
    See Also:
      DuplicateEdgeCurves
      DuplicateSurfaceBorder
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    polylines = mesh.GetNakedEdges()
    rc = []
    if polylines:
        for polyline in polylines:
            id = scriptcontext.doc.Objects.AddPolyline(polyline)
            if id!=System.Guid.Empty: rc.append(id)
    if rc: scriptcontext.doc.Views.Redraw()
    return rc


def ExplodeMeshes(mesh_ids, delete=False):
    """Explodes a mesh object, or mesh objects int submeshes. A submesh is a
    collection of mesh faces that are contained within a closed loop of
    unwelded mesh edges. Unwelded mesh edges are where the mesh faces that
    share the edge have unique mesh vertices (not mesh topology vertices)
    at both ends of the edge
    Parameters:
      mesh_ids ([guid, ...]): list of mesh identifiers
      delete (bool, optional): delete the input meshes
    Returns:
      list(guid, ...): List of resulting objects after explode.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh to explode", rs.filter.mesh)
      if rs.IsMesh(obj): rs.ExplodeMeshes(obj)
    See Also:
      IsMesh
    """
    id = rhutil.coerceguid(mesh_ids)
    if id: mesh_ids = [mesh_ids]
    rc = []
    for mesh_id in mesh_ids:
        mesh = rhutil.coercemesh(mesh_id, True)
        if mesh:
            submeshes = mesh.ExplodeAtUnweldedEdges()
            if submeshes:
                for submesh in submeshes:
                    id = scriptcontext.doc.Objects.AddMesh(submesh)
                    if id!=System.Guid.Empty: rc.append(id)
            if delete:
                scriptcontext.doc.Objects.Delete(mesh_id, True)
                
    if rc: scriptcontext.doc.Views.Redraw()
    return rc


def IsMesh(object_id):
    """Verifies if an object is a mesh
    Parameters:
      object_id (guid): the object's identifier
    Returns:
      bool: True if successful, otherwise False
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh")
      if rs.IsMesh(obj):
          print("The object is a mesh.")
      else:
          print("The object is not a mesh.")
    See Also:
      IsMeshClosed
      MeshFaceCount
      MeshFaces
      MeshVertexCount
      MeshVertices
    """
    mesh = rhutil.coercemesh(object_id)
    return mesh is not None


def IsMeshClosed(object_id):
    """Verifies a mesh object is closed
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      bool: True if successful, otherwise False.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh", rs.filter.mesh)
      if rs.IsMeshClosed(obj):
          print("The mesh is closed.")
      else:
          print("The mesh is not closed.")
    See Also:
      IsMesh
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.IsClosed


def IsMeshManifold(object_id):
    """Verifies a mesh object is manifold. A mesh for which every edge is shared
    by at most two faces is called manifold. If a mesh has at least one edge
    that is shared by more than two faces, then that mesh is called non-manifold
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      bool: True if successful, otherwise False.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh", rs.filter.mesh)
      if rs.IsMeshClosed(obj):
          print("The mesh is manifold.")
      else:
          print("The mesh is non-manifold.")
    See Also:
      IsMesh
      IsMeshClosed
    """
    mesh = rhutil.coercemesh(object_id, True)
    rc = mesh.IsManifold(True)
    return rc[0]


def IsPointOnMesh(object_id, point):
    """Verifies a point is on a mesh
    Parameters:
      object_id (guid): identifier of a mesh object
      point (point): test point
    Returns:
      bool: True if successful, otherwise False.
      None: on error.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh")
      if rs.IsMesh(obj):
          point = rs.GetPointOnMesh(strObject, "Pick a test point")
          if point:
              if rs.IsPointOnMesh(obj, point):
                  print("The point is on the mesh")
              else:
                  print("The point is not on the mesh")
    See Also:
      IsMesh
      MeshClosestPoint
    """
    mesh = rhutil.coercemesh(object_id, True)
    point = rhutil.coerce3dpoint(point, True)
    max_distance = Rhino.RhinoMath.SqrtEpsilon
    face, pt = mesh.ClosestPoint(point, max_distance)
    return face>=0


def JoinMeshes(object_ids, delete_input=False):
    """Joins two or or more mesh objects together
    Parameters:
      object_ids ([guid, ...]): identifiers of two or more mesh objects
      delete_input (bool, optional): delete input after joining
    Returns:
      guid: identifier of newly created mesh on success
    Example:
      import rhinoscriptsyntax as rs
      objs = rs.GetObjects("Select meshes to join", rs.filter.mesh)
      if objs and len(objs)>1: rs.JoinMeshes(objs, True)
    See Also:
      JoinCurves
      JoinSurfaces
    """
    meshes = [rhutil.coercemesh(id,True) for id in object_ids]
    joined_mesh = Rhino.Geometry.Mesh()
    joined_mesh.Append(meshes)
    rc = scriptcontext.doc.Objects.AddMesh(joined_mesh)
    if delete_input:
        for id in object_ids:
            guid = rhutil.coerceguid(id)
            scriptcontext.doc.Objects.Delete(guid,True)
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshArea(object_ids):
    """Returns approximate area of one or more mesh objects
    Parameters:
      object_ids ([guid, ...]): identifiers of one or more mesh objects
    Returns:
      list(number, number, number): if successful where
        [0] = number of meshes used in calculation
        [1] = total area of all meshes
        [2] = the error estimate
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      if obj:
          area_rc = rs.MeshArea(obj)
          if area_rc: print("Mesh area:{}".format(area_rc[1]))
    See Also:
      MeshVolume
    """
    id = rhutil.coerceguid(object_ids)
    if id: object_ids = [object_ids]
    meshes_used = 0
    total_area = 0.0
    error_estimate = 0.0
    for id in object_ids:
        mesh = rhutil.coercemesh(id, True)
        if mesh:
            mp = Rhino.Geometry.AreaMassProperties.Compute(mesh)
            if mp:
                meshes_used += 1
                total_area += mp.Area
                error_estimate += mp.AreaError
    if meshes_used==0: return scriptcontext.errorhandler()
    return meshes_used, total_area, error_estimate


def MeshAreaCentroid(object_id):
    """Calculates the area centroid of a mesh object
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      point: representing the area centroid if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      rs.AddPoint( rs.MeshAreaCentroid(obj) )
    See Also:
      IsMesh
      MeshArea
      MeshVolume
      MeshVolumeCentroid
    """
    mesh = rhutil.coercemesh(object_id, True)
    mp = Rhino.Geometry.AreaMassProperties.Compute(mesh)
    if mp is None: return scriptcontext.errorhandler()
    return mp.Centroid


def MeshBooleanDifference(input0, input1, delete_input=True, tolerance=None):
    """Performs boolean difference operation on two sets of input meshes
    Parameters:
      input0, input1 (guid): identifiers of meshes
      delete_input (bool, optional): delete the input meshes
      tolerance (float, optional): this value is ignored. 
          The parameter is only there to keep the function signature the same, 
          The build in tolerenace always is used.
    Returns:
      list(guid, ...): identifiers of newly created meshes
    Example:
      import rhinoscriptsyntax as rs
      input0 = rs.GetObjects("Select first set of meshes", rs.filter.mesh)
      if input0:
          input1 = rs.GetObjects("Select second set of meshes", rs.filter.mesh)
          if input1: rs.MeshBooleanDifference(input0, input1)
    See Also:
      MeshBooleanIntersection
      MeshBooleanSplit
      MeshBooleanUnion
    """
    id = rhutil.coerceguid(input0)
    if id: input0 = [id]
    id = rhutil.coerceguid(input1)
    if id: input1 = [id]
    meshes0 = [rhutil.coercemesh(id, True) for id in input0]
    meshes1 = [rhutil.coercemesh(id, True) for id in input1]
    if not meshes0 or not meshes1: raise ValueError("no meshes to work with")
    newmeshes = Rhino.Geometry.Mesh.CreateBooleanDifference(meshes0, meshes1)
    rc = []
    for mesh in newmeshes:
        id = scriptcontext.doc.Objects.AddMesh(mesh)
        if id!=System.Guid.Empty: rc.append(id)
    if rc and delete_input:
        input = input0 + input1
        for id in input:
            id = rhutil.coerceguid(id, True)
            scriptcontext.doc.Objects.Delete(id, True)
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshBooleanIntersection(input0, input1, delete_input=True):
    """Performs boolean intersection operation on two sets of input meshes
    Parameters:
      input0, input1 (guid): identifiers of meshes
      delete_input (bool, optional): delete the input meshes
    Returns:
      list(guid, ...): identifiers of new meshes on success
    Example:
      import rhinoscriptsyntax as rs
      input0 = rs.GetObjects("Select first set of meshes", rs.filter.mesh)
      if input0:
          input1 = rs.GetObjects("Select second set of meshes", rs.filter.mesh)
          if input1: rs.MeshBooleanIntersection(input0, input1)
    See Also:
      MeshBooleanDifference
      MeshBooleanSplit
      MeshBooleanUnion
    """
    id = rhutil.coerceguid(input0)
    if id: input0 = [id]
    id = rhutil.coerceguid(input1)
    if id: input1 = [id]
    meshes0 = [rhutil.coercemesh(id, True) for id in input0]
    meshes1 = [rhutil.coercemesh(id, True) for id in input1]
    if not meshes0 or not meshes1: raise ValueError("no meshes to work with")
    newmeshes = Rhino.Geometry.Mesh.CreateBooleanIntersection(meshes0, meshes1)
    rc = []
    for mesh in newmeshes:
        id = scriptcontext.doc.Objects.AddMesh(mesh)
        if id!=System.Guid.Empty: rc.append(id)
    if rc and delete_input:
        input = input0 + input1
        for id in input:
            id = rhutil.coerceguid(id, True)
            scriptcontext.doc.Objects.Delete(id, True)
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshBooleanSplit(input0, input1, delete_input=True):
    """Performs boolean split operation on two sets of input meshes
    Parameters:
      input0, input1 (guid): identifiers of meshes
      delete_input (bool, optional): delete the input meshes
    Returns:
      list(guid, ...): identifiers of new meshes on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      input0 = rs.GetObjects("Select first set of meshes", rs.filter.mesh)
      if input0:
          input1 = rs.GetObjects("Select second set of meshes", rs.filter.mesh)
          if input1: rs.MeshBooleanSplit(input0, input1)
    See Also:
      MeshBooleanDifference
      MeshBooleanIntersection
      MeshBooleanUnion
    """
    id = rhutil.coerceguid(input0)
    if id: input0 = [id]
    id = rhutil.coerceguid(input1)
    if id: input1 = [id]
    meshes0 = [rhutil.coercemesh(id, True) for id in input0]
    meshes1 = [rhutil.coercemesh(id, True) for id in input1]
    if not meshes0 or not meshes1: raise ValueError("no meshes to work with")
    newmeshes = Rhino.Geometry.Mesh.CreateBooleanSplit(meshes0, meshes1)
    rc = []
    for mesh in newmeshes:
        id = scriptcontext.doc.Objects.AddMesh(mesh)
        if id!=System.Guid.Empty: rc.append(id)
    if rc and delete_input:
        input = input0 + input1
        for id in input:
            id = rhutil.coerceguid(id, True)
            scriptcontext.doc.Objects.Delete(id, True)
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshBooleanUnion(mesh_ids, delete_input=True):
    """Performs boolean union operation on a set of input meshes
    Parameters:
      mesh_ids ([guid, ...]): identifiers of meshes
      delete_input (bool, optional): delete the input meshes
    Returns:
      list(guid, ...): identifiers of new meshes
    Example:
      import rhinoscriptsyntax as rs
      input = rs.GetObjects("Select meshes to union", rs.filter.mesh)
      if input: rs.MeshBooleanUnion(input)
    See Also:
      MeshBooleanDifference
      MeshBooleanIntersection
      MeshBooleanSplit
    """
    if len(mesh_ids)<2: raise ValueError("mesh_ids must contain at least 2 meshes")
    meshes = [rhutil.coercemesh(id, True) for id in mesh_ids]
    newmeshes = Rhino.Geometry.Mesh.CreateBooleanUnion(meshes)
    rc = []
    for mesh in newmeshes:
        id = scriptcontext.doc.Objects.AddMesh(mesh)
        if id!=System.Guid.Empty: rc.append(id)
    if rc and delete_input:
        for id in mesh_ids:
            id = rhutil.coerceguid(id, True)
            scriptcontext.doc.Objects.Delete(id, True)
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshClosestPoint(object_id, point, maximum_distance=None):
    """Returns the point on a mesh that is closest to a test point
    Parameters:
      object_id (guid): identifier of a mesh object
      point (point): point to test
      maximum_distance (number, optional): upper bound used for closest point calculation.
        If you are only interested in finding a point Q on the mesh when
        point.DistanceTo(Q) < maximum_distance, then set maximum_distance to
        that value
    Returns:
      tuple(point, number): containing the results of the calculation where
                            [0] = the 3-D point on the mesh
                            [1] = the index of the mesh face on which the 3-D point lies
      None: on error
    Example:
      import rhinocriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      point = rs.GetPoint("Pick test point")
      intersect = rs.MeshClosestPoint(obj, point)
      if intersect: rs.AddPoint(intersect)
    See Also:
      MeshFaceCount
      MeshFaces
    """
    mesh = rhutil.coercemesh(object_id, True)
    point = rhutil.coerce3dpoint(point, True)
    tolerance=maximum_distance if maximum_distance else 0.0
    face, closest_point = mesh.ClosestPoint(point, tolerance)
    if face<0: return scriptcontext.errorhandler()
    return closest_point, face


def MeshFaceCenters(mesh_id):
    """Returns the center of each face of the mesh object
    Parameters:
      mesh_id (guid): identifier of a mesh object
    Returns:
      list(point, ...): points defining the center of each face
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      centers = rs.MeshFaceCenters(obj)
      if centers:
          for point in centers: rs.AddPoint(point)
    See Also:
      IsMesh
      MeshFaceCount
      MeshFaces
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    return [mesh.Faces.GetFaceCenter(i) for i in range(mesh.Faces.Count)]


def MeshFaceCount(object_id):
    """Returns total face count of a mesh object
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      number: the number of mesh faces if successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      print("Quad faces:{}".format(rs.MeshQuadCount(obj)))
      print("Triangle faces:{}".format(rs.MeshTriangleCount(obj)))
      print("Total faces:{}".format(rs.MeshFaceCount(obj)))
    See Also:
      IsMesh
      MeshFaces
      MeshVertexCount
      MeshVertices
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.Faces.Count


def MeshFaceNormals(mesh_id):
    """Returns the face unit normal for each face of a mesh object
    Parameters:
      mesh_id (guid): identifier of a mesh object
    Returns:
      list(vector, ...): 3D vectors that define the face unit normals of the mesh
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      normals = rs.MeshFaceNormals(obj)
      if normals:
          for vector in normals: print(vector)
    See Also:
      MeshHasFaceNormals
      MeshFaceCount
      MeshFaces
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    if mesh.FaceNormals.Count != mesh.Faces.Count:
        mesh.FaceNormals.ComputeFaceNormals()
    rc = []
    for i in compat.RANGE(mesh.FaceNormals.Count):
        normal = mesh.FaceNormals[i]
        rc.append(Rhino.Geometry.Vector3d(normal))
    return rc


def MeshFaces(object_id, face_type=True):
    """Returns face vertices of a mesh
    Parameters:
      object_id (guid): identifier of a mesh object
      face_type (bool, optional): The face type to be returned. True = both triangles
        and quads. False = only triangles
    Returns:
      list([point, point, point, point], ...): 3D points that define the face vertices of the mesh. If
      face_type is True, then faces are returned as both quads and triangles
      (4 3D points). For triangles, the third and fourth vertex will be
      identical. If face_type is False, then faces are returned as only
      triangles(3 3D points). Quads will be converted to triangles.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      faces = rs.MeshFaces(obj, False)
      if faces:
          rs.EnableRedraw(False)
          i = 0
          while( i<=len(faces) ):
              face = faces[i], faces[i+1], faces[i+2], faces[i]
              rs.AddPolyline( face )
              i += 3
      rs.EnableRedraw(True)
    See Also:
      IsMesh
      MeshFaceCount
      MeshVertexCount
      MeshVertices
    """
    mesh = rhutil.coercemesh(object_id, True)
    rc = []
    for i in compat.RANGE(mesh.Faces.Count):
        getrc, p0, p1, p2, p3 = mesh.Faces.GetFaceVertices(i)
        p0 = Rhino.Geometry.Point3d(p0)
        p1 = Rhino.Geometry.Point3d(p1)
        p2 = Rhino.Geometry.Point3d(p2)
        p3 = Rhino.Geometry.Point3d(p3)
        rc.append( p0 )
        rc.append( p1 )
        rc.append( p2 )
        if face_type:
            rc.append(p3)
        else:
            if p2!=p3:
                rc.append( p2 )
                rc.append( p3 )
                rc.append( p0 )
    return rc


def MeshFaceVertices(object_id):
    """Returns the vertex indices of all faces of a mesh object
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      list((number, number, number, number), ...): containing tuples of 4 numbers that define the vertex indices for
      each face of the mesh. Both quad and triangle faces are returned. If the
      third and fourth vertex indices are identical, the face is a triangle.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      faceVerts = rs.MeshFaceVertices( obj )
      if faceVerts:
          for count, face in enumerate(faceVerts):
              print("face({}) = ({}, {}, {}, {})".format(count, face[0], face[1], face[2], face[3]))
    See Also:
      IsMesh
      MeshFaceCount
      MeshFaces
    """
    mesh = rhutil.coercemesh(object_id, True)
    rc = []
    for i in compat.RANGE(mesh.Faces.Count):
        face = mesh.Faces.GetFace(i)
        rc.append( (face.A, face.B, face.C, face.D) )
    return rc


def MeshHasFaceNormals(object_id):
    """Verifies a mesh object has face normals
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      bool: True if successful, otherwise False.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh", rs.filter.mesh)
      if rs.MeshHasFaceNormals(obj):
          print("The mesh has face normal.")
      else:
          print("The mesh does not have face normals.")
    See Also:
      MeshFaceNormals
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.FaceNormals.Count>0


def MeshHasTextureCoordinates(object_id):
    """Verifies a mesh object has texture coordinates
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      bool: True if successful, otherwise False.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh", rs.filter.mesh)
      if rs.MeshHasTextureCoordinates(obj):
          print("The mesh has texture coordinates.")
      else:
          print("The mesh does not have texture coordinates.")
    See Also:
      
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.TextureCoordinates.Count>0


def MeshHasVertexColors(object_id):
    """Verifies a mesh object has vertex colors
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      bool: True if successful, otherwise False.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh", rs.filter.mesh)
      if rs.mesh.MeshHasVertexColors(obj):
          print("The mesh has vertex colors.")
      else:
          print("The mesh does not have vertex colors.")
    See Also:
      MeshVertexColors
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.VertexColors.Count>0


def MeshHasVertexNormals(object_id):
    """Verifies a mesh object has vertex normals
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      bool: True if successful, otherwise False.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select a mesh", rs.filter.mesh)
      if rs.MeshHasVertexNormals(obj):
          print("The mesh has vertex normals.")
      else:
          print("The mesh does not have vertex normals.")
    See Also:
      MeshVertexNormals
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.Normals.Count>0


def MeshMeshIntersection(mesh1, mesh2, tolerance=None):
    """Calculates the intersections of a mesh object with another mesh object
    Parameters:
      mesh1, mesh2 (guid): identifiers of meshes
      tolerance (number, optional): the intersection tolerance. Defaults to ModelAbsoluteTolerance * MeshIntersectionsTolerancesCoefficient
    Returns:
      list(point, ...): of points that define the vertices of the intersection curves
    Example:
      import rhinoscriptsyntax as rs
      mesh1 = rs.GetObject("Select first mesh to intersect", rs.filter.mesh)
      mesh2 = rs.GetObject("Select second mesh to intersect", rs.filter.mesh)
      results = rs.MeshMeshIntersection(mesh1, mesh2)
      if results:
          for points in results: rs.AddPolyline(points)
    See Also:
      CurveMeshIntersection
      MeshClosestPoint
    """
    mesh1 = rhutil.coercemesh(mesh1, True)
    mesh2 = rhutil.coercemesh(mesh2, True)
    if tolerance is None:
      tolerance = scriptcontext.doc.ModelAbsoluteTolerance * Rhino.Geometry.Intersect.Intersection.MeshIntersectionsTolerancesCoefficient
    polylines = Rhino.Geometry.Intersect.Intersection.MeshMeshAccurate(mesh1, mesh2, tolerance)
    if polylines: return list(polylines)


def MeshNakedEdgePoints(object_id):
    """Identifies the naked edge points of a mesh object. This function shows
    where mesh vertices are not completely surrounded by faces. Joined
    meshes, such as are made by MeshBox, have naked mesh edge points where
    the sub-meshes are joined
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      list(bool, ...): of boolean values that represent whether or not a mesh vertex is
      naked or not. The number of elements in the list will be equal to
      the value returned by MeshVertexCount. In which case, the list will
      identify the naked status for each vertex returned by MeshVertices
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      vertices = rs.MeshVertices( obj )
      naked = rs.MeshNakedEdgePoints( obj )
      for i, vertex in enumerate(vertices):
          if naked[i]: rs.AddPoint(vertex)
    See Also:
      IsMesh
      MeshVertexCount
      MeshVertices
    """
    mesh = rhutil.coercemesh(object_id, True)
    rc = mesh.GetNakedEdgePointStatus()
    return rc


def MeshOffset(mesh_id, distance):
    """Makes a new mesh with vertices offset at a distance in the opposite
    direction of the existing vertex normals
    Parameters:
      mesh_id (guid): identifier of a mesh object
      distance (number, optional): the distance to offset
    Returns:
      guid: identifier of the new mesh object if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      mesh = rs.GetObject("Select mesh to offset", rs.filter.mesh)
      rs.MeshOffset( mesh, 10.0 )
    See Also:
      IsMesh
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    offsetmesh = mesh.Offset(distance)
    if offsetmesh is None: return scriptcontext.errorhandler()
    rc = scriptcontext.doc.Objects.AddMesh(offsetmesh)
    if rc==System.Guid.Empty: raise Exception("unable to add mesh to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshOutline(object_ids, view=None):
    """Creates polyline curve outlines of mesh objects
    Parameters:
      objects_ids ([guid, ...]): identifiers of meshes to outline
      view (str, optional): view to use for outline direction
    Returns:
      list(guid, ...): polyline curve identifiers on success
    Example:
      import rhinoscriptsyntax as rs
      objs = rs.GetObjects("Select mesh objects to outline", rs.filter.mesh)
      if objs: rs.MeshOutline(objs)
    See Also:
      IsMesh
    """
    viewport = __viewhelper(view).MainViewport
    meshes = []
    mesh = rhutil.coercemesh(object_ids, False)
    if mesh: meshes.append(mesh)
    else: meshes = [rhutil.coercemesh(id,True) for id in object_ids]
    rc = []
    for mesh in meshes:
        polylines = mesh.GetOutlines(viewport)
        if not polylines: continue
        for polyline in polylines:
            id = scriptcontext.doc.Objects.AddPolyline(polyline)
            rc.append(id)
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshQuadCount(object_id):
    """Returns the number of quad faces of a mesh object
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      number: the number of quad mesh faces if successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      print("Quad faces:{}".format(rs.MeshQuadCount(obj)))
      print("Triangle faces:{}".format(rs.MeshTriangleCount(obj)))
      print("Total faces:{}".format(rs.MeshFaceCount(obj)))
    See Also:
      MeshQuadCount
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.Faces.QuadCount


def MeshQuadsToTriangles(object_id):
    """Converts a mesh object's quad faces to triangles
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      bool: True or False indicating success or failure
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      if rs.MeshQuadCount(obj)>0:
          rs.MeshQuadsToTriangles(obj)
    See Also:
      
    """
    mesh = rhutil.coercemesh(object_id, True)
    rc = True
    if mesh.Faces.QuadCount>0:
        rc = mesh.Faces.ConvertQuadsToTriangles()
        if rc:
            id = rhutil.coerceguid(object_id, True)
            scriptcontext.doc.Objects.Replace(id, mesh)
            scriptcontext.doc.Views.Redraw()
    return rc


def MeshToNurb(object_id, trimmed_triangles=True, delete_input=False):
    """Duplicates each polygon in a mesh with a NURBS surface. The resulting
    surfaces are then joined into a polysurface and added to the document
    Parameters:
      object_id (guid): identifier of a mesh object
      trimmed_triangles (bool, optional): if True, triangles in the mesh will be
        represented by a trimmed plane
      delete_input (bool, optional): delete input object
    Returns:
      list(guid, ...): identifiers for the new breps on success
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      if obj: rs.MeshToNurb(obj)
    See Also:
      IsMesh
      MeshFaces
      MeshVertices
    """
    mesh = rhutil.coercemesh(object_id, True)
    pieces = mesh.SplitDisjointPieces()
    breps = [Rhino.Geometry.Brep.CreateFromMesh(piece,trimmed_triangles) for piece in pieces]
    rhobj = rhutil.coercerhinoobject(object_id, True, True)
    attr = rhobj.Attributes
    ids = [scriptcontext.doc.Objects.AddBrep(brep, attr) for brep in breps]
    if delete_input: scriptcontext.doc.Objects.Delete(rhobj, True)
    scriptcontext.doc.Views.Redraw()
    return ids


def MeshTriangleCount(object_id):
    """Returns number of triangular faces of a mesh
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      number: The number of triangular mesh faces if successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      print("Quad faces:{}".format(rs.MeshQuadCount(obj)))
      print("Triangle faces:{}".format(rs.MeshTriangleCount(obj)))
      print("Total faces:{}".format(rs.MeshFaceCount(obj)))
    See Also:
      IsMesh
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.Faces.TriangleCount


def MeshVertexColors(mesh_id, colors=0):
    """Returns of modifies vertex colors of a mesh
    Parameters:
      mesh_id (guid): identifier of a mesh object
      colors 9{color, ...], optional) A list of color values. Note, for each vertex, there must
        be a corresponding vertex color. If the value is None, then any
        existing vertex colors will be removed from the mesh
    Returns:
      color: if colors is not specified, the current vertex colors
      color: if colors is specified, the previous vertex colors
    Example:
      import rhinoscriptsyntax as rs
      import random
       
      def randomcolor():
          r = random.randint(0,255)
          g = random.randint(0,255)
          b = random.randint(0,255)
          return r,g,b
       
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      if obj:
          colors = []
          for i in range(rs.MeshVertexCount(obj)): colors.append( randomcolor() )
          rs.MeshVertexColors( obj, colors )
    See Also:
      MeshHasVertexColors
      MeshVertexCount
      MeshVertices
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    rc = [mesh.VertexColors[i] for i in range(mesh.VertexColors.Count)]
    if colors==0: return rc
    if colors is None:
        mesh.VertexColors.Clear()
    else:
        color_count = len(colors)
        if color_count!=mesh.Vertices.Count:
            raise ValueError("length of colors must match vertex count")
        colors = [rhutil.coercecolor(c) for c in colors]
        mesh.VertexColors.Clear()
        for c in colors: mesh.VertexColors.Add(c)
    id = rhutil.coerceguid(mesh_id, True)
    scriptcontext.doc.Objects.Replace(id, mesh)
    scriptcontext.doc.Views.Redraw()
    return rc


def MeshVertexCount(object_id):
    """Returns the vertex count of a mesh
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      number: The number of mesh vertices if successful.
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      print("Vertex count: {}".format(rs.MeshVertexCount(obj)))
    See Also:
      IsMesh
      MeshFaceCount
      MeshFaces
      MeshVertices
    """
    mesh = rhutil.coercemesh(object_id, True)
    return mesh.Vertices.Count


def MeshVertexFaces(mesh_id, vertex_index):
    """Returns the mesh faces that share a specified mesh vertex
    Parameters:
      mesh_id (guid): identifier of a mesh object
      vertex_index (number): index of the mesh vertex to find faces for
    Returns:
      list(number, ...): face indices on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      import random
      def TestMeshVertexFaces():
          mesh = rs.GetObject("Select mesh", rs.filter.mesh)
          vertices = rs.MeshVertices(mesh)
          meshfaces = rs.MeshFaceVertices(mesh)
          vertex = random.randint(0, len(vertices)-1) #some random vertex
          vertex_faces = rs.MeshVertexFaces(mesh, vertex )
          if vertex_faces:
              rs.AddPoint( vertices[vertex] )
              for face_index in vertex_faces:
                  face = meshfaces[face_index]
                  polyline = []
                  polyline.append( vertices[face[0]] )
                  polyline.append( vertices[face[1]] )
                  polyline.append( vertices[face[2]] )
                  if face[2]!=face[3]:
                      polyline.append( vertices[face[3]] )
                  polyline.append( polyline[0] )
                  rs.AddPolyline(polyline)
       
      TestMeshVertexFaces()
    See Also:
      MeshFaces
      MeshFaceVertices
      MeshVertices
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    return mesh.Vertices.GetVertexFaces(vertex_index)


def MeshVertexNormals(mesh_id):
    """Returns the vertex unit normal for each vertex of a mesh
    Parameters:
      mesh_id (guid): identifier of a mesh object
    Returns:
      list(vector, ...): of vertex normals, (empty list if no normals exist)
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      normals = rs.MeshVertexNormals(obj)
      if normals:
          for normal in normals: print(normal)
    See Also:
      MeshHasVertexNormals
      MeshVertexCount
      MeshVertices
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    count = mesh.Normals.Count
    if count<1: return []
    return [Rhino.Geometry.Vector3d(mesh.Normals[i]) for i in compat.RANGE(count)]


def MeshVertices(object_id):
    """Returns the vertices of a mesh
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      list(point, ...): vertex points in the mesh
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      vertices = rs.MeshVertices(obj)
      if vertices: rs.AddPointCloud(vertices)
    See Also:
      IsMesh
      MeshFaceCount
      MeshFaces
      MeshVertexCount
    """
    mesh = rhutil.coercemesh(object_id, True)
    count = mesh.Vertices.Count
    rc = []
    for i in compat.RANGE(count):
        vertex = mesh.Vertices.Point3dAt(i)
        rc.append(vertex)
    return rc


def MeshVolume(object_ids):
    """Returns the approximate volume of one or more closed meshes
    Parameters:
      object_ids ([guid, ...]): identifiers of one or more mesh objects
    Returns:
      tuple(number, number, number): containing 3 velues if successful where
           [0] = number of meshes used in volume calculation
           [1] = total volume of all meshes
           [2] = the error estimate
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      if obj and rs.IsMeshClosed(obj):
          volume = rs.MeshVolume(obj)
          if volume: print("Mesh volume:{}".format(volume[1]))
    See Also:
      IsMeshClosed
      MeshArea
    """
    id = rhutil.coerceguid(object_ids)
    if id: object_ids = [id]
    meshes_used = 0
    total_volume = 0.0
    error_estimate = 0.0
    for id in object_ids:
        mesh = rhutil.coercemesh(id, True)
        mp = Rhino.Geometry.VolumeMassProperties.Compute(mesh)
        if mp:
            meshes_used += 1
            total_volume += mp.Volume
            error_estimate += mp.VolumeError
    if meshes_used==0: return scriptcontext.errorhandler()
    return meshes_used, total_volume, error_estimate


def MeshVolumeCentroid(object_id):
    """Calculates the volume centroid of a mesh
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      point: Point3d representing the volume centroid
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh )
      centroid = rs.MeshVolumeCentroid(obj)
      rs.AddPoint( centroid )
    See Also:
      IsMesh
      MeshArea
      MeshAreaCentroid
      MeshVolume
    """
    mesh = rhutil.coercemesh(object_id, True)
    mp = Rhino.Geometry.VolumeMassProperties.Compute(mesh)
    if mp: return mp.Centroid
    return scriptcontext.errorhandler()


def PullCurveToMesh(mesh_id, curve_id):
    """Pulls a curve to a mesh. The function makes a polyline approximation of
    the input curve and gets the closest point on the mesh for each point on
    the polyline. Then it "connects the points" to create a polyline on the mesh
    Parameters:
      mesh_id (guid): identifier of mesh that pulls
      curve_id (guid): identifier of curve to pull
    Returns:
      guid: identifier new curve on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      mesh = rs.GetObject("Select mesh that pulls", rs.filter.mesh)
      curve = rs.GetObject("Select curve to pull", rs.filter.curve)
      rs.PullCurveToMesh( mesh, curve )
    See Also:
      IsMesh
    """
    mesh = rhutil.coercemesh(mesh_id, True)
    curve = rhutil.coercecurve(curve_id, -1, True)
    tol = scriptcontext.doc.ModelAbsoluteTolerance
    polyline = curve.PullToMesh(mesh, tol)
    if not polyline: return scriptcontext.errorhandler()
    rc = scriptcontext.doc.Objects.AddCurve(polyline)
    if rc==System.Guid.Empty: raise Exception("unable to add polyline to document")
    scriptcontext.doc.Views.Redraw()
    return rc


def SplitDisjointMesh(object_id, delete_input=False):
    """Splits up a mesh into its unconnected pieces
    Parameters:
      object_id (guid): identifier of a mesh object
      delete_input (bool, optional): delete the input object
    Returns:
      list(guid, ...): identifiers for the new meshes
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      if rs.DisjointMeshCount(obj)>0: rs.SplitDisjointMesh(obj)
    See Also:
      IsMesh
      DisjointMeshCount
    """
    mesh = rhutil.coercemesh(object_id, True)
    pieces = mesh.SplitDisjointPieces()
    rc = [scriptcontext.doc.Objects.AddMesh(piece) for piece in pieces]
    if rc and delete_input:
        id = rhutil.coerceguid(object_id, True)
        scriptcontext.doc.Objects.Delete(id, True)
    scriptcontext.doc.Views.Redraw()
    return rc


def UnifyMeshNormals(object_id):
    """Fixes inconsistencies in the directions of faces of a mesh
    Parameters:
      object_id (guid): identifier of a mesh object
    Returns:
      number: the number of faces that were modified
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select mesh", rs.filter.mesh)
      if rs.IsMesh(obj): rs.UnifyMeshNormals(obj)
    See Also:
      IsMesh
    """
    mesh = rhutil.coercemesh(object_id, True)
    rc = mesh.UnifyNormals()
    if rc>0:
        id = rhutil.coerceguid(object_id, True)
        scriptcontext.doc.Objects.Replace(id, mesh)
        scriptcontext.doc.Views.Redraw()
    return rc

```

--------------------------------------------------------------------------------
/rhino_mcp_server/static/userinterface.py:
--------------------------------------------------------------------------------

```python
import math

import System
import System.Drawing
import System.Windows.Forms

import Eto.Forms

import Rhino
import Rhino.UI

import scriptcontext

import rhinocompat as compat
from rhinoscript import utility as rhutil
from rhinoscript.view import __viewhelper


def BrowseForFolder(folder=None, message=None, title=None):
    """Display browse-for-folder dialog allowing the user to select a folder
    Parameters:
      folder (str, optional): a default folder
      message (str, optional): a prompt or message
      title (str, optional): a dialog box title
    Returns:
      str: selected folder
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      folder = rs.BrowseForFolder("C:\\Program Files\\" )
      if folder: print(folder)
    See Also:
      OpenFileName
      SaveFileName
    """
    dlg = Eto.Forms.SelectFolderDialog()
    if folder:
        if not isinstance(folder, str): folder = str(folder)
        dlg.Directory = folder
    if message:
        if not isinstance(message, str): message = str(message)
        dlg.Title = message
    if title:
        if not isinstance(title, str): title = str(title)
        dlg.Title = title
    if message and title:
        if not isinstance(message, str): message = str(message)
        if not isinstance(title, str): title = str(title)
        dlg.Title = title + ": " + message
    if dlg.ShowDialog(None)==Eto.Forms.DialogResult.Ok:
        return dlg.Directory


def CheckListBox(items, message=None, title=None):
    """Displays a list of items in a checkable-style list dialog box
    Parameters:
      items ([[str, bool], ...]): a list of tuples containing a string and a boolean check state
      message (str, optional):  a prompt or message
      title (str, optional):  a dialog box title
    Returns:
      list((str, bool), ...): of tuples containing the input string in items along with their new boolean check value
      None: on error
    Example:
      import rhinoscriptsyntax as  rs
      layers = rs.LayerNames()
      if layers:
          items  = [(layer, rs.IsLayerOn(layer)) for layer in layers]
          results  = rs.CheckListBox(items, "Turn layers on/off", "Layers")
          if results:
              for  layer, state in results: rs.LayerVisible(layer, state)
    See Also:
      ComboListBox
      ListBox
      MultiListBox
      PropertyListBox
    """
    checkstates = [item[1] for item in items]
    itemstrs = [str(item[0]) for item in items]
    newcheckstates = Rhino.UI.Dialogs.ShowCheckListBox(title, message, itemstrs, checkstates)
    if newcheckstates:
        rc = compat.ITERATOR2LIST(zip(itemstrs, newcheckstates))
        return rc
    return scriptcontext.errorhandler()


def ComboListBox(items, message=None, title=None):
    """Displays a list of items in a combo-style list box dialog.
    Parameters:
      items ([str, ...]): a list of string
      message (str, optional):  a prompt of message
      title (str, optional):  a dialog box title
    Returns:
      str: The selected item if successful
      None: if not successful or on error
    Example:
      import rhinoscriptsyntax as rs
      layers = rs.LayerNames()
      if layers:
          layer = rs.ComboListBox(layers, "Select current layer")
          if layer: rs.CurrentLayer(layer)
    See Also:
      CheckListBox
      ListBox
      MultiListBox
      PropertyListBox
    """
    return Rhino.UI.Dialogs.ShowComboListBox(title, message, items)


def EditBox(default_string=None, message=None, title=None):
    """Display dialog prompting the user to enter a string. The
    string value may span multiple lines
    Parameters:
      default_string  (str, optional):  a default string value.
      message (str, optional): a prompt message.
      title (str, optional): a dialog box title.
    Returns:
      str: Multiple lines that are separated by carriage return-linefeed combinations if successful
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      text = rs.EditBox(message="Enter some text")
      print(text)
    See Also:
      GetString
      StringBox
    """
    rc, text = Rhino.UI.Dialogs.ShowEditBox(title, message, default_string, True)
    return text

def GetAngle(point=None, reference_point=None, default_angle_degrees=0, message=None):
    """Pause for user input of an angle
    Parameters:
      point (point): starting, or base point
      reference_point (point, optional): if specified, the reference angle is calculated
        from it and the base point
      default_angle_degrees (number, optional): a default angle value specified
      message (str, optional): a prompt to display
    Returns:
      number: angle in degree if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      point = rs.GetPoint("Base point")
      if point:
          reference = rs.GetPoint("Reference point", point)
          if reference:
              angle = rs.GetAngle(point, reference)
              if angle!=None: print("Angle:{}".format(angle))
    See Also:
      GetDistance
    """
    point = rhutil.coerce3dpoint(point)
    if not point: point = Rhino.Geometry.Point3d.Unset
    reference_point = rhutil.coerce3dpoint(reference_point)
    if not reference_point: reference_point = Rhino.Geometry.Point3d.Unset
    default_angle = math.radians(default_angle_degrees)
    rc, angle = Rhino.Input.RhinoGet.GetAngle(message, point, reference_point, default_angle)
    if rc==Rhino.Commands.Result.Success: return math.degrees(angle)


def GetBoolean(message, items, defaults):
    """Pauses for user input of one or more boolean values. Boolean values are
    displayed as click-able command line option toggles
    Parameters:
      message (str): a prompt
      items ([str, str, str], ...): list or tuple of options. Each option is a tuple of three strings
        [n][1]    description of the boolean value. Must only consist of letters
                  and numbers. (no characters like space, period, or dash
        [n][2]    string identifying the false value
        [n][3]    string identifying the true value
      defaults ([bool, ...]): list of boolean values used as default or starting values
    Returns:
      list(bool, ...): a list of values that represent the boolean values if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      items = ("Lights", "Off", "On"), ("Cameras", "Disabled", "Enabled"), ("Action", "False", "True")
      results = rs.GetBoolean("Boolean options", items, (True, True, True) )
      if results:
          for val in results: print(val)
    See Also:
      GetString
    """
    go = Rhino.Input.Custom.GetOption()
    go.AcceptNothing(True)
    go.SetCommandPrompt( message )
    if type(defaults) is list or type(defaults) is tuple: pass
    else: defaults = [defaults]
    # special case for single list. Wrap items into a list
    if len(items)==3 and len(defaults)==1: items = [items]
    count = len(items)
    if count<1 or count!=len(defaults): return scriptcontext.errorhandler()
    toggles = []
    for i in compat.RANGE(count):
        initial = defaults[i]
        item = items[i]
        offVal = item[1]
        t = Rhino.Input.Custom.OptionToggle( initial, item[1], item[2] )
        toggles.append(t)
        go.AddOptionToggle(item[0], t)
    while True:
        getrc = go.Get()
        if getrc==Rhino.Input.GetResult.Option: continue
        if getrc!=Rhino.Input.GetResult.Nothing: return None
        break
    return [t.CurrentValue for t in toggles]


def GetBox(mode=0, base_point=None, prompt1=None, prompt2=None, prompt3=None):
    """Pauses for user input of a box
    Parameters:
      mode (number): The box selection mode.
         0 = All modes
         1 = Corner. The base rectangle is created by picking two corner points
         2 = 3-Point. The base rectangle is created by picking three points
         3 = Vertical. The base vertical rectangle is created by picking three points.
         4 = Center. The base rectangle is created by picking a center point and a corner point
      base_point (point, optional): optional 3D base point
      prompt1, prompt2, prompt3 (str, optional): optional prompts to set
    Returns:
      list(point, ...): list of eight Point3d that define the corners of the box on success
      None: is not successful, or on error
    Example:
      import rhinoscriptsyntax as rs
      box = rs.GetBox()
      if box:
          for i, pt in enumerate(box): rs.AddTextDot( i, pt )
    See Also:
      GetRectangle
    """
    base_point = rhutil.coerce3dpoint(base_point)
    if base_point is None: base_point = Rhino.Geometry.Point3d.Unset
    def intToEnum(m):
      if m not in compat.RANGE(1,5):
        m = 0
      return {
        0 : Rhino.Input.GetBoxMode.All,
        1 : Rhino.Input.GetBoxMode.Corner,
        2 : Rhino.Input.GetBoxMode.ThreePoint,
        3 : Rhino.Input.GetBoxMode.Vertical,
        4 : Rhino.Input.GetBoxMode.Center
      }[m]
    rc, box = Rhino.Input.RhinoGet.GetBox(intToEnum(mode), base_point, prompt1, prompt2, prompt3)
    if rc==Rhino.Commands.Result.Success: return tuple(box.GetCorners())


def GetColor(color=[0,0,0]):
    """Display the Rhino color picker dialog allowing the user to select an RGB color
    Parameters:
      color (color, optional): default RGB value. If omitted, the default color is black
    Returns:
      color: RGB tuple of three numbers on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      color = rs.LayerColor("Default")
      rgb = rs.GetColor(color)
      if rgb: rs.LayerColor("Default", rgb)
    See Also:
      
    """
    color = rhutil.coercecolor(color)
    if color is None: color = System.Drawing.Color.Black
    rc, color = Rhino.UI.Dialogs.ShowColorDialog(color)
    if rc: return color.R, color.G, color.B
    return scriptcontext.errorhandler()


def GetCursorPos():
    """Retrieves the cursor's position
    Returns:
      tuple(point, point, guid, point) containing the following information
        [0]  cursor position in world coordinates
        [1]  cursor position in screen coordinates
        [2]  id of the active viewport
        [3]  cursor position in client coordinates
    Example:
      import rhinoscriptsyntax as  rs
      world, screen, view, client  = rs.GetCursorPos()
    See Also:
      XformScreenToWorld
      XformWorldToScreen
    """
    view = scriptcontext.doc.Views.ActiveView
    screen_pt = Rhino.UI.MouseCursor.Location
    client_pt = view.ScreenToClient(screen_pt)
    viewport = view.ActiveViewport
    xf = viewport.GetTransform(Rhino.DocObjects.CoordinateSystem.Screen, Rhino.DocObjects.CoordinateSystem.World)
    world_pt = Rhino.Geometry.Point3d(client_pt.X, client_pt.Y, 0)
    world_pt.Transform(xf)
    return world_pt, screen_pt, viewport.Id, client_pt


def GetDistance(first_pt=None, distance=None, first_pt_msg='First distance point', second_pt_msg='Second distance point'):
    """Pauses for user input of a distance.
    Parameters:
      first_pt (point, optional): First distance point
      distance (number, optional): Default distance
      first_pt_msg (str, optional): Prompt for the first distance point
      second_pt_msg (str, optional): Prompt for the second distance point
    Returns:
      number: The distance between the two points if successful.
      None: if not successful, or on error.
    Example:
      import rhinoscriptsyntax as  rs
      dist = rs.GetDistance()
      if dist:
          print( dist)
    See Also:
      GetAngle
    """
    if distance is not None and first_pt is None: 
        raise Exception("The 'first_pt' parameter needs a value if 'distance' is not None.")
    if distance is not None and not (isinstance(distance, int) or isinstance(distance, float)): return None
    if first_pt_msg is None or not isinstance(first_pt_msg, str): return None
    if second_pt_msg is None or not isinstance(second_pt_msg, str): return None

    if first_pt is not None:
      if first_pt == 0: first_pt = (0,0,0)
      first_pt = rhutil.coerce3dpoint(first_pt)
      if first_pt is None: return None

    if first_pt is None:
      first_pt = GetPoint(first_pt_msg)
      if first_pt is None: return None

    # cannot use GetPoint for 2nd point because of the need do differentiate 
    # between the user accepting none vs cancelling to exactly mimic RhinoScript
    gp = Rhino.Input.Custom.GetPoint()
    if distance is not None:
      gp.AcceptNothing(True)
      second_pt_msg = "{0}<{1}>".format(second_pt_msg, distance)
    gp.SetCommandPrompt(second_pt_msg)
    gp.DrawLineFromPoint(first_pt,True)
    gp.EnableDrawLineFromPoint(True)
    r = gp.Get()
    if r not in [Rhino.Input.GetResult.Cancel, Rhino.Input.GetResult.Point,
      Rhino.Input.GetResult.Nothing]: return scriptcontext.errorHandler()
    if r == Rhino.Input.GetResult.Cancel: return None
    if r == Rhino.Input.GetResult.Point:
      second_pt = gp.Point()
      distance = second_pt.DistanceTo(first_pt)
    gp.Dispose()

    return distance


def GetEdgeCurves(message=None, min_count=1, max_count=0, select=False):
    """Prompt the user to pick one or more surface or polysurface edge curves
    Parameters:
      message  (str, optional):  A prompt or message.
      min_count (number, optional): minimum number of edges to select.
      max_count (number, optional): maximum number of edges to select.
      select (bool, optional): Select the duplicated edge curves.
    Returns:
      list(tuple[guid, point, point], ...): of selection prompts (curve id, parent id, selection point)
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      edges = rs.GetEdgeCurves()
      if edges:
          for edgeinfo in edges:
              print("Curve Id ={}".format(edgeinfo[0]))
              print("Parent Id ={}".format(edgeinfo[1]))
              print("Pick point ={}".format(edgeinfo[2]))
    See Also:
      DuplicateEdgeCurves
    """
    if min_count<0 or (max_count>0 and min_count>max_count): return
    if not message: message = "Select Edges"
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt(message)
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve
    go.GeometryAttributeFilter = Rhino.Input.Custom.GeometryAttributeFilter.EdgeCurve
    go.EnablePreSelect(False, True)
    rc = go.GetMultiple(min_count, max_count)
    if rc!=Rhino.Input.GetResult.Object: return
    rc = []
    for i in compat.RANGE(go.ObjectCount):
        edge = go.Object(i).Edge()
        if not edge: continue
        edge = edge.Duplicate()
        curve_id = scriptcontext.doc.Objects.AddCurve(edge)
        parent_id = go.Object(i).ObjectId
        pt = go.Object(i).SelectionPoint()
        rc.append( (curve_id, parent_id, pt) )
    if select:
        for item in rc:
            rhobj = scriptcontext.doc.Objects.Find(item[0])
            rhobj.Select(True)
        scriptcontext.doc.Views.Redraw()
    return rc        


def GetInteger(message=None, number=None, minimum=None, maximum=None):
    """Pauses for user input of a whole number.
    Parameters:
      message (str, optional): A prompt or message.
      number (number, optional): A default whole number value.
      minimum (number, optional): A minimum allowable value.
      maximum (number, optional): A maximum allowable value.
    Returns:
       number: The whole number input by the user if successful.
       None: if not successful, or on error
    Example:
      import rhinoscriptsyntax as rs
      color = rs.LayerColor("Default")
      color = rs.GetInteger("Enter an RGB color value", color.ToArgb(), 0)
      if color: rs.LayerColor("Default", color)
    See Also:
      
    """
    gi = Rhino.Input.Custom.GetInteger()
    if message: gi.SetCommandPrompt(message)
    if number is not None: gi.SetDefaultInteger(number)
    if minimum is not None: gi.SetLowerLimit(minimum, False)
    if maximum is not None: gi.SetUpperLimit(maximum, False)
    if gi.Get()!=Rhino.Input.GetResult.Number: return scriptcontext.errorhandler()
    rc = gi.Number()
    gi.Dispose()
    return rc


def GetLayer(title="Select Layer", layer=None, show_new_button=False, show_set_current=False):
    """Displays dialog box prompting the user to select a layer
    Parameters:
      title (str, optional): dialog box title
      layer (str, optional): name of a layer to preselect. If omitted, the current layer will be preselected
      show_new_button, show_set_current (bool, optional): Optional buttons to show on the dialog
    Returns:
      str: name of selected layer if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Select object")
      if obj:
          layer = rs.GetLayer("Select Layer", rs.ObjectLayer(obj), True, True)
          if layer: rs.ObjectLayer( obj, layer )
    See Also:
      
    """
    layer_index = scriptcontext.doc.Layers.CurrentLayerIndex
    if layer:
        if "::" in layer:
            idx = scriptcontext.doc.Layers.FindByFullPath(layer,-1)
            if idx != -1: 
                layer_index = idx
            else:
                # layer name could have embedded '::'
                layer_instance = scriptcontext.doc.Layers.FindName(layer)
                if layer_instance is not None: layer_index = layer_instance.Index
        else:
            layer_instance = scriptcontext.doc.Layers.FindName(layer)
            if layer_instance is not None: layer_index = layer_instance.Index
    rc = Rhino.UI.Dialogs.ShowSelectLayerDialog(layer_index, title, show_new_button, show_set_current, True)
    if rc[0]!=True: return None
    layer = scriptcontext.doc.Layers[rc[1]]
    return layer.FullPath


def GetLayers(title="Select Layers", show_new_button=False):
    """Displays a dialog box prompting the user to select one or more layers
    Parameters:
      title (str, optional):  dialog box title
      show_new_button (bool, optional): Optional button to show on the dialog
    Returns:
      str: The names of selected layers if successful
    Example:
      import rhinoscriptsyntax as rs
      layers = rs.GetLayers("Select Layers")
      if layers:
          for layer in layers: print(layer)
    See Also:
      GetLayer
    """
    rc, layer_indices = Rhino.UI.Dialogs.ShowSelectMultipleLayersDialog(None, title, show_new_button)
    if rc:
        return [scriptcontext.doc.Layers[index].FullPath for index in layer_indices]


def GetLine(mode=0, point=None, message1=None, message2=None, message3=None):
    """Prompts the user to pick points that define a line
    Parameters:
      mode (number, optional): line definition mode.
        0  Default - Show all modes, start in two-point mode
        1  Two-point - Defines a line from two points.
        2  Normal - Defines a line normal to a location on a surface.
        3  Angled - Defines a line at a specified angle from a reference line.
        4  Vertical - Defines a line vertical to the construction plane.
        5  Four-point - Defines a line using two points to establish direction and two points to establish length.
        6  Bisector - Defines a line that bisects a specified angle.
        7  Perpendicular - Defines a line perpendicular to or from a curve
        8  Tangent - Defines a line tangent from a curve.
        9  Extension - Defines a line that extends from a curve.
      point (point, optional): optional starting point
      message1, message2, message3 (str, optional): optional prompts
    Returns:
      line: Tuple of two points on success
      None: on error
    Example:
      import rhinoscriptsyntax as  rs
      line = rs.GetLine()
      if line: rs.AddLine( line[0],  line[1] )
    See Also:
      GetBox
      GetPoint
      GetPolyline
      GetRectangle
    """
    gl = Rhino.Input.Custom.GetLine()
    if mode==0: gl.EnableAllVariations(True)
    else: gl.GetLineMode = System.Enum.ToObject( Rhino.Input.Custom.GetLineMode, mode-1 )
    if point:
        point = rhutil.coerce3dpoint(point)
        gl.SetFirstPoint(point)
    if message1: gl.FirstPointPrompt = message1
    if message2: gl.MidPointPrompt = message2
    if message3: gl.SecondPointPrompt = message3
    rc, line = gl.Get()
    if rc==Rhino.Commands.Result.Success: return line.From, line.To


def GetLinetype(default_linetype=None, show_by_layer=False):
    """Displays a dialog box prompting the user to select one linetype
    Parameters:
      default_linetype (str, optional):  Optional. The name of the linetype to select. If omitted, the current linetype will be selected.
      show_by_layer (bool, optional): If True, the "by Layer" linetype will show. Defaults to False.
    Returns:
      str: The names of selected linetype if successful
    Example:
      import rhinoscriptsyntax as rs
      linetype = rs.GetLinetype()
      if linetype: print(linetype)
    See Also:
      GetLayer
    """
    lt_instance = scriptcontext.doc.Linetypes.CurrentLinetype
    if default_linetype:
        lt_new = scriptcontext.doc.Linetypes.FindName(default_linetype)
        if lt_new is not None: lt_instance = lt_new
    id = Rhino.UI.Dialogs.ShowLineTypes("Select Linetype", "", scriptcontext.doc)
    if id == System.Guid.Empty: return None
    linetype = scriptcontext.doc.Linetypes.FindId(id)
    return linetype.Name

def GetMeshFaces(object_id, message="", min_count=1, max_count=0):
    """Prompts the user to pick one or more mesh faces
    Parameters:
      object_id (guid): the mesh object's identifier
      message (str, optional): a prompt of message
      min_count (number, optional): the minimum number of faces to select
      max_count (number, optional): the maximum number of faces to select.
        If 0, the user must press enter to finish selection.
        If -1, selection stops as soon as there are at least min_count faces selected.
    Returns:
      list(number, ...): of mesh face indices on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      mesh = rs.GetObject("Select mesh", rs.filter.mesh)
      if mesh:
          indices = rs.GetMeshFaces(mesh)
          if indices:
              for index in indices: print(index)
    See Also:
      GetMeshVertices
      MeshFaces
      MeshFaceVertices
      MeshVertices
    """
    scriptcontext.doc.Objects.UnselectAll()
    scriptcontext.doc.Views.Redraw()
    object_id = rhutil.coerceguid(object_id, True)
    def FilterById( rhino_object, geometry, component_index ):
        return object_id == rhino_object.Id
    go = Rhino.Input.Custom.GetObject()
    go.SetCustomGeometryFilter(FilterById)
    if message: go.SetCommandPrompt(message)
    go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshFace
    go.AcceptNothing(True)
    if go.GetMultiple(min_count,max_count)!=Rhino.Input.GetResult.Object: return None
    objrefs = go.Objects()
    rc = [item.GeometryComponentIndex.Index for item in objrefs]
    go.Dispose()
    return rc


def GetMeshVertices(object_id, message="", min_count=1, max_count=0):
    """Prompts the user to pick one or more mesh vertices
    Parameters:
      object_id (guid): the mesh object's identifier
      message (str, optional): a prompt of message
      min_count (number, optional): the minimum number of vertices to select
      max_count (number, optional): the maximum number of vertices to select. If 0, the user must
        press enter to finish selection. If -1, selection stops as soon as there
        are at least min_count vertices selected.
    Returns:
      list(number, ...): of mesh vertex indices on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      mesh = rs.GetObject("Select mesh", rs.filter.mesh)
      if mesh:
          indices = rs.GetMeshVertices(mesh)
          if indices:
              for index in indices: print(index)
    See Also:
      GetMeshFaces
      MeshFaces
      MeshFaceVertices
      MeshVertices
    """
    scriptcontext.doc.Objects.UnselectAll()
    scriptcontext.doc.Views.Redraw()
    object_id = rhutil.coerceguid(object_id, True)
    class CustomGetObject(Rhino.Input.Custom.GetObject):
        def CustomGeometryFilter( self, rhino_object, geometry, component_index ):
            return object_id == rhino_object.Id
    go = CustomGetObject()
    if message: go.SetCommandPrompt(message)
    go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshVertex
    go.AcceptNothing(True)
    if go.GetMultiple(min_count,max_count)!=Rhino.Input.GetResult.Object: return None
    objrefs = go.Objects()
    rc = [item.GeometryComponentIndex.Index for item in objrefs]
    go.Dispose()
    return rc


def GetPoint(message=None, base_point=None, distance=None, in_plane=False):
    """Pauses for user input of a point.
    Parameters:
      message (str, optional): A prompt or message.
      base_point (point, optional): list of 3 numbers or Point3d identifying a starting, or base point
      distance  (number, optional): constraining distance. If distance is specified, basePoint must also be specified.
      in_plane (bool, optional): constrains the point selections to the active construction plane.
    Returns:
      point: point on success
      None: if no point picked or user canceled
    Example:
      import rhinoscriptsyntax as rs
      point1 = rs.GetPoint("Pick first point")
      if point1:
          rs.AddPoint(point1)
          point2 = rs.GetPoint("Pick second point", point1)
          if point2:
              rs.AddPoint(point2)
              distance = (point1-point2).Length
              point3 = rs.GetPoint("Pick third point", point2, distance)
              if point3: rs.AddPoint(point3)
    See Also:
      GetPointOnCurve
      GetPointOnSurface
      GetPoints
      GetRectangle
    """
    gp = Rhino.Input.Custom.GetPoint()
    if message: gp.SetCommandPrompt(message)
    base_point = rhutil.coerce3dpoint(base_point)
    if base_point:
        gp.DrawLineFromPoint(base_point,True)
        gp.EnableDrawLineFromPoint(True)
        if distance: gp.ConstrainDistanceFromBasePoint(distance)
    if in_plane: gp.ConstrainToConstructionPlane(True)
    gp.Get()
    if gp.CommandResult()!=Rhino.Commands.Result.Success:
        return scriptcontext.errorhandler()
    pt = gp.Point()
    gp.Dispose()
    return pt


def GetPointOnCurve(curve_id, message=None):
    """Pauses for user input of a point constrainted to a curve object
    Parameters:
      curve_id (guid): identifier of the curve to get a point on
      message (str, optional): a prompt of message
    Returns:
      point: 3d point if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      obj = rs.GetObject("Pick a curve")
      if rs.IsCurve(obj):
          point = rs.GetPointOnCurve(obj, "Point on curve")
          if point: rs.AddPoint(point)
    See Also:
      GetPoint
      GetPointOnMesh
      GetPointOnSurface
      GetPoints
    """
    curve = rhutil.coercecurve(curve_id, -1, True)
    gp = Rhino.Input.Custom.GetPoint()
    if message: gp.SetCommandPrompt(message)
    gp.Constrain(curve, False)
    gp.Get()
    if gp.CommandResult()!=Rhino.Commands.Result.Success:
        return scriptcontext.errorhandler()
    pt = gp.Point()
    gp.Dispose()
    return pt


def GetPointOnMesh(mesh_id, message=None):
    """Pauses for user input of a point constrained to a mesh object
    Parameters:
      mesh_id (guid): identifier of the mesh to get a point on
      message (str, optional): a prompt or message
    Returns:
      point: 3d point if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      mesh = rs.GetObject("Pick a mesh", rs.filter.mesh)
      if mesh:
          point = rs.GetPointOnMesh(mesh, "Point on mesh")
          if point: rs.AddPoint( point )
    See Also:
      GetPoint
      GetPointOnCurve
      GetPointOnSurface
      GetPoints
    """
    mesh_id = rhutil.coerceguid(mesh_id, True)
    if not message: message = "Point"
    cmdrc, point = Rhino.Input.RhinoGet.GetPointOnMesh(mesh_id, message, False)
    if cmdrc==Rhino.Commands.Result.Success: return point


def GetPointOnSurface(surface_id, message=None):
    """Pauses for user input of a point constrained to a surface or polysurface
    object
    Parameters:
      surface_id (guid): identifier of the surface to get a point on
      message (str, optional): a prompt or message
    Returns:
      point: 3d point if successful
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      surface = rs.GetObject("Pick a surface")
      if surface:
          point = rs.GetPointOnSurface(surface, "Point on surface")
          if point: rs.AddPoint(point)
    See Also:
      GetPoint
      GetPointOnCurve
      GetPointOnMesh
      GetPoints
    """
    surfOrBrep = rhutil.coercesurface(surface_id)
    if not surfOrBrep:
        surfOrBrep = rhutil.coercebrep(surface_id, True)
    gp = Rhino.Input.Custom.GetPoint()
    if message: gp.SetCommandPrompt(message)
    if isinstance(surfOrBrep,Rhino.Geometry.Surface):
        gp.Constrain(surfOrBrep,False)
    else:
        gp.Constrain(surfOrBrep, -1, -1, False)
    gp.Get()
    if gp.CommandResult()!=Rhino.Commands.Result.Success:
        return scriptcontext.errorhandler()
    pt = gp.Point()
    gp.Dispose()
    return pt


def GetPoints(draw_lines=False, in_plane=False, message1=None, message2=None, max_points=None, base_point=None):
    """Pauses for user input of one or more points
    Parameters:
      draw_lines (bool, optional): Draw lines between points
      in_plane (bool, optional): Constrain point selection to the active construction plane
      message1 (str, optional): A prompt or message for the first point
      message2 (str, optional): A prompt or message for the next points
      max_points (number, optional): maximum number of points to pick. If not specified, an
                        unlimited number of points can be picked.
      base_point (point, optional): a starting or base point
    Returns:
      list(point, ...): of 3d points if successful
      None: if not successful or on error
    Example:
      import rhinoscriptsyntax as rs
      points = rs.GetPoints(True)
      if points: rs.AddPointCloud(points)
    See Also:
      GetPoint
      GetPointOnCurve
      GetPointOnSurface
      GetRectangle
    """
    gp = Rhino.Input.Custom.GetPoint()
    if message1: gp.SetCommandPrompt(message1)
    gp.EnableDrawLineFromPoint( draw_lines )
    if in_plane:
        gp.ConstrainToConstructionPlane(True)
        plane = scriptcontext.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
        gp.Constrain(plane, False)
    getres = gp.Get()
    if gp.CommandResult()!=Rhino.Commands.Result.Success: return None
    prevPoint = gp.Point()
    rc = [prevPoint]
    if max_points is None or max_points>1:
        current_point = 1
        if message2: gp.SetCommandPrompt(message2)
        def GetPointDynamicDrawFunc( sender, args ):
            if len(rc)>1:
                c = Rhino.ApplicationSettings.AppearanceSettings.FeedbackColor
                args.Display.DrawPolyline(rc, c)
        if draw_lines: gp.DynamicDraw += GetPointDynamicDrawFunc
        while True:
            if max_points and current_point>=max_points: break
            if draw_lines: gp.DrawLineFromPoint(prevPoint, True)
            gp.SetBasePoint(prevPoint, True)
            current_point += 1
            getres = gp.Get()
            if getres==Rhino.Input.GetResult.Cancel: break
            if gp.CommandResult()!=Rhino.Commands.Result.Success: return None
            prevPoint = gp.Point()
            rc.append(prevPoint)
    return rc

def GetPolyline(flags=3, message1=None, message2=None, message3=None, message4=None, min=2, max=0):
  """Prompts the user to pick points that define a polyline.
  Parameters:
    flags (number, optional) The options are bit coded flags. Values can be added together to specify more than one option. The default is 3.
      value description
      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.
      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.
      4     Force close. If specified, then the returned polyline is always closed. If specified, then intMax must be 0 or >= 4.
      Note: the default is 3, or "Permit close option = True", "Permit close snap = True", and "Force close = False".
    message1 (str, optional): A prompt or message for the first point.
    message2 (str, optional): A prompt or message for the second point.
    message3 (str, optional): A prompt or message for the third point.
    message4 (str, optional): A prompt or message for the 'next' point.
    min (number, optional): The minimum number of points to require. The default is 2.
    max (number, optional): The maximum number of points to require; 0 for no limit.  The default is 0.
  Returns:
    list(point, ...): A list of 3-D points that define the polyline if successful.
    None: if not successful or on error
  Example:
    import rhinoscriptsyntax as rs
    from scriptcontext import doc
    arr = rs.GetPolyline()
    if arr is not None:
        doc.AddPolyline(arr)
  See Also:
    GetBox
    GetLine
    GetRectangle
  """
  gpl = Rhino.Input.Custom.GetPolyline()
  if message1: gpl.FirstPointPrompt = message1
  if message2: gpl.SecondPointPrompt = message2
  if message3: gpl.ThirdPointPrompt = message3
  if message4: gpl.FourthPointPrompt = message4
  if min: gpl.MinPointCount = min
  if max: gpl.MaxPointCount = max
  rc, polyline = gpl.Get()
  scriptcontext.doc.Views.Redraw()
  if rc==Rhino.Commands.Result.Success: return polyline
  return None

def GetReal(message="Number", number=None, minimum=None, maximum=None):
    """Pauses for user input of a number.
    Parameters:
      message (str, optional): A prompt or message.
      number (number, optional): A default number value.
      minimum (number, optional): A minimum allowable value.
      maximum (number, optional): A maximum allowable value.
    Returns:
      number: The number input by the user if successful.
      None: if not successful, or on error
    Example:
      import rhinoscriptsyntax as rs
      radius = rs.GetReal("Radius of new circle", 3.14, 1.0)
      if radius: rs.AddCircle( (0,0,0), radius )
    See Also:
      RealBox
    """
    gn = Rhino.Input.Custom.GetNumber()
    if message: gn.SetCommandPrompt(message)
    if number is not None: gn.SetDefaultNumber(number)
    if minimum is not None: gn.SetLowerLimit(minimum, False)
    if maximum is not None: gn.SetUpperLimit(maximum, False)
    if gn.Get()!=Rhino.Input.GetResult.Number: return None
    rc = gn.Number()
    gn.Dispose()
    return rc


def GetRectangle(mode=0, base_point=None, prompt1=None, prompt2=None, prompt3=None):
    """Pauses for user input of a rectangle
    Parameters:
      mode (number, optional): The rectangle selection mode. The modes are as follows
          0 = All modes
          1 = Corner - a rectangle is created by picking two corner points
          2 = 3Point - a rectangle is created by picking three points
          3 = Vertical - a vertical rectangle is created by picking three points
          4 = Center - a rectangle is created by picking a center point and a corner point
      base_point (point, optional): a 3d base point
      prompt1, prompt2, prompt3 (str, optional): optional prompts
    Returns:
      tuple(point, point, point, point): four 3d points that define the corners of the rectangle
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      rect = rs.GetRectangle()
      if rect:
          for i, corner in enumerate(rect):
              rs.AddTextDot( i, corner )
    See Also:
      GetPoint
      GetPoints
    """
    mode = System.Enum.ToObject( Rhino.Input.GetBoxMode, mode )
    base_point = rhutil.coerce3dpoint(base_point)
    if( base_point==None ): base_point = Rhino.Geometry.Point3d.Unset
    prompts = ["", "", ""]
    if prompt1: prompts[0] = prompt1
    if prompt2: prompts[1] = prompt2
    if prompt3: prompts[2] = prompt3
    rc, corners = Rhino.Input.RhinoGet.GetRectangle(mode, base_point, prompts)
    if rc==Rhino.Commands.Result.Success: return corners
    return None


def GetString(message=None, defaultString=None, strings=None):
    """Pauses for user input of a string value
    Parameters:
      message (str, optional): a prompt or message
      defaultString (str, optional): a default value
      strings ([str, ...], optional): list of strings to be displayed as a click-able command options.
                                      Note, strings cannot begin with a numeric character
    Returns:
      str: The string either input or selected by the user if successful.
           If the user presses the Enter key without typing in a string, an empty string "" is returned.
      None: if not successful, on error, or if the user pressed cancel.
    Example:
      import rhinoscriptsyntax as rs
      layer = rs.CurrentLayer()
      layer = rs.GetString("Layer to set current", layer)
      if layer: rs.CurrentLayer(layer)
    See Also:
      GetBoolean
      StringBox
    """
    gs = Rhino.Input.Custom.GetString()
    gs.AcceptNothing(True)
    if message: gs.SetCommandPrompt(message)
    if defaultString: gs.SetDefaultString(defaultString)
    if strings:
        for s in strings: gs.AddOption(s)
    result = gs.Get()
    if result==Rhino.Input.GetResult.Cancel: return None
    if( result == Rhino.Input.GetResult.Option ):
        return gs.Option().EnglishName
    return gs.StringResult()


def ListBox(items, message=None, title=None, default=None):
    """Display a list of items in a list box dialog.
    Parameters:
      items ([str, ...]): a list of values to select
      message (str, optional): a prompt of message
      title (str, optional): a dialog box title
      default (str, optional): selected item in the list
    Returns:
      str: he selected item if successful
      None: if not successful or on error
    Example:
      import rhinoscriptsyntax as rs
      layers = rs.LayerNames()
      if layers:
          result = rs.ListBox(layers, "Layer to set current")
          if result: rs.CurrentLayer( result )
    See Also:
      CheckListBox
      ComboListBox
      MultiListBox
      PropertyListBox
    """
    return Rhino.UI.Dialogs.ShowListBox(title, message, items, default)


def MessageBox(message, buttons=0, title=""):
    """Displays a message box. A message box contains a message and
    title, plus any combination of predefined icons and push buttons.
    Parameters:
      message (str): A prompt or message.
      buttons (number, optional): buttons and icon to display as a bit coded flag. Can be a combination of the
        following flags. If omitted, an OK button and no icon is displayed
        0      Display OK button only.
        1      Display OK and Cancel buttons.
        2      Display Abort, Retry, and Ignore buttons.
        3      Display Yes, No, and Cancel buttons.
        4      Display Yes and No buttons.
        5      Display Retry and Cancel buttons.
        16     Display Critical Message icon.
        32     Display Warning Query icon.
        48     Display Warning Message icon.
        64     Display Information Message icon.
        0      First button is the default.
        256    Second button is the default.
        512    Third button is the default.
        768    Fourth button is the default.
        0      Application modal. The user must respond to the message box
               before continuing work in the current application.
        4096   System modal. The user must respond to the message box
               before continuing work in any application.
      title(str, optional): the dialog box title
    Returns:
      number: indicating which button was clicked:
        1      OK button was clicked.
        2      Cancel button was clicked.
        3      Abort button was clicked.
        4      Retry button was clicked.
        5      Ignore button was clicked.
        6      Yes button was clicked.
        7      No button was clicked.
    Example:
      import rhinoscriptsyntax as rs
      rs.MessageBox("Hello Rhino!")
      rs.MessageBox("Hello Rhino!", 4 | 32)
      rs.MessageBox("Hello Rhino!", 2 | 48)
    See Also:
      
    """
    buttontype = buttons & 0x00000007 #111 in binary
    btn = Rhino.UI.ShowMessageButton.OK
    if buttontype==1: btn = Rhino.UI.ShowMessageButton.OKCancel
    elif buttontype==2: btn = Rhino.UI.ShowMessageButton.AbortRetryIgnore
    elif buttontype==3: btn = Rhino.UI.ShowMessageButton.YesNoCancel
    elif buttontype==4: btn = Rhino.UI.ShowMessageButton.YesNo
    elif buttontype==5: btn = Rhino.UI.ShowMessageButton.RetryCancel
    
    icontype = buttons & 0x00000070
    icon = compat.ENUM_NONE(Rhino.UI.ShowMessageIcon)
    if icontype==16: icon = Rhino.UI.ShowMessageIcon.Error
    elif icontype==32: icon = Rhino.UI.ShowMessageIcon.Question
    elif icontype==48: icon = Rhino.UI.ShowMessageIcon.Warning
    elif icontype==64: icon = Rhino.UI.ShowMessageIcon.Information
    
    ### 15 Sep 2014 Alain - default button not supported in new version of RC 
    ### that isn't tied to Windows.Forms but it probably will so I'm commenting 
    ### the old code instead of deleting it.
    #defbtntype = buttons & 0x00000300
    #defbtn = System.Windows.Forms.MessageDefaultButton.Button1
    #if defbtntype==256:
    #    defbtn = System.Windows.Forms.MessageDefaultButton.Button2
    #elif defbtntype==512:
    #    defbtn = System.Windows.Forms.MessageDefaultButton.Button3

    if not isinstance(message, str): message = str(message)
    dlg_result = Rhino.UI.Dialogs.ShowMessage(message, title, btn, icon)
    if dlg_result==Rhino.UI.ShowMessageResult.OK:     return 1
    if dlg_result==Rhino.UI.ShowMessageResult.Cancel: return 2
    if dlg_result==Rhino.UI.ShowMessageResult.Abort:  return 3
    if dlg_result==Rhino.UI.ShowMessageResult.Retry:  return 4
    if dlg_result==Rhino.UI.ShowMessageResult.Ignore: return 5
    if dlg_result==Rhino.UI.ShowMessageResult.Yes:    return 6
    if dlg_result==Rhino.UI.ShowMessageResult.No:     return 7


def PropertyListBox(items, values, message=None, title=None):
    """Displays list of items and their values in a property-style list box dialog
    Parameters:
      items, values ([str, ...]): list of string items and their corresponding values
      message (str, optional): a prompt or message
      title (str, optional): a dialog box title
    Returns:
      list(str, ..): of new values on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      objs = rs.GetObjects("Select Objects")
      if objs:
          names = []
          for obj in objs:
              name = rs.ObjectName(obj)
              if name is None: name=""
              names.append(name)
          results = rs.PropertyListBox(objs, names, "Modify object name(s)")
          if results:
              for i in compat.RANGE(len(objs)):
                  rs.ObjectName( objs[i], results[i] )
    See Also:
      CheckListBox
      ComboListBox
      ListBox
      MultiListBox
    """
    values = [str(v) for v in values]
    return Rhino.UI.Dialogs.ShowPropertyListBox(title, message, items, values)


def MultiListBox(items, message=None, title=None, defaults=None):
    """Displays a list of items in a multiple-selection list box dialog
    Parameters:
      items ([str, ...]) a zero-based list of string items
      message (str, optional): a prompt or message
      title (str, optional): a dialog box title
      defaults (str|[str,...], optional): either a string representing the pre-selected item in the list
                                          or a list if multiple items are pre-selected
    Returns:
      list(str, ...): containing the selected items if successful
      None: on error
    Example:
      import rhinoscriptsyntax as  rs
      layers = rs.LayerNames()
      if layers:
          layers  = rs.MultiListBox(layers, "Layers to lock")
      if layers:
          for  layer in layers:
              rs.LayerLocked(layer,  True)
    See Also:
      CheckListBox
      ComboListBox
      ListBox
      PropertyListBox
    """
    if isinstance(defaults, str):
      defaults = [defaults]  
    return Rhino.UI.Dialogs.ShowMultiListBox(title, message, items, defaults)


def OpenFileName(title=None, filter=None, folder=None, filename=None, extension=None):
    """Displays file open dialog box allowing the user to enter a file name.
    Note, this function does not open the file.
    Parameters:
      title (str, optional): A dialog box title.
      filter (str, optional): A filter string. The filter must be in the following form:
        "Description1|Filter1|Description2|Filter2||", where "||" terminates filter string.
        If omitted, the filter (*.*) is used.
      folder (str, optional): A default folder.
      filename (str, optional): a default file name
      extension (str, optional): a default file extension
    Returns:
      str: file name is successful
      None: if not successful, or on error
    Example:
      import rhinoscriptsyntax as rs
      filename = rs.OpenFileName()
      if filename: rs.MessageBox(filename)
      filename = rs.OpenFileName("Open", "Text Files (*.txt)|*.txt||")
      if filename: rs.MessageBox(filename)
      filename = rs.OpenFileName("Open", "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||")
      if filename: rs.MessageBox(filename)
    See Also:
      BrowseForFolder
      OpenFileNames
      SaveFileName
    """
    fd = Rhino.UI.OpenFileDialog()
    if title: fd.Title = title
    if filter: fd.Filter = filter
    if folder: fd.InitialDirectory = folder
    if filename: fd.FileName = filename
    if extension: fd.DefaultExt = extension
    if fd.ShowOpenDialog(): return fd.FileName


def OpenFileNames(title=None, filter=None, folder=None, filename=None, extension=None):
    """Displays file open dialog box allowing the user to select one or more file names.
    Note, this function does not open the file.
    Parameters:
      title (str, optional): A dialog box title.
      filter (str, optional): A filter string. The filter must be in the following form:
        "Description1|Filter1|Description2|Filter2||", where "||" terminates filter string.
        If omitted, the filter (*.*) is used.
      folder (str, optional): A default folder.
      filename (str, optional): a default file name
      extension (str, optional): a default file extension
    Returns:
      list(str, ...): of selected file names
    Example:
      import rhinoscriptsyntax as rs
      filenames = rs.OpenFileNames("Open", "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||")
      for filename in filenames: print(filename)
    See Also:
      BrowseForFolder
      OpenFileName
      SaveFileName
    """
    fd = Rhino.UI.OpenFileDialog()
    if title: fd.Title = title
    if filter: fd.Filter = filter
    if folder: fd.InitialDirectory = folder
    if filename: fd.FileName = filename
    if extension: fd.DefaultExt = extension
    fd.MultiSelect = True
    if fd.ShowOpenDialog(): return fd.FileNames
    return []


def PopupMenu(items, modes=None, point=None, view=None):
    """Display a context-style popup menu. The popup menu can appear almost
    anywhere, and can be dismissed by clicking the left or right mouse buttons
    Parameters:
      items ([str, ...]): list of strings representing the menu items. An empty string or None
        will create a separator
      modes ([number, ...]): List of numbers identifying the display modes. If omitted, all
        modes are enabled.
          0 = menu item is enabled
          1 = menu item is disabled
          2 = menu item is checked
          3 = menu item is disabled and checked
      point (point, optional): a 3D point where the menu item will appear. If omitted, the menu
        will appear at the current cursor position
      view (str, optional): if point is specified, the view in which the point is computed.
        If omitted, the active view is used
    Returns:
      number: index of the menu item picked or -1 if no menu item was picked
    Example:
      import rhinoscriptsyntax as rs
      items = "Line", "", "Circle", "Arc"
      modes = 2,0,0,0
      result = rs.PopupMenu(items, modes)
      if result>=0: rs.MessageBox(items[result])
    See Also:
      
    """
    screen_point = System.Windows.Forms.Cursor.Position
    if point:
        point = rhutil.coerce3dpoint(point)
        view = __viewhelper(view)
        viewport = view.ActiveViewport
        point2d = viewport.WorldToClient(point)
        screen_point = viewport.ClientToScreen(point2d)
    return Rhino.UI.Dialogs.ShowContextMenu(items, screen_point, modes);


def RealBox(message="", default_number=None, title="", minimum=None, maximum=None):
    """Display a dialog box prompting the user to enter a number
    Parameters:
      message (str, optional): a prompt message.
      default_number (number, optional):  a default number.
      title (str, optional):  a dialog box title.
      minimum (number, optional):  a minimum allowable value.
      maximum (number, optional):  a maximum allowable value.
    Returns:
      number: The newly entered number on success
      None: on error
    Example:
      import rhinoscriptsyntax as rs
      radius = rs.RealBox("Enter a radius value", 5.0 )
      if radius:
          point = (0,0,0)
          rs.AddCircle( point, radius )
    See Also:
      GetReal
    """
    if default_number is None: default_number = Rhino.RhinoMath.UnsetValue
    if minimum is None: minimum = Rhino.RhinoMath.UnsetValue
    if maximum is None: maximum = Rhino.RhinoMath.UnsetValue
    rc, number = Rhino.UI.Dialogs.ShowNumberBox(title, message, default_number, minimum, maximum)
    if rc: return number


def SaveFileName(title=None, filter=None, folder=None, filename=None, extension=None):
    """Display a save dialog box allowing the user to enter a file name.
    Note, this function does not save the file.
    Parameters:
      title (str, optional): A dialog box title.
      filter(str, optional): A filter string. The filter must be in the following form:
        "Description1|Filter1|Description2|Filter2||", where "||" terminates filter string.
        If omitted, the filter (*.*) is used.
      folder (str, optional): A default folder.
      filename (str, optional): a default file name
      extension (str, optional):  a default file extension
    Returns:
      str: the file name is successful
      None: if not successful, or on error
    Example:
      import rhinoscriptsyntax as rs
      filename = rs.SaveFileName()
      if filename: rs.MessageBox(filename)
      filename = rs.SaveFileName ("Save", "Text Files (*.txt)|*.txt||")
      if filename: rs.MessageBox(filename)
      filename = rrshui.SaveFileName ("Save", "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||")
      if filename: rs.MessageBox(filename)
    See Also:
      BrowseForFolder
      OpenFileName
    """
    fd = Rhino.UI.SaveFileDialog()
    if title: fd.Title = title
    if filter: fd.Filter = filter
    if folder: fd.InitialDirectory = folder
    if filename: fd.FileName = filename
    if extension: fd.DefaultExt = extension
    if fd.ShowSaveDialog(): return fd.FileName


def StringBox(message=None, default_value=None, title=None):
    """Display a dialog box prompting the user to enter a string value.
    Parameters:
      message (str, optional): a prompt message
      default_value (str, optional): a default string value
      title (str, optional): a dialog box title
    Returns:
      str: the newly entered string value if successful
      None: if not successful
    Example:
      import rhinoscriptsyntax as rs
      layer = rs.StringBox("New layer name" )
      if layer: rs.AddLayer( layer )
    See Also:
      GetString
    """
    rc, text = Rhino.UI.Dialogs.ShowEditBox(title, message, default_value, False)
    if rc: return text


def TextOut(message=None, title=None):
    """Display a text dialog box similar to the one used by the _What command.
    Parameters:
      message (str): a message
      title (str, optional): the message title
    Returns:
      None: in any case
    Example:
      import rhinoscriptsyntax as rs
      rs.TextOut("This is a long string..." )
    See Also:
      MessagBox
    """
    Rhino.UI.Dialogs.ShowTextDialog(message, title)

```
Page 4/7FirstPrevNextLast