Usage of SplineHelp.InitSplineWith() regarding flags -> returned data
-
Dear community,
Returned Data of Flag
c4d.SPLINEHELPFLAGS_CONTINUECURVEunclear.I've read that the
SplineHelp()has flag calledc4d.SPLINEHELPFLAGS_CONTINUECURVE.
While the written explanation is clear to me :
Continue the curvature of an existing spline at the end points.Its unclear to me how to utilize the data or even how the data I get is different from a "normal" helper.
Reason of interest: I am coding a "Curvature" displaying Tag Plugin atm.
thank you for your time.
cheers mogh -
Hey @mogh,
Thank you for reaching out to us. I agree that it is a bit unclear, but the TLDR is that this is just a minor niche feature. I first thought it would be a way to treat a spline as a close splined, with the description a bit weirdly put, but that is not the case. There is only once place where this flag is used, and it is here:

I.e., it seems to try to continue the curvature of the last segment. How this works in detail and how sensible this is, I cannot really tell you either. From the code we can see here, it seems to try to parallel transport the last tangent. But there is also something else going on, as it not only takes the last point but the point before that into account (
i - 2). It then uses the tangent ofm2 * (~m1 * m2), which is also super hand-wavy for me. It basically takes the orientation of the last tangent twice but for A * B, makes B relative to the second last tangent (m1). Or a bit incorrect but more readable: 'It takes the orientation of the last point twice, but also undoes the orientation of the second last point.'How this is relevant I have absolutely no idea, probably some MoGraph related 'custom logic'. My advice: Leave it as its default and otherwise ignore it.
As a warning: All the spline helpers implement parallel transport, which can make their output for curvature tasks undesirable (as it messes with what is the mathematical tangent of a spline in favour of what humans would expect. When you are at a loss about what I am talking about, search the forum for parallel transport and my username, the topic has come up multiple times in the past). It might be better to get the
LineObjectof a spline, i.e., its current discrete form, and do all the math based on its vertices.Cheers,
Ferdinand -
Thank you ferdinand,
I will implement my own "tagent" / "colinear" ending then, and not use this flag.
@ferdinand said in Usage of SplineHelp.InitSplineWith() regarding flags -> returned data:
As a warning: All the spline helpers implement parallel transport, which can make their output for curvature tasks undesirable (as it messes with what is the mathematical tangent of a spline in favour of what humans would expect. When you are at a loss about what I am talking about, search the forum for parallel transport and my username, the topic has come up multiple times in the past). It might be better to get the LineObject of a spline, i.e., its current discrete form, and do all the math based on its vertices.
Aha ... thank you - this explains why I get so different from spline-helpers tangent and cross tangent. Could also corelate to my "noisy" sampling with splinehelper (see screen below)
My question other topic but same context would be how to get a more high resolution Line-Object. We talked about this in an early stage about this, but my code wasn't mature enough to be sure. -> Is the short answer C4D can not get more precise than a 0° degree line object ?Screenshot line object Bezier 0° degree (for enough resolution). Nice plot but resolution enough? Probably not for edge cases like flatish dips.
![2025-10-27-Cinema 4D 2025.2.1 - [Untitled 1 _] - Main_001066.png](/forum/assets/uploads/files/1761567924411-2025-10-27-cinema-4d-2025.2.1-untitled-1-_-main_001066.png)
Splinehelper 200x samples not moving average smoothed. The noise starts to show at about double the resolution of a line object ...

