Check if Reference Planes are Coincident

Hi All,

Just a quick one (I hope) as this has stumped me this morning.
I need to find out if two Planes are coincident (are aligned, but do not necessarily share a common vector or origin)

Comparing angles of the Plane Normals won’t work as there may be planes with the same vector, but are not coincident (dont overlap).
Any thoughts are appreciated? :grinning:

1 Like

so you want to find out if two planes both lie in the same plane?

can’t you take any point on one plane and test if it lies on the second plane?

1 Like

@Michael_Kirschner2 - not necessarily. Perpendicular planes have overlap. Test the angle between normals first. That will remove the most planes fastest. Then test origin point distance between each.

@jacob.small the likelyhood that the origin for overlapping perpedicular planes to have their origin in the same location is quite low is it not?

The Planes I am attempting to “match” may have vectors 180 degrees apart but exist in the “same plane” so capturing this is easy enough by looking for a 0 and 180 value.

@Michael_Kirschner2 good point, Ill test using the plane origin as the point to compare once I have filtered by vector.

Thanks for the help, will update soon.

@jacob.small @Michael_Kirschner2 Thanks, all sorted. :grinning:

3 Likes

@Ewan_Opie,

Do you mind sharng a ‘readable’ version of your graph (the part where you check parralells)? Curious how you did it. Thanks!

Weird, that image was taken with the dynamo camera function, so should be full resolution when selected, but I can’t even select it in the post. I’ll capture it tmw full res, and post the dyn. (Will be a node in my next release) :grinning:

I believe if you zoom in so that the graph is legible, then use the camera feature it’s fine (And will capture the entire graph!)

Will do @solamour I’ve just downloaded that image from the post and it’s clear as day, so it is full size…:thinking: will still look at when in the office tmw.

Forum isn’t letting me click to see larger on any images.

@Racel did something change?

@Ewan_Opie, @jacob.small,

Things are clickable again (and readable!), thanks.

2 Likes

I needed this today…
Here’s a quick python implementation for it, someone will need it someday

# Enable Python support and load DesignScript library
# IMPORTANT : ALL DYNAMO DESIGN SCRIPT NODES ARE AS (dg)
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript import Geometry as dg
from itertools import groupby

planes=UnwrapElement(IN[0])

planes = list(set(planes))

def flatten(x):
    result = []
    for el in x:
        if hasattr(el, "__iter__") and not isinstance(el, basestring):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

norms = []
wantedplanes = []
for p in planes:
	norms.append(p.Normal)
	
closest = []
bigcount = 0
for n in norms:
	bigplane = planes[bigcount]
	bigcount += 1
	tmp = []
	tmp_plane = []
	tmp_close = []
	smallcount = 0
	for n2 in norms:
		smallplane = planes[smallcount]
		angle = round(dg.Vector.AngleWithVector(n,n2),2)
		if angle == 0 or angle == 180:
			tmp.append(True)
			smallorigin = smallplane.Origin
			tmp_close.append(smallorigin)
			tmp_plane.append(smallplane)
		smallcount += 1
	if tmp.count(True) != 0 and len(tmp) != 0:
		wantedplanes.append(tmp_plane)
		closest.append(tmp_close)

wantedplanesclean = []
for x in wantedplanes:
    if x not in wantedplanesclean:
        wantedplanesclean.append(x)
wantedplanesclean = (wantedplanesclean)

closestclean = []
for x in closest:
    if x not in closestclean:
        closestclean.append(x)
closestclean = (closestclean)

goodstuff = []
problems = []
count = 0
for plist in wantedplanesclean:
	ptmp = []
	gtmp = []
	for pl in plist:
		clist = closestclean[count]
		yesorno = []
		for c in clist:
			bestpoint = dg.Geometry.ClosestPointTo(pl,c)
			yesorno.append(dg.Geometry.IsAlmostEqualTo(c,bestpoint))
		if yesorno.count(True) != 1:
			ptmp.append(pl)
		else:
			gtmp.append(pl)
	if len(ptmp) != 0:
		problems.append(ptmp)
	if len(gtmp) != 0:
		goodstuff.append(gtmp)
	count += 1

OUT = problems

Even a further one to actually get unique planes:

# Enable Python support and load DesignScript library
# IMPORTANT : ALL DYNAMO DESIGN SCRIPT NODES ARE AS (dg)
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript import Geometry as dg
from itertools import groupby

from collections import defaultdict

planes=UnwrapElement(IN[0])

planes = list(set(planes))

def flatten(x):
    result = []
    for el in x:
        if hasattr(el, "__iter__") and not isinstance(el, basestring):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

norms = []
wantedplanes = []
for p in planes:
	norms.append(p.Normal)
	
closest = []
bigcount = 0
for n in norms:
	bigplane = planes[bigcount]
	bigcount += 1
	tmp = []
	tmp_plane = []
	tmp_close = []
	smallcount = 0
	for n2 in norms:
		smallplane = planes[smallcount]
		angle = round(dg.Vector.AngleWithVector(n,n2),2)
		if angle == 0 or angle == 180:
			tmp.append(True)
			smallorigin = smallplane.Origin
			tmp_close.append(smallorigin)
			tmp_plane.append(smallplane)
		smallcount += 1
	if tmp.count(True) != 0 and len(tmp) != 0:
		wantedplanes.append(tmp_plane)
		closest.append(tmp_close)

wantedplanesclean = []
for x in wantedplanes:
    if x not in wantedplanesclean:
        wantedplanesclean.append(x)
wantedplanesclean = (wantedplanesclean)

closestclean = []
for x in closest:
    if x not in closestclean:
        closestclean.append(x)
closestclean = (closestclean)

goodstuff = []
problems = []
count = 0
for plist in wantedplanesclean:
	ptmp = []
	gtmp = []
	for pl in plist:
		clist = closestclean[count]
		yesorno = []
		for c in clist:
			bestpoint = dg.Geometry.ClosestPointTo(pl,c)
			yesorno.append(dg.Geometry.IsAlmostEqualTo(c,bestpoint))
		if yesorno.count(True) != 1:
			ptmp.append(pl)
		else:
			gtmp.append(pl)
	if len(ptmp) != 0:
		problems.append(ptmp)
	if len(gtmp) != 0:
		goodstuff.append(gtmp)
	count += 1

# take X for sort
def takeX(plane):
    return plane.Origin.X

intersects = []
for plist in problems:
	tmpall = []
	for p in plist:
		tmp = []
		excluded = []
		for p2 in plist:
			if dg.Geometry.DoesIntersect(p,p2) and p != p2:
				tmp.append([p,p2])
		flattened = list(set(flatten(tmp)))
		sortme = sorted(flattened, key=takeX)
		if len(sortme) != 0:
			tmpall.append(sortme)
	grouped_things = defaultdict(list)
	if len(tmpall) != 0:
		for thing in tmpall:
		    grouped_things[thing[0]].append(thing)
		fixedthings = []
		for gthings in grouped_things:
			fixedthings.append(gthings)
		intersects.append(list(set(fixedthings)))
pureplanes = flatten([intersects + goodstuff])
OUT = pureplanes
5 Likes