Importing compas_fd to rhino8 ScriptEditor

Hi Tom,

I’m trying to import compas_fd to rhino8 Script editor and since its pip installable I add it to the package requirements in the beginning, like below

#! python3
# r: compas_fd

import compas_fd
from compas_fd.datastructures import CableMesh

but the ScriptEditor freezes and I’m having to kill rhino and restart. (perhaps this is a rhino issue) ?

I want to be able to use compas_fd and compas.dev, would you recommend sticking to rhino7 (so compas_fd will run with compas.rpc?) or use the latest version with viewer?

It is important I visualize the geometry in rhino in the end. Any suggestions might be helpful

Thanks!

hi,

currently, only a subset of compas_fd has been re-released. the CableMesh is not part of that yet (see Constrained Form Finding with Iterative Force Density — COMPAS Force Density). however, you can just use a normal mesh instead and visualize the results in a scene like you would normally do.

from compas.datastructures import Mesh
from compas.geometry import Point, Vector, Line, Sphere, NurbsCurve
from compas_fd.solvers import fd_constrained_numpy
from compas_fd.constraints import Constraint

# mesh

mesh = Mesh.from_meshgrid(dx=10, nx=10)

# vertices, edges

vertices = mesh.vertices_attributes("xyz")
edges = list(mesh.edges())

# fixed vertices

fixed = list(mesh.vertices_where(vertex_degree=2))

# loads

loads = [[0, 0, 0] for _ in range(mesh.number_of_vertices())]

# force densities

q = []
for edge in edges:
    if mesh.is_edge_on_boundary(edge):
        q.append(10)
    else:
        q.append(1.0)

# constraints

arch = NurbsCurve.from_points([[5, 0, 0], [5, 5, 5], [5, 10, 0]])
constraint = Constraint(arch)

constraints = [None] * mesh.number_of_vertices()
for vertex in mesh.vertices_where(x=5):
    constraints[vertex] = constraint
    fixed.append(vertex)

# solve and update

result = fd_constrained_numpy(
    vertices=vertices,
    fixed=fixed,
    edges=edges,
    forcedensities=q,
    loads=loads,
    constraints=constraints,
)

for vertex, attr in mesh.vertices(data=True):
    attr["x"] = result.vertices[vertex, 0]
    attr["y"] = result.vertices[vertex, 1]
    attr["z"] = result.vertices[vertex, 2]

1 Like

i would also use the install instructions available here Working in Rhino 8 — COMPAS instead of the comment based requirements. as far as i know (and at least until recently) using the comment based requirements install the required packages over and over again…

i will update the package further in the coming days and add a tutorial and examples to the docs

thanks! I have a basic question, I found my rhino python executable path, what do I do with it? should I paste it somewhere?

alright, ignore the above. I see that it works if compas is in my machine. thanks!

thanks a lot for the example! another basic question, I have compas_fd installed in an environment. but it does not load in Rhino8, should it be installed in my base environment ?

i think this only works because you had already installed compas using the requirements thing…

just pas the path in the terminal and then add the pip instructions. for example

C:\Users\Uday\.rhinocode\py39-rh8\python.exe -m pip install compas_fd

or if you want to install from local source

cd path/to/compas_fd
C:\Users\Uday\.rhinocode\py39-rh8\python.exe -m pip install -e .
2 Likes

yes this works and now I am able to import compas_fd without loading having it every time with requirements in Script Editor.
test12

thanks for the bonus example. On running your code I do run into an error at the #solve and update part

the error message below:

Traceback (most recent call last):
  File "file:///C:/Users/Uday/OneDrive%20-%20sbp%20SE/Dokumente/coding/test4.py", line 44, in <module>
  File "C:\Users\Uday\.rhinocode\py39-rh8\lib\site-packages\compas_fd\solvers\fd_constrained_numpy.py", line 85, in fd_constrained_numpy
    _update_constraints(numdata, constraints, damping)
  File "C:\Users\Uday\.rhinocode\py39-rh8\lib\site-packages\compas_fd\solvers\fd_constrained_numpy.py", line 129, in _update_constraints
    constraint.location = numdata.xyz[vertex]
  File "C:\Users\Uday\.rhinocode\py39-rh8\lib\site-packages\compas_fd\constraints\curveconstraint.py", line 41, in location
    self.project()
  File "C:\Users\Uday\.rhinocode\py39-rh8\lib\site-packages\compas_fd\constraints\curveconstraint.py", line 59, in project
    xyz, self._param = self.geometry.closest_point(
  File "C:\Users\Uday\.rhinocode\py39-rh8\site-envs\default-KA6C24DI\compas_rhino\geometry\curves\curve.py", line 272, in closest_point
    result, t = self.rhino_curve.ClosestPoint(point_to_r
hino(point))  # type: ignore
AttributeError: 'NoneType' object has no attribute 'ClosestPoint'`Preformatted text`

I printed out Constraints and I see that some items are None where ever the vertex is not to be constrained, my guess it this None is causing the error ? print result below

print(constraints)

[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), CurveConstraint(RhinoNurbsCurve(points=None, weigths=None, knots=None, multiplicities=None, degree=None, is_periodic=None), name=None), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]

