Parallel curve between two others

Hi, i try to write code to draw pipe between two others. Now i get two closest connectors and pipes vectors. Here i stuck… I tried to use ComputeClosestPoint to get “midpoints” between connsectors. It doesn’t work. I get error :TypeError: expected StrongBox[IList[ClosestPointsPairBetweenTwoCurves]], got ClosestPointsPairBetweenTwoCurves
This is what i want to draw:

here my code(sorry for mess but i’m still fighting):

# create pipe between and add to closest_connectors list
## get middle point
p1 = closest_connectors.items()[0]
p2 = closest_connectors.items()[1]
vector_p1 = p1[0].Owner.Location.Curve
vector_p2 = p2[0].Owner.Location.Curve
vector_p1_num = vector_p1.GetEndPoint(1) - vector_p1.GetEndPoint(0)
vector_p2_num = vector_p2.GetEndPoint(1) - vector_p2.GetEndPoint(0)
parrarel = vector_p1_num[0]*vector_p2_num[1]-vector_p1_num[1]*vector_p2_num[0]
print("parrarel = {}".format(parrarel))
print("location = {}".format(p1[0].Owner.Location.Curve.Direction))
print(p1[0].Origin[2] - p2[0].Origin[2])
print(parrarel ==0.0)

# ## perpedicular
# p1[0].Origin[0]

# midX_1=(p1[0].Origin[0] + p2[0].Origin[0])/2 # (x1+x2)/2
# midY_1=(p1[0].Origin[1] + p2[0].Origin[1])/2 # (y1+y2)/2
# midZ=p1[0].Origin[2]

# midX_2=midX_1-p2[0].Origin[1]+p1[0].Origin[1] # midX-y2+y1
# midY_2=midY_1+p2[0].Origin[0]-p1[0].Origin[0] # midY + x2-x1

if (p1[0].Origin[2]-p2[0].Origin[2])<0.0000001 and round(parrarel) ==0.0:
    print("Create Pipe!!!")
    point1 = XYZ(midX_1, midY_1, midZ)
    point2 = XYZ(midX_2, midY_2, midZ)
    # vector_p1.ComputeClosestPoints(vector_p2, True, True, True, v) # gett error TypeError: expected StrongBox[IList[ClosestPointsPairBetweenTwoCurves]], got ClosestPointsPairBetweenTwoCurves
    # print(v)
    transaction = Transaction(doc, 'pipe create')
    Plumbing.Pipe.Create(doc, ElementId(592532), ElementId(142438), ElementId(311), point1, point2)

Me being nerdy lazy on a Sunday night.:face_with_monocle::nerd_face:
Will it help? Probably not entirely.

It seems that you are trying to use the ComputeClosestPoints method incorrectly. This method returns an object of type IList[ClosestPointsPairBetweenTwoCurves] which contains information about the closest points between two curves. Therefore, you need to use a list to store the results of this method, like this:

Copy code
v = ListClosestPointsPairBetweenTwoCurves
vector_p1.ComputeClosestPoints(vector_p2, True, True, True, v)

Then, you can access the midpoint of the closest points pair by using the XYZ property of the ClosestPointsPairBetweenTwoCurves object:

Copy code
midpoint1 = v[0].XYZPoint1
midpoint2 = v[0].XYZPoint2

Note that the ComputeClosestPoints method might return more than one closest points pair if the two curves intersect or overlap. In that case, you need to iterate through the list of results to find the midpoint that is closest to the middle point between the two connectors.

Once you have the midpoint coordinates, you can create a pipe element between the two connectors using the Plumbing.Pipe.Create method, like this:

Copy code
pipe = Plumbing.Pipe.Create(doc, ElementId(592532), ElementId(142438), ElementId(311), midpoint1, midpoint2)
where doc is the current document, ElementId(592532) and ElementId(142438) are the ids of the connectors, and ElementId(311) is the id of the pipe type.

I hope this helps! Let me know if you have any further questions.

1 Like

Hah, i work with GPT and “he” give me this solution with Compute closestPoints… but i have problem with create. This is what he suggest:

v = clr.StrongBox[IList[ClosestPointsPairBetweenTwoCurves]]()

