Trying to understand Mesh CreateFromLines

I have a couple questions about this RhinoCommon function:

public static Mesh CreateFromLines(
Curve[ ] lines,
int maxFaceValence,
double tolerance)

  1. Why lines parameter is of type Curve[ ], and not Line[ ]?
  2. Is maxFaceValance = max number of sides per face?
  3. I assume lines array have to form a closed polyline? If so, why not accept a polyline as input instead of Curve[ ]?
  4. The result can be a non-planar mesh, while Mesh.FromPolyline triangulats if non-planar polyline is passed. Is this the main difference between the 2 functions?
1 Like

@piac, can you help?

Hi Rajaa

I’ll go though your questions one-by-one.

  • There are several types of “Lines” in RhinoCommon, for example a NurbsCurve of degree 1 or a PolylineCurve with one segment. The code is written to just pay attention to starts and ends, thereby not forcing you to accumulate a large array of copies of things that are already in the document when you call this from a command. If you have Rhino.Geometry.Line arrays, then transform these to Rhino.Geometry.LineCurve.
  • The answer is in the function and in the command documentation. “The maximum valence for faces to be probed.”, “Limits the number of sides for each face.”. If you elevate the limit, it is more likely that the algorithm will become slow and it might “get stuck” in faces of higher valence that you did not originally consider.
  • Lines should be disjoint. At any vertex, they can biforcate unlike polylines. You can explode Polylines if you prefer to see it that way. That’s what the function would have to do anyways.
  • I did not find what Mesh.FromPolyline is. Mesh.CreateFromClosedPolyline and the similar Mesh.CreateFromTessellation will triangulate “one face”. This, other other hand, has the goal to construct the mesh from any group of lines that have been extracted from a mesh, recreating something similar to the original mesh. In other words, this will “fill the empty” inside closed line regions.

Does it help?



Giulio Piacentino
for Robert McNeel & Associates

1 Like

Thank you Giulio for your reply. A couple followup comments:

For clarity, I tend to think that the burden is on the caller to pass the geometry that a function can use without much further processing. Indeed I had to transform my lines into curves before passing (only to be changed back into lines inside the function). If have to use curves, the documentation should clarify that only start and end of each Curve will be used.

When I first read the description in the RhinoCommon doc, I did not understand the meaning from this comment. Would be great if can use simpler language. Something like “Maximum number of sides per face” might be more clear (if accurate?).

Good point (I assume tolerance is used to calculate overlapping ends).
My “Polyline” suggestion was to make clear that a “closed” region of Curves is needed for the function to succeed, which I guess can be clarified in the documentation?

You also mention that a Polyline is exploded inside the function? Does that mean if a PolylineCurve is passed as one of the curves in the Curve[ ] (or the only curve), it get exploded and all segments-ends are used? If so, then it should be mentioned in the doc.

Do you mean that the caller does not have to pass exactly “one” closed region, and the function can detect multiple regions to fill? If true, this should be made clear in the function description.

Thanks once again.

That is a design feature missing in RhinoCommon: a common interface for Line and LineCurve. Line and LineCurve have no common method for developers to call inside code that can work interchangeably for both. I need to pick either Curve or Line and, for the sake of speed, the function accepts Curves. If it makes you feel better, we could add an overload of Mesh.CreateFromLines that accepts a Line[], and then converts them to a Curve[]. Maybe there will be a way to fix this in the future, while for now anything will require performance hits. I want the performance hit to be on the Line[] side.

Are you sure that you need this function? It sounds to me like you should be using something else.

Please feel free to add more documentation.

Tolerance is the third parameter…

No, it’s not mentioned because it’s not. This function accepts “lines”. For example, also a ArcCurve with a large radius is considered a line for this function. So is an ArcCurve with a tiny radius. So is any Polyline (be it linear, almost linear, or not linear at all). They just count for their endpoints. It’s the connection of these “lines” that matter, not their exact manifestation.

Do you think a mesh as a single region, or as multiple regions? Did you see the video in the documentation of the corresponding command?

Thanks for your input.

Thank you for the additional comments. I’ll let you update the documentation as you see fit (to avoid any misunderstanding I might have). I made a YT item for you with the ambiguities I found.

I did not see the command video, I was only working with RhinoCommon. Besides, the command might do the region detection before calling the function, so one can’t assume if the function handles multiple regions unless stated.

Thanks once again for clarifying.

Sorry I don’t understand.

This documentation looks good to me. You are free to make additions as you see fit.

Well just because the command takes lines enclosing multiple regions does not necessarily mean that the function can handle it. Without seeing the command code, the detection of enclosed regions from input lines might be happening on command-level, and the function is called multiple times to calculate each region.

I am not adding geometry code to commands. Also, it appears difficult to decide which lines would go with each region.

Yes, the documentation looks fine to me. One thing that is missing is probably a mention of the Rhino command.

So how do I convert a list of curves to Curve[]?

Does mylist.ToArray() help?

Got it :star_struck:

thanks for the hint