OS: Windows10
Rhino: Rhino 8.3.24 commercial version

sorry, should have checked the example in rhino before sending. i guess i haven’t implemented the constraints for Rhino yet. it is not a big deal. just needs to be done. will let you know once it is ready…

thanks! Additionally I also ran your example externally on VScode (with environment set up installing compas 2.0.4 latest stable and latest compas_fd
0.4.2). on line 34,

arch = NurbsCurve.from_points([[5, 0, 0], [5, 5, 5], [5, 10, 0]])

I get the following error:

Exception has occurred: PluginNotInstalledError
exception: no description
  File "C:\Users\Uday\OneDrive - sbp SE\Dokumente\coding\test5.py", line 34, in <module>
    arch = NurbsCurve.from_points([[5, 0, 0], [5, 5, 5], [5, 10, 0]])
compas.plugins.PluginNotInstalledError:

you need to have compas_occ installed for Nurbs support outside of Rhino…

i will work on the fd package later today. if you can add the bugs to the issue tracker (like you did for the Rhino implementation of the constraints) i can go through them one by one…,

hi keerthana,

just wanted to let you know that most problems are resolved.
the screenshot is generated with the following code

from compas.datastructures import Mesh
from compas.geometry import Point, Vector, Line, NurbsCurve
from compas.geometry import Sphere, Cylinder
from compas.scene import Scene
from compas.colors import Color

from compas_fd.solvers import fd_constrained_numpy
from compas_fd.constraints import Constraint

# mesh

mesh = Mesh.from_meshgrid(dx=100, nx=26)

# vertices, edges

vertices = mesh.vertices_attributes("xyz")
edges = list(mesh.edges())

# anchors/supports

supports = list(mesh.vertices_where(vertex_degree=2))
supports += list(mesh.vertices_where(x=50, y=0))
supports += list(mesh.vertices_where(x=50, y=100))

# loads

loads = [[0, 0, 0] for _ in range(mesh.number_of_vertices())]

# force densities

q = []
for edge in edges:
    if mesh.is_edge_on_boundary(edge):
        q.append(30)
    else:
        q.append(1.0)

# constraints

arch = NurbsCurve.from_points([[50, 0, 0], [50, 50, 50], [50, 100, 0]], degree=2)
constraint = Constraint(arch)

constraints = [None] * mesh.number_of_vertices()
constrained = []
for vertex in mesh.vertices_where(x=50):
    if vertex in supports:
        continue
    constraints[vertex] = constraint
    constrained.append(vertex)

# solve and update

result = fd_constrained_numpy(
    vertices=vertices,
    fixed=list(set(supports + constrained)),
    edges=edges,
    forcedensities=q,
    loads=loads,
    constraints=constraints,
)

for vertex, attr in mesh.vertices(data=True):
    attr["x"] = result.vertices[vertex, 0]
    attr["y"] = result.vertices[vertex, 1]
    attr["z"] = result.vertices[vertex, 2]

# visualize

scene = Scene()
scene.clear()

scene.add(mesh, disjoint=True)
scene.add(arch)

for vertex in supports:
    scene.add(mesh.vertex_point(vertex), color=Color.red())

for vertex in supports:
    point = mesh.vertex_point(vertex)
    vector = Vector(*result.residuals[vertex]) * -0.5
    line = Line.from_point_and_vector(point, vector)
    scene.add(line, color=Color.green())

for index, edge in enumerate(mesh.edges()):
    if mesh.is_edge_on_boundary(edge):
        line = mesh.edge_line(edge)
        radius = 0.005 * result.forces[index]
        pipe = Cylinder.from_line_and_radius(line, radius)
        scene.add(pipe, color=Color.red())

scene.draw()

we will release a new version of COMPAS with all of the small updates and a few more additional improvements on Friday (the weekly build)…

2 Likes

thanks a lot Tom! it work for me as well