I hope this will help, but I’m not sure what your exact requirements are.
I don’t have the ability to test it at the moment, but I know it will work on scenario you presented in your snapshot.
This method has the assumption that the pipes are not sloped, and it should also work with pipes at different elevations.
Edit: Fixed a mistake in the is_parallel boolean.

p1 = closest_connectors.items()[0]
p2 = closest_connectors.items()[1]

# create variable for connector to remove indexing and have more understandable code
p1_connector = p1[0]
p2_connector = p2[0]

# this is the "Direction" of the connector
p1_vector = p1_connector.CoordinateSystem.BasisZ
p2_vector = p2_connector.CoordinateSystem.BasisZ

vector_between_connectors = p1_connector.Origin.Subtract(p2_connector.Origin)

# this will give us the scalar for the projected distance between connectors
# multiply 0.5 to get the midpoint of the distance between the vectors
distance_between_connectors = p2_vector.DotProduct(vector_between_connectors) * 0.5

# now we add the distance to both of the pipes endpoints
p1_point = p1_connector.Origin.Add(p1_vector.Multiply(distance_between_connectors))
p2_point = p2_connector.Origin.Add(p2_vector.Multiply(distance_between_connectors))

is_parallel = round(p1_vector.X * p2_vector.Y - p1_vector.Y * p2_vector.X) == 0.0

# please use attributes for xyz objects instead of indexing
# be explicit with your code. indexing just makes the code harder to read and understand
# I.E. use p1_connector.Origin.Z instead of p1_connector.Origin[2]
if (p1_connector.Origin.Z - p2_connector.Origin.Z) < 0.0000001 and is_parallel:
    print("Create Pipe!!!")

    transaction = Transaction(doc, 'pipe create')
    Plumbing.Pipe.Create(doc, ElementId(592532), ElementId(142438), ElementId(311), p1_point, p2_point)

It’s my fault sorry… i need to pay more attention on “ask more clearly”(to people and AI :stuck_out_tongue: ). I think about it in “math way” and write this code(this work with all direction except horizontal pipe but i will not end this because your code is much more simpler):

# create parallel function 1
## function between two points
x_1 = (y1-y2)/(x1 - x2)
rest_1 = (y1 -(y1 - y2)/(x1-x2)*x1)
## build parallel function
x_1_parallel = -1/x_1
rest_parallel_function = p1[0].Origin[1]-(x_1_parallel)*p1[0].Origin[0]

# create function between two points 2
## function between two points
x_2 = (y1-y2)/(x1 - x2)
rest_2 = (y1 -(y1 - y2)/(x1-x2)*x1)

# get intersection point
point_x = (rest_2-rest_parallel_function)/(x_1_parallel-x_2)
point_y = x_1_parallel*point_x+rest_parallel_function
point_new = XYZ(point_x, point_y, p1[0].Origin[2])

Thank you for help @Nicholas.Miles and @Jean-Marc !!! But i want to ask one more question. There was this problem “StrongBox[IList[ClosestPointsPairBetweenTwoCurves]]”. If i want use this i should create this class???

I don’t see where you defined the StrongBox in either of your posts, so I don’t know how you are doing it. But, if you are using a StrongBox you need to create an instance of it first.

Here’s a simple example using the Intersect Method which works the same way. This should apply to ComputeClosestPoints and other similar methods that require a StrongBox.

import clr
intersection_array = clr.StrongBox[IntersectionResultArray]()
if curve_one.Intersect(curve_two, intersection_array) == SetComparisonResult.Overlap:
    if intersection_array.Size > 1:
      raise ValueError("Multiple Intersections Found")
    intersection = intersection_array.Item[0].XYZPoint
1 Like

Ok now i understand!

for reference:

import clr
from Autodesk.Revit.DB import SetComparisonResult, IntersectionResultArray
from Autodesk.Revit.Exceptions import InvalidOperationException

line1 = Line.CreateBound(XYZ(0,0,0), XYZ(10,0,0))
line2 = Line.CreateBound(XYZ(5,-5,0), XYZ(5,5,0))

results = clr.Reference[IntersectionResultArray]()
result = line1.Intersect(line2, results)

if result != SetComparisonResult.Overlap:
    print('No Intesection')

if results is None or results.Size != 1:
    raise InvalidOperationException("Could not extract line intersection point." )

intersection = results.Item[0]
xyz_point = intersection.XYZPoint
1 Like