Updating coodinates of lines

rhino

#1

Hi,

I have a huge collection of lines in Rhino forming a network. I would like to update their start and end points based on a list of new coordinates for their start and end points. So far I am deleting all line objects and creating new ones with the new coordinates given. All other attributes such as object name and colour should remain the same. However this is rather slow. How can I avoid creating new line objects but only updating their start and end points.

I am using RhinoCommon and python.

Thanks
M


#2

LineCurve has a property “Line” for access to the underlaying Line object. Line has the pleasant properties From and To which would do the trick for you. In C# it would look something like so:

var _linecurve = < your LineCurve >;
_linecurve.Line.From = < new point >; // or ...
_linecurve.Line.From += < offset vector >; // or ...
_linecurve.Line.From.X += < your x offset >; // or ... 
_linecurve.Line.From.Y += < your y offset >; // or ...
_linecurve.Line.From.Z += < your z offset >; // or ...

// And ditto for your end points

_linecurve.Line.To = < new point >; // or ...
_linecurve.Line.To += < offset vector >; // or ...
_linecurve.Line.To.X += < your x offset >; // or ... 
_linecurve.Line.To.Y += < your y offset >; // or ...
_linecurve.Line.To.Z += < your z offset >; // or ...

// Rolf


#3

Hi Rolf,

many thanks for your help. That sounded easy but I am missing a piece of the puzzle. My previous post was not very precise. The first thing I get is actually a bunch of curve objects (simple, straight lines in Rhino). So, my problem is how to “cast” them into LineCurves to make the modifications you suggested. The snipped below gets me all objects from a layer. As curve objects I can ask for their start and end points but how can I modify their start and end points without generating new curve objects??

rh_objs = sc.doc.Objects.FindByLayer(layer)

# global_start = Rhino.Geometry.Point3d(0., 0., 0.)
# global_end = Rhino.Geometry.Point3d(1., 1., 1.)

for rh_obj in rh_objs:
    curve = rh_obj.Geometry

    start = curve.PointAtStart
    end = curve.PointAtEnd

    # -> how to do something like this:  curve.Line.From = global_start 
    # -> how to do something like this:  curve.Line.To = global_end

Any help is very much appreciated. Thanks!


#4

Receive the “straight curves” as Lines instead. If they are Lines in Rhino, then they should come in as “Line” in your “curve” variable. Have you tried accessing the .From and .To properties directly from your curve variable, like so “curve.From” ? (It was you saying that you had “LineCurves” in Rhino… :slight_smile: )

I’m not versed in Python and casting, but it seems to me that if you have Lines in Rhino, then they should come in as Lines in the script as well.

In any case, it is the Line type which has then .From and .To properties.

Documentation: http://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_Line.htm

// Rolf


#5

Hi,

curve.From results in “Message: ‘CurveObject’ object has no attribute ‘From’”. So, I am getting the objects from the layer as curves but I still don’t know how to update their start and end points. To test the *.From / *.To I need to get them as or convert them to LineCurves. Does anyone have any ideas on this? Thanks!

The properties of the objects in Rhino show the following:

curve

ID: 67e2e785-3633-4e6f-91cd-bf6759df49da (375432)
Object name: e_396_280_0
Layer name: Layer 01
Render Material:
source = from layer
index = -1
Attribute UserData:
UserData ID: 563238F9-C201-411d-A7B1-13895A0317AD
Plug-in: Rhino
description: AutoPointsOn
saved in file: no
copy count: 1

Geometry:
Valid curve.
Line
start = (-233.19,217.437,0)
end = (-236.496,217.437,0)
domain = 0 to 3.30628
line length = 3.30628


#6

if they are indeed Lines, then convert them to Lines.

I think you can filter the inputs from the layer, and so safely cast the resulting objects to Lines. Filtering should look something like this:

rs.GetObjects("", rs.filter.line, preselect=True)

See also this thread

// Rolf


#7

… filter the inputs from the layer, and so safely cast the resulting obejcts to Lines…

Unfortunately, I couldn’t figure out how to cast or convert them to lines (within python).

In Rhino they are curves (see properties above) and I don’t think that I can define different curve types in Rhino. The filter option only lists the following options: (points, curves, surfaces, meshes,…) -> see https://discourse-cdn-sjc1.com/mcneel/uploads/default/original/3X/3/9/39a33e8b823803a7a85c838dbb9a18a17a92b006.png


#8

Hm. In an image in the link I posted it looked like there were lines as well. But obviously I was wrong, sorry.

Then I know of nothing else but to create new Line objects based on the curves. But that would be slow if you have many curves.

You should look into C# instead. It’s not too different, only add some “;” to the line ends, and enclose code blocks with “{…}” (instead of indent) and… off you go! :wink:

We should consult @Helvetosaur or @piac or some other expert on Python on this.

Ping on you out there! :slight_smile:

// Rolf


#9

Thanks for your help! I approached it differently using sc.doc.Objects.Replace. Not sure if this is a proper solution but it seems to work :slight_smile:

import Rhino
import rhinoscriptsyntax as rs  
import scriptcontext as sc

line = rs.GetObject("Select Line", rs.filter.curve, preselect=True)

start = Rhino.Geometry.Point3d(0., 0., 0.)
end = Rhino.Geometry.Point3d(1., 1., 0.)
line_rh = Rhino.Geometry.LineCurve(start,end)

sc.doc.Objects.Replace(line,line_rh)
sc.doc.Views.Redraw()