# Intersect PlanarFace with Solid (Python)

**URL:** <https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674>\
**Category:** Revit\
**Tags:** python, geometry\
**Created:** [September 4, 2022, 9:36pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674 "2022-09-04T21:36:16Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 4, 2022, 9:36pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/1 "2022-09-04T21:36:16Z")

</div>

Hello Dynamo Friends,

I want to intersect a Wall Face (got that as PlanarFace) and a Solid with the DoesIntersect method.  
But this method doesn´t work with the planarface. Can I convert that to a face/surface somehow?  
Tried to GetSurface but that gives me a Plane 😃

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/2/a/2a47e0a289c337d1f7895d25c8b4c59dad539497.png)

```auto
z= x.DoesIntersect(y)

```

Thankful for any advice!

---

<div class="post-metadata">

**Author:** ![jacob.small](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/jacob.small/32/161030_2.png) [@jacob.small](https://forum.dynamobim.com/u/jacob.small)\
**Post date:** [September 5, 2022, 1:09am UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/2 "2022-09-05T01:09:16Z")

</div>

You’ll need to convert the Revit face to a DesignScript (Dynamo) surface first, which you should be able to do with the ToProtoType() method. Something along the lines of this:

```auto
dynamoFace = x.ToProtoType()
dynamoSolid = y.ToProtoType()
z = dynamoFace.DoesIntersect(DynamoSolid)

```

Note that it’s likely there is a better way to do what you’re after by staying in the Revit API enitrely, but we don’t have enough context to help just yet.

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 5, 2022, 9:35pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/3 "2022-09-05T21:35:26Z")

</div>

Hello Jacob 🙂  
Yes i would like to avoid the dynamo geometry, so how about that:

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/8/5/85ddb83b25433f6593da91acb6a144a3e76811a7.jpeg)

I can use the Face.Intersect(Face) method by breaking the solid down.

Good solution or will this be much slower then intersecting with a solid?

I just want to know if this specific wall face is intersecting with a solid (floor.)

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 5, 2022, 10:45pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/4 "2022-09-05T22:45:36Z")

</div>

This method does not work, it alway gives intersections where are none 😕

[The Building Coder: Face Intersect Face is Unbounded (typepad.com)](https://thebuildingcoder.typepad.com/blog/2019/09/face-intersect-face-is-unbounded.html)

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/b/b/bb830971920da817447e92535c07b9d19871c48e.png)

```auto
w = UnwrapElement(IN[0])
f = UnwrapElement(IN[1])
outlist=[]

for f in face:
	z= w.Intersect(f)
	outlist.append(z)

OUT = outlist

```

---

<div class="post-metadata">

**Author:** ![jacob.small](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/jacob.small/32/161030_2.png) [@jacob.small](https://forum.dynamobim.com/u/jacob.small)\
**Post date:** [September 5, 2022, 11:10pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/5 "2022-09-05T23:10:27Z")

</div>

What are you getting the PlanarFaces and solids from? What is the larger workflow?

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 6, 2022, 4:37pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/7 "2022-09-06T16:37:54Z")

</div>

I found a method and now have wonderful 5mm solids from the faces 😃

```auto
lines = UnwrapElement(IN[0])
normal = UnwrapElement(IN[1])

loop = CurveLoop.Create(lines)

z= GeometryCreationUtilities.CreateExtrusionGeometry(List[CurveLoop]([loop]),normal,0.005)

OUT = z

```

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/a/2/a2f983612081603e571e6a8f3865b64c9f502d97.png)

Now i just have to find out if i can also get the area/volume of inbtersection when workin with Revit.DB.

Purpose is still that one:

[Getting Faces and Solids gives errors for Walls and Floors - Dynamo (dynamobim.com)](https://forum.dynamobim.com/t/getting-faces-and-solids-gives-errors-for-walls-and-floors/79869)

Want to try to go the full Revit.DB route.

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 6, 2022, 5:53pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/8 "2022-09-06T17:53:22Z")

</div>

Aaaaand this method is not reliable 😬

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/a/8/a8b8a5c6dd2ad0626ac1d94d034adba38cf900b3.png)

```auto
lineslist = UnwrapElement(IN[0])
normalslist = UnwrapElement(IN[1])

for lines, normals in zip(lineslist,normalslist):
	for line, normal in zip(lines, normals):
		loop = CurveLoop.Create(line)

		z= GeometryCreationUtilities.CreateExtrusionGeometry(List[CurveLoop]([loop]),normal,0.005)

OUT = z

```

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 6, 2022, 6:30pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/9 "2022-09-06T18:30:12Z")

</div>

