Join intersecting straight lines

Hello,
When reading the edges of a solid using the Face EdgeLoops property, some times an edge cam be composed of multiple segments.
I would like to obtain the joined elements as a single curve/line.

Have anyone faced this? As depending on the solid the number of joined lines can vary I am finding it difficult to reconstruct the loops simplifying them.

When I retrieve the solid geometry from a part, for example, them a face from the solid and finally a curve from one of the faces edge the edge can contain more than one line.

how do I join the lines into one single line that would represent the total of the edge?

It may be simple but I am stuck! :smiley:

Thank you!

What have you tried so far? Unless I’m misunderstanding your query, is it not the case of using PolyCurve.ByJoinedCurves to get a closed loop from your selected face edge geometry?

1 Like

Hi Thomas, It is similar, but, in some cases when a connecting part face if divided because that face is shared, the edge ends up being composed of multiple segments. So even by doing that I get that extra intermediate node on a line that should be contiguous but instead is composed of segments.

In my case, my analysis consists of the horizontal lines only, so that simplifies things.

I sorta found a workaround by checking the curves that intersect it other and grouping them and finding the endpoints that do not repeat, and using it to form the contiguous line I was needing if that makes any sense.

Mostly I use Dynamo as a prototyping environment for more complex tools that will be reused by other users. So I did all that using the python node.

Thanks for engaging in the discussion!

Try this.


Merge Collinear in Grouped Curves.dyf (77.5 KB)

1 Like

Thanks Greg indeed the solution I used had a very similar logic.

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
import Autodesk
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
#from Revit import GeometryConversion as gp

import math

curves = IN[0]
#The next 2 methods will assume that the directions is known.
#The start point of a curve
def startPoint(curve):
    return curve.GetEndPoint(0)

#The end point of a curve
def endPoint(curve):
    return curve.GetEndPoint(1)
#Groups lines to be joined in sublists with the curves that have to be joined    
def joinCurves(list):
	comp=[]
	re=[]
	unjoined = []
	for c in curves:
		c = c.ToRevitType()
		match = False
		for co in comp:
			if startPoint(c).IsAlmostEqualTo(startPoint(co)) and endPoint(c).IsAlmostEqualTo(endPoint(co)):
				match = True
		if match:
			continue
		else:
			comp.append(c)			
			joined = []
			for c2 in curves:
				
				match = False
				c2 = c2.ToRevitType()
				for co in comp:
					if startPoint(c2).IsAlmostEqualTo(startPoint(co)) and endPoint(c2).IsAlmostEqualTo(endPoint(co)):
						match = True
				if match:
					continue
				else:
					if c2.Intersect(c) == SetComparisonResult.Disjoint:
						continue
					elif c2.Intersect(c) ==  SetComparisonResult.Equal:
						continue
					elif c2.Intersect(c) == SetComparisonResult.Subset:
						comp.append(c2)
						joined.append(c2.ToProtoType())
		joined.append(c.ToProtoType())
		re.append(joined)
		
	return re
		
result = joinCurves(curves)
def removeIntermediate(list):
	
	pts = []
	corner=[]
	for i in list:
		i= i.ToRevitType()
		pts.append(startPoint(i))
		pts.append(endPoint(i))
	for p in pts:
		counter = 0
		for pi in pts:
			if p.IsAlmostEqualTo(pi):
				counter+=1
		if counter < 2:
			corner.append(p)
	return corner[0], corner[1]
	
	
combined = []
for r in result:
	if isinstance(r, list) and len(r)> 1:
		n = removeIntermediate(r)
		nline = Line.CreateBound(n[0], n[1]).ToProtoType()
		combined.append(nline)
	else:
		try:
			combined.append(r[0])
		except:
			combined.append(r)
			
OUT = combined

The difference is I am filtering the curve-loops differently as I am not using polylines.

1 Like

and i bet yours runs faster! lol

1 Like

Pretty much instant I would say. But the code as you can see still has room for improvement as I was at first much more concerned about finding the solution. Now I will probably work o making it more readable and clean.

Awesome. Would you mind sharing it when you’re done?

I don’t mind at all, but it has a lot to do with remembering, I tend to be forgetful, this is a tiny portion of a much bigger code, so I will probably work on the refactoring much later.

1 Like

Another thing is, I am only using horizontally aligned edges in relation to the base plane of the wall that forms the parts, though this part of the code should work for any orientation, it will join any lines that have a matching pair of endpoints (Curves.GetEndPoint()), so you may have to adjust it for your case regardless of my final code.

When I did this I was finding a clean perimeter of a room. I found that, very rarely, there would be an extra line on top of the boundary that I had to first remove before I could clean up the linework. It probably came from my method of finding the room edges but it was there nonetheless.