Create mesh from intersecting lines and get centerpoints of meshes

Hello!

I am importing some lines from autocad (ceiling plan exported from revit, exploded, and imported back).
I want to determine the centerpoints of all the ceilingtiles.

The data i get in is just a list of lines.

I plan using the script to center my lighting fixtures, fire alarm devices, building automation devices and so forth in the ceiling tiles.

Anyone know a good way to do this without slowing down the program significantly?

1 Like

I created this python script which seems to find the intersections without slowing the script down a crazy amount:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
OUT = []

def line_intersects(p1sp,p1ep,p2sp,p2ep):
	xdiff = (p1sp.X - p1ep.X, p2sp.X - p2ep.X)
	ydiff = (p1sp.Y - p1ep.Y, p2sp.Y - p2ep.Y)
	
	def det(a1,a2,b1,b2):
		return a1 * b2 - a2 * b1
	
	div = det(xdiff[0],xdiff[1],ydiff[0],ydiff[1])
	if div <> 0:
		d = (det(p1sp.X,p1sp.Y,p1ep.X,p1ep.Y), det(p2sp.X,p2sp.Y,p2ep.X,p2ep.Y))
		x = det(d[0],d[1], xdiff[0],xdiff[1]) / div
		y = det(d[0],d[1], ydiff[0],ydiff[1]) / div
		if x > p1sp.X and x < p1ep.X and y > p2sp.Y and y < p2ep.Y:
			OUT.append([x,y])



for l1 in IN[0]:
	p1sp = l1.StartPoint 
	p1ep = l1.EndPoint
	for l2 in IN[0]:
		if l1 <> l2:
			p2sp = l2.StartPoint
			p2ep = l2.EndPoint
			if  p1sp.X < p2sp.X and p1ep.X > p2ep.X  or p1sp.Y > p2sp.Y and p1ep.Y < p2ep.Y:
				line_intersects(p1sp,p1ep,p2sp,p2ep)

The script takes in a flat list of all the lines and check if they intersect. I couldn’t figure out how to make the points in python, so i just output the values and combined them to points. Easy way to implement this to the python script would be appreciated.

How should i progress to find the centerpoints of the tiles?

Import DSCore Nodes and use Point.ByCoordinates.

1 Like
  1. Group points by the X line they are on.
  2. Sort each group by the Y value.
  3. Create paired lists for each index and the following index of each group.
    IE: {{1,2},{2,3},{3,4}…}
  4. Drop the first item from the second list in all cases (the lowest Y value) and the list item from each item in the first list (the highest Y value).
  5. Draw a line between each (longest lacing), and draw a line between the matching indexes of each list (index 0 to index 0). They should be diagonal lines across each tile except the end tiles (where you likely don’t want fixtures anyway).
  6. Use a point at parameter to find the midpoint of each of the new diagonal lines.
1 Like

Thanks for your response, this seems like a good way of going about it.
As you can probably see from the code, I am not very experienced with Python. I have just recently started learning it-
So how do I go forth grouping points by the X line, and pair list for indexes like you said in 3. ?

As of now my code is:

import clr
clr.AddReference('ProtoGeometry')
clr.AddReference('DSCoreNodes') 
import DSCore
from DSCore import *
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
data = []
OUT = []

def line_intersects(p1sp,p1ep,p2sp,p2ep):
	xdiff = (p1sp.X - p1ep.X, p2sp.X - p2ep.X)
	ydiff = (p1sp.Y - p1ep.Y, p2sp.Y - p2ep.Y)
	
	def det(a1,a2,b1,b2):
		return a1 * b2 - a2 * b1
	
	div = det(xdiff[0],xdiff[1],ydiff[0],ydiff[1])
	if div <> 0:
		d = (det(p1sp.X,p1sp.Y,p1ep.X,p1ep.Y), det(p2sp.X,p2sp.Y,p2ep.X,p2ep.Y))
		x = det(d[0],d[1], xdiff[0],xdiff[1]) / div
		y = det(d[0],d[1], ydiff[0],ydiff[1]) / div
		if x > p1sp.X and x < p1ep.X and y > p2sp.Y and y < p2ep.Y:
			OUT.append(Point.ByCoordinates(x,y))
			


for l1 in IN[0]:
	p1sp = l1.StartPoint 
	p1ep = l1.EndPoint
	for l2 in IN[0]:
		if l1 <> l2:
			p2sp = l2.StartPoint
			p2ep = l2.EndPoint
			if  p1sp.X < p2sp.X and p1ep.X > p2ep.X  or p1sp.Y > p2sp.Y and p1ep.Y < p2ep.Y:
				line_intersects(p1sp,p1ep,p2sp,p2ep)

The graph looks as simple as this for now:

