DupBorder functionality through Rhino Compute or Rhino3dm

Hi,
I am new to the Rhino Compute and Rhino3dm world. I have it set-up and running and I was able to do this Getting Started with compute.rhino3d for Python - YouTube

Big picture - I want to find internal and external boundary of contiguous surfaces (/regions/mesh…). Each surface is planar, but the surfaces are not co-planar with each other.

  1. Creating a surface - cannot find an API call to create a surface given the points and connectivity order.
    I have a list of points and connectivity order and want to make a surface. Each surface is planar, and has 3 or 4 points. I couldn’t find any command in rhino3dm or rhino compute to create a surface from points. I found the commands to make points and circles but couldn’t figure out how to make a surface from points.

  2. I want to merge these surfaces, which I think I can do using this command
    BrepUnion

  3. DupBorder - I can’t find an API call for this.

  4. Differentiate between exterior and interior borders - Is there a command to identify interior vs exterior curves?

Below is an image of what I want to achieve.

I don’t necessarily have to create a surface from the points, so I am open to other suggestions as well.

Any help is much appreciated

Thanks

Here is an example:

SampleCsDuplicateBorder.cs

– Dale

Thanks for sharing the link.
I’m unable to get the union/ join breps. I have tried looking through the forums and documentation but can’t seem to figure out, what I am doing wrong.

Any suggestions?

import rhinoinside
rhinoinside.load()

import Rhino
import System
import Rhino.Geometry

# rhino 3dm import
# from rhino3dm import *
import rhino3dm as r3d
import random
import compute_rhino3d
import compute_rhino3d.Util
import compute_rhino3d.Curve
import compute_rhino3d.Mesh
import compute_rhino3d.Intersection
import compute_rhino3d.Brep

# general pyhthon libs import
import base64
import json
import requests
# import 

# Rhino compute by default launches on port 6500
compute_url = "http://localhost:6500//"

# set the URL
compute_rhino3d.Util.url = compute_url
# no auth token required
compute_rhino3d.Util.authToken = ""

# test, should return version object
version_test = requests.get(compute_url + '/version')
json.loads(version_test.content)

This runs and shows this output
{‘rhino’: ‘7.29.23107.3001’, ‘compute’: ‘1.0.0.0’, ‘git_sha’: None}

I am creating a rectangle and a triangle that share a common edge

# create one reactanble surface
surface1 = Rhino.Geometry.Brep.CreateFromCornerPoints(
    Rhino.Geometry.Point3d(0.0,0.0,0.0), 
    Rhino.Geometry.Point3d(10.0,0.0,0.0),
    Rhino.Geometry.Point3d(10.0,10.0,0.0),
    Rhino.Geometry.Point3d(0.0,10.0,0.0),
    3
    )

# create one triangle surface
surface2 = Rhino.Geometry.Brep.CreateFromCornerPoints(
    Rhino.Geometry.Point3d(10.0,0.0,0.0), 
    Rhino.Geometry.Point3d(10.0,10.0,0.0),
    Rhino.Geometry.Point3d(20.0,0.0,0.0),
    3
    )

Then I’m creating a list

breps = System.Collections.Generic.List[Rhino.Geometry.Brep]()
breps.Add(surface1)
breps.Add(surface2)
breps

Which results in
<System.Collections.Generic.List[Brep] object at 0x000001703F178640>

Now I’m trying to join, but not getting any results
USing RHino Common

joined_brep =Rhino.Geometry.Brep.JoinBreps(breps,3)
joined_brep

<Rhino.Geometry.Brep object at 0x000001703F221600>
or

joined_brep2 = Rhino.Geometry.Brep.CreateBooleanUnion(breps, 3, manifoldOnly=True)
type(joined_brep2)

NoneType

or using compute_3d

compute_rhino3d.Brep.CreateBooleanUnion(breps, 3, multiple=False)

which results in this

TypeError                                 Traceback (most recent call last)
Cell In[84], line 1
----> 1 compute_rhino3d.Brep.CreateBooleanUnion(breps, 3, multiple=False)

File c:\Users\<username>\mambaforge\envs\py031012\lib\site-packages\compute_rhino3d\Brep.py:1488, in CreateBooleanUnion(breps, tolerance, multiple)
   1486 args = [breps, tolerance]
   1487 if multiple: args = list(zip(breps, tolerance))
-> 1488 response = Util.ComputeFetch(url, args)
   1489 response = Util.DecodeToCommonObject(response)
   1490 return response

