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,

Thanks for the reply.
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