I’m looking for a way to report back the total angle of twist of a 1-rail sweep that is set to freeform. See attached example. When I use roadlike and set it to top, then the profile is oriented to the XY plane the same at both ends. But if the profile gets swept freeform, the end profile is rotated. I want to know if I can get info on this angle in a script. Any ideas?angle_of_twist.3dm (234.7 KB)

You could get the bounding box of both spirals and check their respective height. If the sweep rotates during it’s path upwards, its height will be off. How easy the calculation is will depend on the input though, what exactly is your starting point? Which variables parameterise your geometry?

This example I would parameterise as follows:

- height of cross section
- width of cross section
- angle of sweep starting surface with respect to the vertical world axis
- height of sweep end point

Based on that geometry you should be able to determine how high the bounding box should be and if it is higher than it’s supposed to be. Of course this approach as formulated mostly works for simple cross sections.

EDIT: It also assumes that the rise angle of the sweep is constant and equal to the starting angle.

I really need the angle of twist rather than a derivative such as the boudingbox difference. In the end this is a profile that needs to be bent on a bending machine. The bending machine bends the profile in a helix shape and this turns out to be exactly the ‘freeform’ style. But the intended shape is ‘roadlike top’. So what we want is add some sort of correction to the bending process based on the difference in angle. This example shows a square profile, but it could also be a elliptical profile or something else.

Yes, but the difference in height of the bounding box in combination width your cross section width and height will return the bending angle of the cross section.

Ok, I think I understand what you mean now. Maybe I can extrude a simple straight line of 1 unit length, then the bounding box difference should be exactly equal to the sinus of the angle (if I correct it for the slope angle)

I can try to at least tell you how to relate the height difference to an angle of rotation.

Let’s say that you measure a height difference of `z=14.495`

for an unknown rotation `t2`

.

The green `r`

in the figure is simply the half diagonal of the rectangle:

`r = sqrt((0.5*h)^2+(0.5*w)^2)`

You know your width and height, so you can also use the half width and half height to calculate the gold `t1`

:

`t1 = arcsind(0.5*h/r)`

(arcsine in degrees)

You can also use your knowledge of the radius and the half height `0.5h`

and height difference `z`

to calculate `t = t1 + t2`

:

`t = arcsind((0.5*h+z)/r)`

Then, the angle of rotation of your cross section is simply:

`t2 = t - t1 = 35 degrees`

Bingo!

thanks for this, this works well in 2D, but the thing is that the profile is also tilted. Furthermore, the twist can be more than 90 degrees, for example it could even be something like a full twist + more like 372 degrees, depending on helix.

Somehow I think that this information should be somewhere in the curve. Because when I orient a profile perpendicular to the rail, it gets the same twists I see when doing the sweep1

https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_SweepOneRail.htm

This is all the information I would be able to get and it doesn’t seem to contain the info you need.

Does the flatworm script from the documentation help?

https://developer.rhino3d.com/guides/rhinopython/primer-101/8-geometry/#861-ellipses

I haven’t fully understood you question or the above script so sorry if this is not helpful!

If I can somehow calculate the angle difference between Curve frames, then I think I should be able to derive the information from the curve itself. Rhino.Geometry.Curve.PerpendicularFrameAt() is giving me frames that are twisted the same way as the sweep1rail.

EDIT: Something like this altough this doesn’t give me the accurate angle:

```
import rhinoscriptsyntax as rs
def getAngle():
curve = rs.GetObject("select curve to analyze")
curve = rs.coercecurve(curve)
x=[] #curve frame x-axis
a=0 #total angle
d=200 #divisions
for i in range(0,d):
result, frame = curve.PerpendicularFrameAt(i/d)
x.append(frame.XAxis)
for i in range(0,d-1):
a+=rs.VectorAngle(x[i],x[i+1])
return a
print getAngle()
```

Yes could be helpful, not sure if I understand everything that is going on in that script, but it does twist the profile in the same way as sweep1 freeform does. Edit: upon closer investigation, it doesn’t

I’m a bit confused, if you’re already going through the trouble of clicking curves for reference frames, then why not perform three extra operations to check the angle? I was under the impression that you needed a fully automatic way of finding the angle?

Either way, I think this is beyond my skillset to solve. I tried a couple of things programming wise but I didn’t get anywhere.

I’m not sure but I think rs.CurveFrame() should twist with the curve. So you might be able to just get the angle difference between the normal vectors start and end? Or am I way off in left field here?

The code with selecting a curve is just an example that I played with to test things. In the end I just create the curve based on certain specifications and then It should be somehow possible to get info on the total twist that the profile makes.

Right now if I would need to do this manually, I need to look very carefully how many times the profile is twisted and it is easy to make a mistake.

If I could get a frame perpendicular (which has the twist) plus a frame at that exact location without the twist but also perpendicular tot the curve then I have the angle at that point. Since there can be twists of more than 360 degrees I think that only measuring at the end of the curve does not give reliable info.

I tried. FrameAt() but this gives frames that slide along the curve (a bit like what happens when using OrientOncrv without the perpendicular option) Or do you think that I can still use those?

Hi Gijs,

maybe I’m confused but I get a twist angle of 145° from your sample. Now I wonder if this value still will be useful for the fabricator? However, in the attached file you’ll see how I’d try to solve that.

Jess

angle_of_twist.3dm (332.5 KB)

Thanks Jess, you’re right, and it exactly proves my point that it’s easy to make a mistake ;-). Indeed the profile here has turned 180-35 degrees instead of just 35. So basically I can shoot two vectors from the endpoint to one of the corners and measure their angle. I’ll see if I can make that work, should not be too difficult. What I will do is just use part of the helix only so that there will never be more than say 45 degrees twist and multiply that by the length of the complete helix.

As for the value to the manufacturer: They don’t yet know how to solve the issue, but fact is that it behaves like a freeform sweep, so in the end they need to know how much it needs to be modified per given length to correct for this twist.

Edit: thanks again everyone for the contributions. My scripted solution is probably not very elegant but it works by making the suggested sweeps with lines as in Jess’ example, extracting the brep edges and calculate the angle. As said I make it so that it only sweeps 1/10th of a rail and multiply the resulting value.

Hi Gijs,

If you are just dealing with regular helices and you know the parameters (radius, height and number of turns) then it should be possible to calculate the twist angle of a freeform sweep1 directly. But I’m not sure about the equation right now - maybe some bigger brains can help @dale ?

Seems like my question was already solved here as well:

So in code this would simplify it to:

```
result, frame1 = rail_crv.PerpendicularFrameAt(Parameter)
result, frame2 = rail_crv.FrameAt(Parameter)
vec1 = frame1.XAxis
vec2 = frame2.YAxis
angle = Rhino.Geometry.Vector3d.VectorAngle(vec1, vec2, frame1)
angle = math.degrees(angle)
```