[SOLVED/NotABug] Bug with c4d.CPolygon



  • Cinema 4D Version: R21
    OS: Windows 10

    UPDATE: Not a bug, the CPolygon determines whether it's a triangle by checking if c == d.

    Setting the 'c' component of a triangle CPolygon to anything other than 0 will cause the CPolygon to no longer be a triangle.

    Foo = c4d.CPolygon(0, 1, 2)
    Foo.IsTriangle() # True
    
    Foo.c = 0
    Foo.IsTriangle() # True
    Foo.c = 5
    Foo.IsTriangle() # False
    

    EDIT: The problem also occurs with the C++ sdk, and also occurs if you set 'c' to 0.

    CPolygon x( 0, 1, 2 );
    x.IsTriangle(); // True
    
    x.c = 0;
    x.IsTriangle(); // False
    


  • Of course not. If you change the c attribute, then c will no longer be equal to d, and it becomes a quadrangle.

    To be more precise: A polygon object always has 4 corner points in form of point indices a,b,c,d. If the corners c and d are equal, then Cinema handles it as a triangle.

    In your code, you create a triangle by setting the corners to the points 0, 1, 2. Corner d will automatically also be 2, since you didn't specify otherwise (print Foo.d to verify). So actually you get the CPolygon (0,1,2,2). This is a triangle.

    Then you set c to 0, resulting in the CPolygon (0,1,0,2). This is a quadrangle (albeit a degenerated one). In your code, you comment # True but actually that's wrong, you get False. (I just tried.)

    Then you set c to 5, resulting in the CPolygon (0,1,5,2). This is a proper quadrangle.

    It would be easier to see if you had actual geometry attached to the points, instead of just having the indices.



  • I see, sorry for the confusion, thanks for the reply!

    I was under the assumption that the CPolygon would stay as a triangle until you changed the 'd' attribute, in hindsight I realize why that wouldn't be the case (d is a property and isn't being set by a function). As for the improper True comment, I must have set 'd' to zero while testing and missed that while copying back the code, my bad.



  • @xNWP Yeah, a CPolygon is really just those four corner indices, a,b,c,d - there is no separate flag that would tell C4D whether this is a triangle or a quadrangle. The information what type of polygon the CPolygon is, is really only encoded in the equality c==d. The function IsTriangle could be written as

    def IsTriangle(self):
        return self.c == self.d
    

    I assume you have read
    https://developers.maxon.net/docs/Cinema4DPythonSDK/html/manuals/3d_concept/modeling/polygon_object.html#polygon-object
    already, although that doesn't go in depth into the triangle property.

    (It gets even better when you come to edge indices: a triangle has edges ab, bc, da - not cd obviously, but also not ca!)


    Learn more about Python for C4D scripting:
    https://www.patreon.com/cairyn



  • Hi @xNWP,

    thank you for reaching out us. No need to be sorry, new APIs can sometimes be a bit confusing ;) And thank you @Cairyn for jumping in and answering the question correctly.

    I just wanted to point out that a, b, c and d of a CPolygon are not properties, but just fields, there is very little special going on with the whole entity, also indicated by it being a struct in C++. The advantage of this design, i.e., also expressing tris as quads, is that you can often neglect checking if a polygon is a tri or quad and thereby optimize out branching. E.g.: You can always compute the arithmetic mean of the vertices of a Cpolygon by computing (pnts[cpoly.a] + pnts[cpoly.b] + pnts[cpoly.c] + pnts[cpoly.d]) * .25, without having to worry if it is a tri or quad.

    Please note that we also have a ask-as-a-question feature in the forum which we would prefer you using instead of doing it manually.

    Cheers,
    Ferdinand



  • E.g.: You can always compute the arithmetic mean of the vertices of a Cpolygon by computing (pnts[cpoly.a] + pnts[cpoly.b] + pnts[cpoly.c] + pnts[cpoly.d]) * .25, without having to worry if it is a tri or quad.

    I tend to disagree here. In a triangle, the arithmetic center should only consider the first three vertices. Doubling the last vertex leads to a different (weighted) result. E.g. reduced to one axis:

    1 + 2 + 9 = 12, divided by 3 results in 4
    1 + 2 + 9 + 9 = 21, divided by 4 results in 5.25



  • Hi @Cairyn,

    you are absolutely right, thanks for catching that, wasn't paying attention this morning. But I would still say that this design can has its advantages where one can optimize out some branching, .e.g. when computing a normal for a x d (quad) or a x c (tri), where you then can just always compute a x d.

    Cheers,
    Ferdinand



  • Thanks for all the extra info guys! I'll make sure to use the ask-as-a-question feature next time :)


Log in to reply