# Get the normal of a polygon selection

• On 26/02/2018 at 03:24, xxxxxxxx wrote:

How do I get the normal of a polygon selection (more than one polygon selected)?

- Pim

• On 27/02/2018 at 07:12, xxxxxxxx wrote:

Hi Pim, thanks for writing us.

With reference to your question I've a doubt: given that more than one polygon is part of the selection set, are you interested to retrieve all the polygon normals belonging to that set or the average value of them?

In any case getting the normal is pretty trivial once you've accessed points and polygon's indexes of your selection set. The code below briefly shows an attempt without taking in consideration NormalTag. In this latter case the extension would be pretty straightforward.

``````
import c4d

def EvaluateNormal(poly, points) :
res = c4d.Vector
if poly.IsTriangle() : # a,b,c
# retrieve position of points tagged as a, b, c
pointA = points[poly.a]
pointB = points[poly.b]
pointC = points[poly.c]

# compute the vectors between B-A and C-A
u = pointB - pointA
v = pointC - pointA

# calculate the normal as cross product between A-B and C-B vectors
res = u.Cross(v)

# return as a list
return (res.GetNormalized())
else: # a,b,c,d
# retrieve position of points tagged as a, b, c and d
pointA = points[poly.a]
pointB = points[poly.b]
pointC = points[poly.c]
pointD = points[poly.d]

# compute the vectors between B-A and D-A
u = pointB - pointA
v = pointD - pointA

# calculate the normal as cross product between A-B and C-B vectors
res1 = u.Cross(v)

# compute the vectors between A-D and C-D
u = pointC - pointA
v = pointD - pointA

# calculate the normal as cross product between A-D and C-D vectors
res2 = u.Cross(v)
return (res1.GetNormalized(), res2.GetNormalized())

def main() :
if op is None or not op.IsInstanceOf(c4d.Opolygon) :
print "Select a PolygonObject."
return
# get the tags
tags = op.GetTags()
if tags is None:
return

# get the polygons' indexes list
polys = op.GetAllPolygons()
if polys is None:
return
print polys

# get the points' positions list
points = op.GetAllPoints()
if points is None:
return
print points

for i in tags:
# iterate over the tags to look for selection tags
if i is None:
return

if i.IsInstanceOf(c4d.Tpolygonselection) :
# get the BaseSelect out of the current selection tag
bs = i.GetBaseSelect()
if bs is None:
retutn
# get the selection status of the polygons
sel = bs.GetAll(op.GetPointCount())
if sel is None:
return
# iterate over the data found in BaseSelect and retrieve face normal data
for index, selected in enumerate(sel) :
if not selected: continue
print "Polygon[", index, "] is selected in", i.GetName(), " and related normals are ",EvaluateNormal(polys[index], points)

if __name__=='__main__':
main()
``````

Best, Riccardo

• On 27/02/2018 at 07:48, xxxxxxxx wrote:

Hi Ricardo,

I can calculate the normal for one polygon, what what to do for a selection with multiple polygons?

If I select some polygons of an object, cinema 4d shows me one (1) normal.
Is that the average of all normals?

And how to calculate the average of these normals.
Just add them and divide them by the number of vectors?

-Pim

• On 28/02/2018 at 01:57, xxxxxxxx wrote:

Hi Pim, I'd say frankly I'm a bit confused by your second answer. Could you please specify what you're actually trying to achieve and the intent of the request? This will help me better address the support effort.

With regard to average vector, just summing up at component level and dividing by the number of vectors should work properly ;)

Looking forward hearing from you, give best.

• On 01/03/2018 at 01:49, xxxxxxxx wrote:

Hi Ricardo,

I want to place an object in the polygon selection of another object.
Placing should be done according the normal of the polygon selection and the object should be scaled according to the size of the polygon selection.

But I guess the average normal of all normals of the polygons in the polygon selection will do.

-Pim

• On 01/03/2018 at 09:30, xxxxxxxx wrote:

For my PolyGnome plugin (inspired by William Vaughan's Polystein kit for MODO) I used to position an object on a polygon selection by calculating the average normal of all selected polygons, using CalcFaceNormal, additioning them all up and dividing by the number of selected polygons.
Then used a ray collider to detect the position on the surface.

For the scaling I calculated the bounds of the selected polygons and projected the object from the position onto these bounds. The distance of the projection provided the scaling values, from which I used the smallest value to let the object fit inside the polygon selection.
Obviously, it will not always provide for a perfect fit, but with the smallest value you at least end up with a scale where the object doesn't intersect with non-selected polygons.

• On 26/03/2018 at 04:50, xxxxxxxx wrote:

Hi C4DS,

That is exactly the plugin, we had in mind.
But it is there already, so I will stop developing.

-Pim