I’m not a python guru, but I can design script and node most things to death. If I have the time before my train home tonight I’ll have a look.

Here are my files so far.
As far as I can tell, the actual Ceiling elements is not needed for the graph to work, so only the dwg and graph are attached:

TESTPROJECT - Reflected Ceiling Plan - Plan 01.dwg (153.5 KB)

HOMEMADE_AlignFixturesinCeilingGrid.dyn (28.1 KB)

Don’t miss your train ride over this though :slight_smile:

I have still not had any further progression on this. Any suggestions?

well… if u want the midpoint of a polygon u can calculate the average point of the polygonpoint.
So u need all points of one mesh and calculate the average.

Hope this helps

Thank you for your response.

I am not sure if i am missing something, but:
I only have a list of points, containing all the points shown in the picture in the posts above. I am not sure how to progress to collect and connect the correct sets of points to create a mesh, or a shape for each grid.

I did some testing and got something which almost worked, but had a flaw. Would have posted earlier but had to run to the train and forgot about it in the days that followed.

First I got the direction from each line, and adjusted t so they were all in the +Y quadrants (some were flipped when in autocad). I then grouped each line by the vector, then grouped again by the X value for the start point, then sorted by the Y value of the same point. I then intersected them all with each other to get the points. This produced a series of points which were grouped by common axis line, and orted by their distance from the endpoint.

I finally offset by 1/2 of the distance between points (half a tiles short direction), and then 1/2 the distance along the Y+ vector rotated -90 degrees and the next line extended infinitely (to allow for oddly shaped rooms like circles). This was more accurate than the diagonal as the diagonal produced odd results on end tiles, and the math was simple enough so I let it ride.

The method works on any single grouping of the lines but I was concerned (and verified the issue) with large groupings of lines where differing grids may overlap oddly (I.E. two rooms with the start point off by a fraction of a tile). So I’m now left wondering how to group each pair of lines with each other, or going back to the drawing board and starting another method.

I’ll try to remember to upload the DYN tonight but am out of the office for a good while today.

1 Like

Wow, this sounds promising :slight_smile: maybe we can be able to group the lines by intersection with the ceiling element?

That was my first thought but I would need a matching Revit file to test. :slight_smile:

1 Like

The last update i did on the python script was to group the points per line.
They are grouped in order, but it seems to be ordered from right to left.

(the random points you see are just lighting fixtures)

2017-08-22_07-52-58

New Python Code:

import clr
clr.AddReference('ProtoGeometry')
clr.AddReference('DSCoreNodes') 
import DSCore
from DSCore import *
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
OUT = []

def line_intersects(p1sp,p1ep,p2sp,p2ep):
	xdiff = (p1sp.X - p1ep.X, p2sp.X - p2ep.X)
	ydiff = (p1sp.Y - p1ep.Y, p2sp.Y - p2ep.Y)
	
	def det(a1,a2,b1,b2):
		return a1 * b2 - a2 * b1
	
	div = det(xdiff[0],xdiff[1],ydiff[0],ydiff[1])
	if div <> 0:
		d = (det(p1sp.X,p1sp.Y,p1ep.X,p1ep.Y), det(p2sp.X,p2sp.Y,p2ep.X,p2ep.Y))
		x = det(d[0],d[1], xdiff[0],xdiff[1]) / div
		y = det(d[0],d[1], ydiff[0],ydiff[1]) / div
		if x > p1sp.X and x < p1ep.X and y > p2sp.Y and y < p2ep.Y:
			return Point.ByCoordinates(x,y)
			
for l1 in IN[0]:
	p1sp = l1.StartPoint 
	p1ep = l1.EndPoint
	data = []
	for l2 in IN[0]:
		if l1 <> l2:
			p2sp = l2.StartPoint
			p2ep = l2.EndPoint
			if  p1sp.X < p2sp.X and p1ep.X > p2ep.X  or p1sp.Y > p2sp.Y and p1ep.Y < p2ep.Y:
				if not (line_intersects(p1sp,p1ep,p2sp,p2ep) is None):
					data.append(line_intersects(p1sp,p1ep,p2sp,p2ep))
	if data.Count > 0:
		OUT.append(data)
1 Like

Hello JacobSmall.

Do you still have the .DYN file?
I am unable to recreate the script the way you said you solved it, and I would love to fiddle around with your solution :sweat_smile:

Thanks in advance

Any update on this?
I used your code but it didn’t work and some of it needed to be updated. I’m sure its pretty close but I can seem to get any points.

RVT 2016 but you can update it if you want:
Lines Test.rvt (312 KB)

Dynamo 1.3.2 but again feel free to update:
GetIntersectionPoints.dyn (5.0 KB)

Edit: Is this relevant enough? Should I just make a new topic?