File c:\Users\<username>\mambaforge\envs\py031012\lib\site-packages\compute_rhino3d\Util.py:28, in ComputeFetch(endpoint, arglist)
     26     else: posturl += '?stopat='
     27     posturl += str(stopat)
---> 28 postdata = json.dumps(arglist, cls=__Rhino3dmEncoder)
     29 headers = { 'User-Agent': 'compute.rhino3d.py/' + __version__ }
     30 if authToken:

File c:\Users\<username>\mambaforge\envs\py031012\lib\json\__init__.py:238, in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    232 if cls is None:
    233     cls = JSONEncoder
    234 return cls(
    235     skipkeys=skipkeys, ensure_ascii=ensure_ascii,
    236     check_circular=check_circular, allow_nan=allow_nan, indent=indent,
...
    178     """
--> 179     raise TypeError(f'Object of type {o.__class__.__name__} '
    180                     f'is not JSON serializable')

TypeError: Object of type List[Brep] is not JSON serializable

@dale - any suggestions?

@dale - I’m still trying to figure this out. Any help is appreciated m!

@AndyPayne - can you have a look at this?

Hi @Aakk . My apologies for the delay. Are you open to using Hops with Rhino.Compute in order to get the results you’re looking for? Or does it have to stay in python? I’m only asking as it changes how the solution is made for what you’re trying to do.

(Reposted it through my account)
@AndyPayne -
I’m open to suggestions.

Big picture of what I am trying to achieve is:
I have files(json/csv/…) with geometry info, that I can read with Rhino/GH or with python libraries. I’m trying to use Rhino/GH libraries as they have a whole bunch of advanced CAD specific tools.

Here are my workflow expectations:

  1. (need) I would want to start the process through cpython so that I can run it on multiple data sources.
  2. (need) As much as I can, I want to keep the data in cpython or get results back into cpython so that I can use other cpython libraries as needed.
  3. (need) There are certain GH packages that I would love to use (ex: lunchbox). So, if I can make a gh script, push data from python and get back results into python, I’ll take it.
    I could keep the data from cpython to be minimal, maybe sending file name to gh script for processing, saving results into another file, and reading that file back in python.
    (wish) Not sure how I would do error handling for this case when I’m sending sequential inputs (ex: one file name after the other)
  4. (wish) At some point I would want to use same geometry across Rhino/GH and libraries such as Open3D to take advantage of CAD functionality and GPU compute scenarios.

Thank you for uploading your AECtech videos to YouTube, that helped me get started with all this.

Ok. I had some time to pull together a simple demo. You’ll need to unzip the attachment below and look at the ReadMe as it has instructions on how to run it… But essentially you’ll need to spin up an instance of rhino.compute. If you have Hops installed, then an instance of rhino.compute should be started automatically whenever you launch Grasshopper. This instance will be listening on http://localhost:6500/.

Then just run the script below (after following the instructions in the ReadMe). This example has a base Rhino file which contains 2 breps (I used similar ones as the ones you showed in your screenshot). It loads up the breps and encodes them as json. Then, it passes that data as an input to a Grasshopper file (FindBorderCurves.gh) and that simply follows the algorithm you posted above (ie. join surfaces and extract the border). Those borders are returned in the response. The python script then decodes the curves it receives back from rhino.compute and writes them out to a separate .3dm file (called ExportedBorders.3dm).

Hopefully this will do what you’re looking for.

import compute_rhino3d.Util
import compute_rhino3d.Grasshopper as gh
import rhino3dm
import json

compute_rhino3d.Util.url = "http://localhost:6500/"
#compute_rhino3d.Util.apiKey = ""

# create list of input trees
srf_tree = gh.DataTree("RH_IN:Surfaces")
# import model with surfaces
inputModel = rhino3dm.File3dm().Read('FindBorderCurves.3dm')

for obj in inputModel.Objects:
    s = json.dumps(obj.Geometry.Encode())
    srf_tree.Append([0], [s])

trees = [srf_tree]
output = gh.EvaluateDefinition('FindBorderCurves.gh', trees)
# print(output)

# decode results
branch = output['values'][0]['InnerTree']['{0;0;0}']
borders = [rhino3dm.CommonObject.Decode(json.loads(item['data'])) for item in branch]

filename = 'ExportedBorders.3dm'

print('Writing {} curves to {}'.format(len(borders), filename))

# create a 3dm file with results
model = rhino3dm.File3dm()
for b in borders:
    model.Objects.AddCurve(b) 

model.Write(filename)

FindBorders.zip (9.9 MB)