[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
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:

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.


MAXON SDK Specialist

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.


MAXON SDK Specialist

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