Jump to content

Selecting polygons that share the same normal direction


Cybergooch
Go to solution Solved by srek,

Recommended Posts

There used to be a plugin (a couple, actually) that let you select a polygon on a model, and then executing the plugin would select all the other faces that shared that normal direction. That plugin (a French one I believe, "Selection Suppletives" or something like that, doesn't seem to work in C4D 2023. Has this ability been built in yet, or is there another plugin or way to do this?

Link to comment

Here is a python solution. Enjoy 🙂 It also works with multiple polygons selected with different normals. It will select all the polygons that match any of the normals in the initial selection.

 

import c4d

def getNormal(poly, points):
    a = poly.a
    b = poly.b
    c = poly.c
    d = poly.d
    a_pos = points[a]
    b_pos = points[b]
    c_pos = points[c]
    vector1 = a_pos-b_pos
    vector2 = b_pos-c_pos
    normal = vector1.Cross(vector2)
    normal.Normalize()
    return str(normal)

def main():
    doc.StartUndo()
    obj = doc.GetActiveObject()
    polys = obj.GetAllPolygons()
    points = obj.GetAllPoints()
    poly_sel = obj.GetPolygonS()
    indices = poly_sel.GetAll(len(polys))
    selected = [i for i, selected in enumerate(indices) if selected]
    selected_normals = {getNormal(polys[index], points) for index in selected}
    for i, poly in enumerate(polys):
        normal = getNormal(poly, points)
        if normal in selected_normals:
            doc.AddUndo(c4d.UNDOTYPE_CHANGE_SELECTION, obj)
            poly_sel.Select(i)
    doc.EndUndo()
    c4d.EventAdd()
if __name__ == '__main__':
    main()

 

 

select_similar_normals.py

Edited by kalugin (see edit history)
Link to comment
5 hours ago, kalugin said:

Here is a python solution. Enjoy 🙂 It also works with multiple polygons selected with different normals. It will select all the polygons that match any of the normals in the initial selection.

 

import c4d

def getNormal(poly, points):
    a = poly.a
    b = poly.b
    c = poly.c
    d = poly.d
    a_pos = points[a]
    b_pos = points[b]
    c_pos = points[c]
    vector1 = a_pos-b_pos
    vector2 = b_pos-c_pos
    normal = vector1.Cross(vector2)
    normal.Normalize()
    return str(normal)

def main():
    doc.StartUndo()
    obj = doc.GetActiveObject()
    polys = obj.GetAllPolygons()
    points = obj.GetAllPoints()
    poly_sel = obj.GetPolygonS()
    indices = poly_sel.GetAll(len(polys))
    selected = [i for i, selected in enumerate(indices) if selected]
    selected_normals = {getNormal(polys[index], points) for index in selected}
    for i, poly in enumerate(polys):
        normal = getNormal(poly, points)
        if normal in selected_normals:
            doc.AddUndo(c4d.UNDOTYPE_CHANGE_SELECTION, obj)
            poly_sel.Select(i)
    doc.EndUndo()
    c4d.EventAdd()
if __name__ == '__main__':
    main()

 

 

select_similar_normals.py 969 B · 1 download

 

I just want to mention that you have to be very careful with these sorts of scripts when dealing with non-planar quad polygons that may be present and selected.

 

For example, consider the following view through a Parallel Camera (to minimize perspective distortion) being used as the Viewport camera:

nonplanar_quad.thumb.png.82b881f039c66c7d234a2d1eb6f14eb9.png

The magenta diagonal line is a guide that goes from Point 0 to Point 3, representing how this non-planar quad is presently being triangulated by Cinema 4D.

 

The yellow line segment emanating from the center (actually through the center, sort of, since it starts quite a ways below the surface of the quad at what Cinema 4D considers to be the center point of this quad) represents what Cinema considers to be the polygon's normal, with Polygon Normals enabled for display in the Viewport (and shown via Preferences at a 400% scale, so that they are long enough to be "legible"). Similar yellow line segments going through the corner points of the polygon, added in via creative use of a Matrix object (and the little originally white cubes at the vertices that it thinks it is aligning!), overlay a copy of the polygon normal at each point, so that it can be compared with the light gray vertex normals coming up from each point, as rendered by Cinema 4D, since Vertex Normals are also enabled for the Viewport. In addition to all of the above, the point indices are also displayed to label the individual vertices, courtesy of the aforementioned Matrix object.

 

I should also note that there is a slight discrepancy between the direction of the Z Modeling Axis and the quad normal, as displayed. Active tool info: Move Tool in Polygon mode with the Modeling Axis set to Selected/Axis and all else default. This is not a figment of your imagination and this is noticeable regardless of whether the Viewport is using a Perspective camera or a Parallel camera. They are truly pointing in slightly different directions and I don't know which of the two is "correct."

 

Here are the point coordinates making up the sole Polygon of the polygonal object (uncreatively) named nonplanar_quad, as shown via the Structure Manager:

 

nonplanar_quad-structure-manager.png.deacd6506d6c0e787ce0f36ac50849f3.png

 

Finally, here is what the Python script, quoted from the above post, produces as the polygon's normal for the Polygon comprising our nonplanar_quad object, along with additional data describing the point properties of the object and its sole polygon, as retrieved via the usual Cinema 4D Python API member functions called on the object:

 

nonplanar_quad_normal_calculation.thumb.png.ffa27c8c97e837a849877b051f6bdd76.png

 

The resulting normalized unit-vector (last line of output, above) lacks a Z directional component, even though Cinema's interpretation (via those yellow normal line segments and their leftward tilt in the view) is clearly showing that Cinema 4D thinks a Z component should be present in the polygon normal.

 

The cause of the difference is that the quoted script only uses Polygon points a, b, and c, to calculate the cross-product of rays ba and cb as the polygon's normal. For this non-planar case, polygon point d is also playing a role in what Cinema 4D considers to be the polygon's "true" normal. Of course we are not dealing with a quadrangle or polygon in the mathematical sense here, since it is non-planar, but it can be argued that the (averaged) normal for this non-planar quad should take into account the individual normals of both of the planar triangles from which it is constructed.

 

 

Edited by SharpEars (see edit history)
Link to comment
On 2/2/2023 at 10:09 PM, srek said:

In the asset browser search for select facing. There should be only one capsule that matches. Drag it into the object manager as a child of your object.

You can use the resulting selection for modeling operations or store the selection for texturing etc.

Check the attached scene for an example.

image.png.39ca4b0060721f7ba5707a1fbb973418.png

Select Facing Demo 01.c4d 339.09 kB · 1 download

Thanks for the example. This is my first run-in with "capsules" so I have some catching up to do. I see how this would be useful, but it seems like it's primarily a step used to alter data rather than a selection mode. If I make this a child of an object, nothing seems to be actually selected in the scene, unless I'm doing something wrong.

Link to comment
23 hours ago, kalugin said:

Here is a python solution. Enjoy 🙂 It also works with multiple polygons selected with different normals. It will select all the polygons that match any of the normals in the initial selection.

 

 

 

Hey thanks for this, it works great!

Sharpears is correct with his comments, but the majority of my work when I need something like this is pretty clean geometric shapes that are planar and quads.

This might not give desired reults in some cases, but will help a lot for architectural type work, etc.

Link to comment
1 hour ago, Cybergooch said:

Thanks for the example. This is my first run-in with "capsules" so I have some catching up to do. I see how this would be useful, but it seems like it's primarily a step used to alter data rather than a selection mode. If I make this a child of an object, nothing seems to be actually selected in the scene, unless I'm doing something wrong.

The selection is not meant for interactive use but with modeling operations or for the creation of selection tags, the example scene does both.

Link to comment

Here is another image that shows how Cinema 4D calculates the normal for a non-planar quad, with a detailed description of the math and elements shown appearing right below it:

nonplanar_quad_how_to_get_its_normal.thumb.png.58fb72843fdd0fe6ab6c6cb2821e775f.png

 

The violet and magenta line segments are simple Segment Guides that I added to help represent the diagonals of this non-planar quad.

 

In terms of calculations, the ▲abc Normal is averaged with the ▲cda Normal to arrive at the final normal being sought, one that matches Cinema 4D's calculations for the quad "polygon," and is represented in the image by the ▰ abcd Normal. If you look closely, you can even see the yellow Cinema 4D polygon normal protruding from the arrow-tip of this blue (calculated) average normal.

 

I hope that this picture explains it well. Each of the two triangle normals' directions were arrived at by calculating the normalized cross-products of two edge vectors from the quad, with:

ab x bc used for the ▲abc Normal, and

cd x da used for the ▲cda Normal

 

With the directions of the normals calculated, the yellow illustrative arrows representing them in the image were positioned so that they each originate from the centroid (aka barycenter) of their respective triangles, as one is normally accustomed to seeing them.

 

The component triangle normal vectors were then used in the following calculations:

1. Find the average of the two triangle normals using the formulat: (▲abc Normal + ▲cda Normal) / 2

2. Normalize the resulting vector to be a Unit Vector

3. Show the final outcome as an arrow labeled with: ▰ abcd Normal

 

The final normal's arrow is positioned so that it starts at the center of the quad, defined as the average of its four points' coordinates (the points are labeled in the image with a, b, c, and d). This is identical to how Cinema 4D calculate the quad's center, as you can see from the polygon normal's start point in the image (and also happens to be the World origin, as well as the quad's axis as I positioned it).

 

Edited by SharpEars (see edit history)
Link to comment
×
×
  • Create New...

Copyright Core 4D © 2023 Powered by Invision Community