Next idea is to use UV method to get min and max points and build a whole face on my own.  
But I have no luck again, here is what i get for UV 0,0 and UV 1,1:

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/6/1/610d8db11b4de75ed56784432157c3d52c7e8655.png)

```auto
w = UnwrapElement(IN[0])
uv=UV(0,0)
x=w.Evaluate(uv)

OUT = x

```

Maybe time now to give up that Revit geometry thing…

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 6, 2022, 8:36pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/10 "2022-09-06T20:36:39Z")

</div>

So a different approach:

Using solids for intersection and then getting the right wall face by checking which wall face is the nearest to the floor:

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/b/6/b6dbe1cb035bca6096b385d2a802966cdcab9e2c.png)

```auto
for floor, wall in zip(floors,walls):
	outlist=[]
	for w in wall:
			x=BooleanOperationsUtils.ExecuteBooleanOperation(floor, w, BooleanOperationsType.Intersect).Volume
			outlist.append(x)
	outlist2.append(outlist)

	
OUT = outlist2

```

```auto
for walls,floor in zip(wallslist,floors):
	outlist2=[]
	for wall in walls:
		outlist=[]
		for w in wall:
			x= w.Project(floor).Distance
			outlist.append(x)
		outlist2.append(outlist)
	outlist3.append(outlist2)
OUT = outlist3

```

---

<div class="post-metadata">

**Author:** ![jacob.small](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/jacob.small/32/161030_2.png) [@jacob.small](https://forum.dynamobim.com/u/jacob.small)\
**Post date:** [September 6, 2022, 9:39pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/11 "2022-09-06T21:39:47Z")

</div>

SO you’re gathering a bunch of floors, and a bunch of walls, and testing to see which floors intersect which walls?

Why not use an element.intersects filter instead?

> **[ElementIntersectsSolidFilter Class](https://www.revitapidocs.com/2023/19276b94-fa39-64bb-bfb8-c16967c83485.htm)**
>
> Online Documentation for Autodesk's Revit API: 2015, 2016, 2017, 2017.1, 2018

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 7, 2022, 8:06pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/12 "2022-09-07T20:06:17Z")

</div>

Hello Jacob, thats in fact the method I´m starting with, but there is so much else to do 😃  
At this moment i got nearly everything working with Revit.DB, had a hard time and would be very interrested in your thoughts about my methods. Questionable workarounds with question marks.

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/e/5/e5df8e07f73c4b2a697f86786f28e92d358a4f34.png)

- Get floor solid with **f.get\_Geometry(opt)**
- Scale Floor Solid with **SolidUtils.CreateTransformed(scaledSolid, transform)**
- Get Walls with **ElementIntersectsSolidFilter(s)**
- Get wall solid with **w.get\_Geometry(opt)**
- Intersect with **BooleanOperationsUtils.ExecuteBooleanOperation(floor, w, \* BooleanOperationsType.Intersect).Volume** to drop walls that are intersecting too little
- Get floor centroid with **s.ComputeCentroid()**
- Get 2 largest wall faces by **s.Faces** and sort by area
- Get nearest wall face for every wall by **w.Project(floor).Distance**
- Get vertical floor faces with **s.FaceNormal.Z ==0**
- Filter floor faces by edges that have length=floor hight

Now it gets interresting at finding the wall face for every floor face.

- Get all Face normal vectors by **x=f.FaceNormal**
- Match parallel wall and floor faces
- Get floor faces center by **x=face.GetEdgesAsCurveLoops(), y=z.GetPlane(), center= y.Origin**  **???**
- Pull floor face centerpoints on wall faces by **wall.Project(point).Distance** and use distance to match a floor face to every wall face
- Get lines from floor faces by **w.GetEdgesAsCurveLoops() and y=u.ToProtoType()**
- Switch to Dynamo geometry, lines to Polycurve, surface by patch, use U/V parameter 0/0.5 and 1/0.5 to get centerline on floor face. **???** , thats where the family will be placed
- Back to Revit Geometry, pull start/endpoint of line on wall face by **w.Project(p).XYZPoint**
- finally place family by **doc.Create.NewFamilyInstance(f,p,v,family)**

There is for sure potential to make some things better, for example, can i get the distance between 2 faces?

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 7, 2022, 8:54pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/13 "2022-09-07T20:54:37Z")

</div>

After testing on about 30 floors/90 walls, it works great!

There is only one single method failing from time to time, in about 3% of my tests.

It is getting the distance from floor centroid to the wall faces to check which face is the nearest one:

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/4/f/4f6d7a00e7db30d4ae0a576e93ef26acdbe823bb.png)

so i have to find another way for that.

