Extending lines

I have a bunch of lines (this may look familiar)…

I want to close the gaps. I have been using Curve.ExtendStart and Curve.ExtendEnd… Then Shatter (thanks to @sovitek)

but I wonder if it’s possible to just extend the lines to intersect instead.

These are the lines I’m using if you want some to play with (but I’d like it to work for any bunch of lines) :slight_smile:

Line(StartPoint = Point(X = -7371.266, Y = 2648.234, Z = 4000.000), EndPoint = Point(X = -196.266, Y = 2648.234, Z = 4000.000), Direction = Vector(X = 7175.000, Y = 0.000, Z = 0.000, Length = 7175.000))
Line(StartPoint = Point(X = -7371.266, Y = -4101.766, Z = 4000.000), EndPoint = Point(X = -7371.266, Y = 2298.234, Z = 4000.000), Direction = Vector(X = 0.000, Y = 6400.000, Z = 0.000, Length = 6400.000))
Line(StartPoint = Point(X = 3678.734, Y = -4101.766, Z = 4000.000), EndPoint = Point(X = -7021.266, Y = -4101.766, Z = 4000.000), Direction = Vector(X = -10700.000, Y = 0.000, Z = 0.000, Length = 10700.000))
Line(StartPoint = Point(X = 3678.734, Y = 4898.234, Z = 4000.000), EndPoint = Point(X = 3678.734, Y = -3751.766, Z = 4000.000), Direction = Vector(X = 0.000, Y = -8650.000, Z = 0.000, Length = 8650.000))
Line(StartPoint = Point(X = 878.734, Y = 2648.234, Z = 4000.000), EndPoint = Point(X = 878.734, Y = -3751.766, Z = 4000.000), Direction = Vector(X = 0.000, Y = -6400.000, Z = 0.000, Length = 6400.000))
Line(StartPoint = Point(X = -546.266, Y = 2648.234, Z = 4000.000), EndPoint = Point(X = -546.266, Y = 5248.234, Z = 4000.000), Direction = Vector(X = 0.000, Y = 2600.000, Z = 0.000, Length = 2600.000))
Line(StartPoint = Point(X = -196.266, Y = 5248.234, Z = 4000.000), EndPoint = Point(X = 3678.734, Y = 5248.234, Z = 4000.000), Direction = Vector(X = 3875.000, Y = 0.000, Z = 0.000, Length = 3875.000))
Line(StartPoint = Point(X = -196.266, Y = 2648.234, Z = 4000.000), EndPoint = Point(X = 528.734, Y = 2648.234, Z = 4000.000), Direction = Vector(X = 725.000, Y = 0.000, Z = 0.000, Length = 725.000))

This is just vector math. You can calculate the intersection of two vectors with a little trig.

It’s probably more work than extending and breaking the curves like you’ve already done, but for a large number of intersections it’s probably computationally lighter.

With two lines yes…
But it’s a bit more complicated with a bunch of them?

Also… I was hoping there was a ready made node :smiley:
#LazinessFTW

Well you’d have to pair them up first, yes. But that’s kind of the whole exercise here: determining which edges create corners and how to join them. You’re doing the same thing with the mass extend/shatter method, it’s just that you’re using the “sledgehammer approach” to brute force all of them and see what sticks. In order to use a more refined approach you need to have more refined data.

How to pair though… That’s the tricky bit?

I mean finding the intersect isn’t hard…

But which intersects to pay attention to, that’s the bit that’s difficult?

Maybe find all intersects of one line… with the others. Then only pick ones that are within X…

But as you said, “the extend thing does probably make more sense”…

All the recent posts have been for fun, it’s good to experiment imo. :slight_smile:

Well, perhaps in true Dynamo fashion… Don’t. Do the trig on each pairing under a certain distance, and take the one with the least added length.

2 Likes

Another option is to do something like the following:

  • For each line startpoint and end-point, get the closest other piece of geometry with “DistanceTo”. This results in each line being attached to two others.
  • Set a threshold of reasonableness, and discard any lines that fall outside of that.
  • Do the trig on these pairs / sub-pairs
2 Likes

I thought about that but some of the lines may be segmented so I wasn’t sure this method would work.

1 Like

Here is an example with Python to extend / join lines (between 2 lines)

join curves

Code Python
import clr
import sys
pyEngineName = sys.implementation.name 
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