Should I open another Topic?
thank you again -
Hey @mogh,
Yes, a new topic would be better if we move on to debugging your plugin. But I'll briefly answer here.
- That the comb curve flips between 'above' and 'below' is normal and exactly what I talked about before with mathematical vs 'what artists want' tangents. I once spend here some time on explaining this.
- The problem with your screens is a bit that you do not explain what you would consider incorrect. I assume that you understand why the flipping happens and are okay with it and are concerned about the jaggedness of your combs? Without debugging your code this is very hard to evaluate.
C4D can not get more precise than a 0° degree line object ?
Splines are what is often called smooth geometry, i.e., a parametric curve that is mathematically defined and has infinite precision (you can think of it as infinite points). This is opposed by discrete geometry such as a
LineObjectwhich has a finite set of data points. The interpolation settings of a spline are the parameters with which the smooth form ('the spline') is brought into a discrete representation ('the line object') for display and other purposes. So, asking if Cinema 4D could discretize with 0° (or less) does not make too much sense, since discretization with 0° means infinite precision, i.e., the smooth form. For practical purposes, 0.1° should be more than enough. And that is probably already more than order of precision more than you actually need, as humans cannot see that level of detail.When you do not want to only control the discretization over the angle of change (a.k.a. curvature), but also over the distance of points, you can also set a maximum length for the segments. For that you must change the spline interpolation from 'Adaptive' to 'Subdivided'. This way, you can ensure that even in straight areas, the segments do not become too long.
But the general problem is probably that you do not normalize your data. It makes a difference if the last point is 10 units away from the second last or 1000 units. To approximate the mean curvature between two vertices in some discrete geometry, the formula shown below exists; which is a hack compared to more fancy approaches such as this one. It will approximate the mean curvature between two vertices
pandqwith the normalsnpandnq:(nq - np) * (q - p) c_i = ------------------- |q - p|For a mesh vertex you do this with all neighboring vertices and average the result. My guess would be that you are missing this exact normalization step (
/|q - p|, i.e., the value divided by the Euclidean distance between the two points) in your comb calculation. Because curvature is inherently a smooth property, the 'neighbor' of a point in a smooth curve/geometry is always exactly1/infinityunits away. So, you need to ensure that the influence of a neighbor vertex in the discrete world is weighted by its distance to the current vertex.For splines you would probably have to do this for the left and right tangent of each vertex and then take the mean value. But curvature discretization is like all computational geometry subjects not super trivial, and there might be extra/expert steps required for splines I am not aware of right now.
Hope this helps,
FerdinandHere is a script I wrote a long time ago where I used that 'formula' to approximate the mean curvature for a mesh. This is non-public code, so it has no comments except for me pointing out the formula.
"""Computes the mean curvature of the selected mesh and stores it in a vertex map. """ import c4d def GetNormal(pid, points, polygons, neighbor): """ """ connected = neighbor.GetPointPolys(pid) vertexNormals = [] for cpoly in [polygons[pid] for pid in connected]: if pid == cpoly.a: o, p, q = points[cpoly.d], points[cpoly.a], points[cpoly.b] elif pid == cpoly.b: o, p, q = points[cpoly.a], points[cpoly.b], points[cpoly.c] elif pid == cpoly.c and cpoly.IsTriangle(): o, p, q = points[cpoly.b], points[cpoly.c], points[cpoly.a] elif pid == cpoly.c and not cpoly.IsTriangle(): o, p, q = points[cpoly.b], points[cpoly.c], points[cpoly.d] elif pid == cpoly.d: o, p, q = points[cpoly.c], points[cpoly.d], points[cpoly.a] vNormal = ~((o-p) % (q-p)) vertexNormals.append(vNormal) factor = 1./len(vertexNormals) return ~(sum(vertexNormals) * factor) def GetCurvature(node): """ """ neighbor = c4d.utils.Neighbor() neighbor.Init(node) points = node.GetAllPoints() polygons = node.GetAllPolygons() def getNeighborVertices(pid): ids = [pid] for i in neighbor.GetPointPolys(pid): cpoly = polygons[i] pnts = [cpoly.a, cpoly.b, cpoly.c] if not cpoly.IsTriangle(): pnts.append(cpoly.d) fi = cpoly.Find(pid) cnt = len(pnts) - 1 prev = pnts[fi - 1] if fi > 0 else pnts[-1] nxt = pnts[fi + 1] if fi < cnt else pnts[0] if prev not in ids: ids.append(prev) if nxt not in ids: ids.append(nxt) for i in ids[1:]: yield i, points[i] data = [] for ip, p in enumerate(points): np = GetNormal(ip, points, polygons, neighbor) temp = [] for iq, q in getNeighborVertices(ip): nq = GetNormal(iq, points, polygons, neighbor) # This is just a very cheap # # (nq - np) * (q - p) # c_i = ------------------- # |q - p| # temp.append((nq - np) * (q - p) / (q - p).GetLength()) c = sum(temp) * (1. / len(temp)) * .5 + .5 data.append(c) neighbor.Flush() return data def CreateVertexMap(node, data): """ """ tag = c4d.VariableTag(c4d.Tvertexmap, len(data)) tag.SetAllHighlevelData(data) tag.SetBit(c4d.BIT_ACTIVE) node.InsertTag(tag) c4d.EventAdd() def main(): """ """ data = GetCurvature(op) CreateVertexMap(op, data) if __name__ == '__main__': main() -
Hey ferdinand,
I mixed different questions - I'll keep to the theoretical part to keep the Post relevant to the original question.
I appreciate the informative post as always.

Parametric concept of a spline is clear to me -> that's why i asked about "C4D can not get more precise than a 0° degree line object ?" which was formulated to lose as 0° is mathematical problematic? and I know 0.1 would be better. sorry about that.
The tip about spline 'Adaptive' setting was a good hint, I never use it in work so I forgot about it.So to summarize regarding my question.
The Line object always samples what the user has set in the spline settings and not by a unknown internal setting (for example to give good viewport performance, or nice equal sections)
And its a better fit for my application, hence there is no "linear transport" shenanigans going on.
And if I want to display a high resolution of my calculation, I make an internal copy of that spline and edit the spline settings, instead of sampling a low division spline with spline helper.Normalization / Jagged lines:
I use Menger-Krümmung. -> will open a new topic.
Your code might come in handy when I'll extend the plugin to polygon meshes.
...
...
...Remark
as humans cannot see that level of detail.
I have to disagree on this topic. As a tell tale we import CAD data here into C4D to evaluate the work of the engineers.
Not long ago I said to our surface engineer. "take a look at the end of that surface something feels off, it looks like the surface is lifting" -> The engineer reportet back "you just spoted a 0.001mm surface deviation of an unconstrained spline ending I did not set."
We could argue that the seen result was in fact not 0.001mm but perhaps to surface setup more than 1mm, (or by some rounding error C4D normal tag shading where continuous and then stagnant for 1 pixel) but my point is settings in precision are important and carry through till the final product. Even though a setting of 0.1° for a spline might might be unsuitable in most cases (rendering, performance, ...) it is not for evaluation.
So even C4D and all that rounding / conversion / floating point precision might look like unrealiable, unecessary or even esotheric it caries through to a certain degree and its more reliable than you think.
(Yes we evaluate in the original CAD Program, but the tale is that I saw something even after importing it into C4D)
As reference to why I need this:
Blender Plugin: Surface Diagnostics - Josef Ludvík Böhm
Thank You