But if it works, pretty much fun 😃

![[video-to-gif output image]](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/5/c/5c6281355372ce6d428b516b487a21cbd386c957.gif)

---

<div class="post-metadata">

**Author:** ![jacob.small](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/jacob.small/32/161030_2.png) [@jacob.small](https://forum.dynamobim.com/u/jacob.small)\
**Post date:** [September 8, 2022, 12:29am UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/14 "2022-09-08T00:29:44Z")

</div>

This seems pretty close to spot on. it may be that the 3% of conditions returning an error could be resolved by modifying the call methods, but it’d require you post the full python to confirm.

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 8, 2022, 12:53am UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/15 "2022-09-08T00:53:03Z")

</div>

Hey Jacob, thanks for your reply,

As this Project method fails 3 times in the graph, i looked for another method and found this:

[The Building Coder: Planes, Projections and Picking Points (typepad.com)](https://thebuildingcoder.typepad.com/blog/2014/09/planes-projections-and-picking-points.html)

So I´m now using the Signed distance and the dotproduct, it works now for all the walls that didnt work befor, but now the others don´t work anymore 😃 Hope to find the mistake tomorrow. And then i also will post the code you mentioned, maybe you will find out why my project method fails.

current status:

```auto
	for w,p in zip(wall,point):
		a = w.GetEdgesAsCurveLoops()
		for i in a:
			k=i.GetPlane()
			v=p-k.Origin
			x=k.Normal.DotProduct(v)
			o=p-x*k.Normal
			p=o.ToPoint()

```

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/c/6/c65b7f596dc294f235921936ea0a7d952f494afa.png)

EDIT: Here is the failing project method code:

```auto
wallslist = UnwrapElement(IN[0])
floors = UnwrapElement(IN[1])
outlist3=[]
for walls,floor in zip(wallslist,floors):
	outlist2=[]
	for wall in walls:
		outlist=[]
		for w in wall:
			x= w.Project(floor)#.Distance
			outlist.append(x)
		outlist2.append(outlist)
	outlist3.append(outlist2)
OUT = outlist3

```

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/e/1/e1e4453f860aeae815e263d4bf3c4042dcc72a13.png)

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 8, 2022, 7:08pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/16 "2022-09-08T19:08:12Z")

</div>

I had just some mistake with my variables, the graph works now on **100%** of the floors i tested 😃

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/e/a/ea4b2beaf3afad968824218b9a3fafff7f903a60.png)

```auto
faces = UnwrapElement(IN[0])
points = UnwrapElement(IN[1])
outlist2=[]
for face, point in zip(faces, points):
	outlist=[]
	for f,p in zip(face,point):
		loops = f.GetEdgesAsCurveLoops()
		for loop in loops:
			plane = loop.GetPlane()
			diff = p-plane.Origin
			normal = plane.Normal
			skalar = normal.DotProduct(diff)
			pointOnPlane=p-skalar*normal
			dynPoint=pointOnPlane.ToPoint()
		outlist.append(dynPoint)
	outlist2.append(outlist)

OUT = outlist2

```

Still interrested in finding out why the Project-Method doesn´t work, going to isolate a failing element…

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 8, 2022, 7:29pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/17 "2022-09-08T19:29:46Z")

</div>

Haha, any idea why this point cant be projected on this wall face? 😃

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/7/3/73fb0c1084218c628d36cb289d76f2c0f6d43910.png)

So this planar faces are so strange, they always behave as they would have no boundaries, as if they were planes. So they can not be used for face intersection etc…

BUT if you want them to behave one single time like a plane, they don´t and won´t let you project if there is a hole.

So the method with the curveloops/plane seems to be the better option for my purposes.

---

<div class="post-metadata">

**Author:** ![jacob.small](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/jacob.small/32/161030_2.png) [@jacob.small](https://forum.dynamobim.com/u/jacob.small)\
**Post date:** [September 8, 2022, 8:22pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/18 "2022-09-08T20:22:39Z")

</div>

Not sure why it won’t project in this case; the profile shape being convex in two spots might be causing an issue, but it’d take awhile to confirm.

---

<div class="post-metadata">

**Author:** ![gerhard.p](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/gerhard.p/32/147675_2.png) [@gerhard.p](https://forum.dynamobim.com/u/gerhard.p)\
**Post date:** [September 8, 2022, 8:41pm UTC](https://forum.dynamobim.com/t/intersect-planarface-with-solid-python/80674/19 "2022-09-08T20:41:12Z")

</div>

It is definitely the cutout, i now remember that i had the exact same problem with the dynamo geometry version, thats why I also there used pull onto plane instead of pull onto face.