def create_extend_lines(ds_lineA, ds_lineB):
    """
    create extend lines by lineA and lineB
    
    Args:
        ds_lineA (Line): input lineA
        ds_lineB (Line): input lineB

    Returns:
        intersectPoint (Point): intersection point between extend lines
        extend_LineA (Line): extend lineA
        extend_LineB (Line): extend lineB
    """
    curveA = ds_lineA.ToRevitType()
    curveB = ds_lineB.ToRevitType()
    curveA.MakeUnbound()
    curveB.MakeUnbound()
    p1, p2, intersectPoint = None, None, None
    extend_LineA = ds_lineA
    extend_LineB = ds_lineB
    #
    if abs(curveA.Direction.CrossProduct(curveB.Direction).Z) > 0.01:
        if pyEngineName == "ironpython":
            outInterR = clr.Reference[DB.IntersectionResultArray]()
            result = curveA.Intersect(curveB, outInterR)
            if result == DB.SetComparisonResult.Overlap:
                interResult = outInterR.Value
                intersectPoint = interResult[0].XYZPoint.ToPoint()
        else:
            dummy_out = DB.IntersectionResultArray()
            result, interResult = curveA.Intersect(curveB, dummy_out)
            if result == DB.SetComparisonResult.Overlap:
                intersectPoint = interResult[0].XYZPoint.ToPoint()
        # make extend Lines
        p1 = ds_lineA.ParameterAtPoint(intersectPoint)
        p2 = ds_lineB.ParameterAtPoint(intersectPoint)
        # if parameter egal to 1 or 0
        if p1 < 0.001 or p1 > 0.999:
            extend_LineA = DS.Line.ByStartPointEndPoint(intersectPoint, ds_lineA.PointAtParameter(1 - p1))
        if p2 < 0.001 or p2 > 0.999:
            extend_LineB = DS.Line.ByStartPointEndPoint(intersectPoint, ds_lineB.PointAtParameter(1 - p2))
            
    return intersectPoint, extend_LineA, extend_LineB

#Preparing input from dynamo to revit
ds_lineA = IN[0]
ds_lineB = IN[1]

OUT = create_extend_lines(ds_lineA, ds_lineB)
2 Likes

But with just 2 lines at a time?

yes, with this example, need to process the lines 2 by 2 (pair) for a set of lines, taking into account the previous lines modified as you go along.

Hi @Alien ,

I wrote a quite simple algoritm which I think solves this. It is quite long though and probably can be optimised/ shortened a bit, but it workes perfect, no matter the amount of curves and intersections.

  1. It first extrudes all curves by 1000 on both sides (can be changed if desired).
  2. It then checks if two curves now overlap and joins them together, but only if their direction & “line” they lie in is exactly the same.
  3. Now every line is intersected with every other line, returning points. These points can be sorted according to their parameter-value on their respecitve curve.
  4. Based on these parameter-values the lowest (start) and highest (end) value is used and matched to the points to create a new curve.


Input Curves
// Line 1
startPoint1 = Point.ByCoordinates(-7371.266, 2648.234, 4000.000);
endPoint1 = Point.ByCoordinates(-196.266, 2648.234, 4000.000);
line1 = Line.ByStartPointEndPoint(startPoint1, endPoint1);

// Line 2
startPoint2 = Point.ByCoordinates(-7371.266, -4101.766, 4000.000);
endPoint2 = Point.ByCoordinates(-7371.266, 2298.234, 4000.000);
line2 = Line.ByStartPointEndPoint(startPoint2, endPoint2);

// Line 3
startPoint3 = Point.ByCoordinates(3678.734, -4101.766, 4000.000);
endPoint3 = Point.ByCoordinates(-7021.266, -4101.766, 4000.000);
line3 = Line.ByStartPointEndPoint(startPoint3, endPoint3);

// Line 4
startPoint4 = Point.ByCoordinates(3678.734, 4898.234, 4000.000);
endPoint4 = Point.ByCoordinates(3678.734, -3751.766, 4000.000);
line4 = Line.ByStartPointEndPoint(startPoint4, endPoint4);

// Line 5
startPoint5 = Point.ByCoordinates(878.734, 2648.234, 4000.000);
endPoint5 = Point.ByCoordinates(878.734, -3751.766, 4000.000);
line5 = Line.ByStartPointEndPoint(startPoint5, endPoint5);

// Line 6
startPoint6 = Point.ByCoordinates(-546.266, 2648.234, 4000.000);
endPoint6 = Point.ByCoordinates(-546.266, 5248.234, 4000.000);
line6 = Line.ByStartPointEndPoint(startPoint6, endPoint6);

// Line 7
startPoint7 = Point.ByCoordinates(-196.266, 5248.234, 4000.000);
endPoint7 = Point.ByCoordinates(3678.734, 5248.234, 4000.000);
line7 = Line.ByStartPointEndPoint(startPoint7, endPoint7);

// Line 8
startPoint8 = Point.ByCoordinates(-196.266, 2648.234, 4000.000);
endPoint8 = Point.ByCoordinates(528.734, 2648.234, 4000.000);
line8 = Line.ByStartPointEndPoint(startPoint8, endPoint8);

// List of all lines
allLines = [line1, line2, line3, line4, line5, line6, line7, line8];

2023-21-11 Extend and Trim Lines by Intersecting Curves.dyn (80.9 KB)

4 Likes