Open RickBrice opened 4 months ago
Ping @civilx64 @aothms @peterrdf Any thoughts on this?
I have not taken an in-depth look but in general I think that:
no deviation in the position of the curve segment to the base curve axis is specified
in the docs.
Said another way,
How are these three cases distinguished using only the geometric representation?
Perhaps they cannot be determined by geometric representation only and the implementation needs to pull from the segment's design parameters in the business logic.
@RickBrice
When cross posting to the implementer's forum I had an idea. Perhaps defining these three different cases via business logic only and then running through Enrich4.3 would help illuminate how to define the corresponding representation? If the resulting output representation is not unique across the three cases then that would seem to prove my hypothesis re: business logic being required.
My expectation is that (unless the business logic differs only in redundent information) the output as geometrical representation is always unique. Note that although conversion from business logic towards geometrical representation is always the same when using Enrich, alternative geometric representations can represent the same business logic. i.e. another geometrical representation of the same business logic does not automatically mean business logic and geometrical representation are out-of-sync. Also note that although any business logic can be converted to a geometrical representation, not every geometrical representation could be represented in business logic.
@civilx64 I tend to agree with @peterrdf that the geometric representation is logically related to the business logic but not dependent upon the business logic for geometric calculations.
Taking this back one step, in the linear-placement-of-signal.ifc example, all the clothoid constants for the cant have positive values which means to me that the super elevation is always increasing over these segments. This is a contradiction to the business logic where the point of rotation is about the mid-point between rails so no super elevation. It seems to me the clothoid constants should be zero indicating no change in super elevation and at the same time alternate positive, negative, positive, negative values to indicate the rate of rail head rotation align the segments. These are the two issues I pose above. Am I still misunderstanding cant or is there something incorrect with the example?
@sergejmuhic can you offer any additional insights?
FWIW this is the LandXML file from which the IFC was generated from. https://github.com/ciro-vendrame/IFC4.x-IF/blob/bb0c11aeee64ea5db1e61843d64da3c82f41ad6a/tests/STN01/Dataset/Alignment_exchange.xml
@michelangelo-acca Thank you for pointing to the source LandXML file. It will be useful in working through this example data to understand proper implementation of cant.
@RickBrice I am slowly starting to see how the geometry representation is sufficient without looking at business logic. Something that clicked was considering the information provided by the preceding and following segments.
My next hypothesis is that your case 2 scenario listed above is not possible. Namely IfcSegmentedReferenceCurve always provides the cant - when we think of cant as the rotation described by RefDirection of the placement. If rotation is about the center of rails then we have cant only with no superelevation. This corresponds to the Z coordinate being 0. for segment n-1 and n+1. So in the graph above the yellow line should be coincident with the blue line as there is never any deviation in IfcSegmentedReferenceCurve from the BaseCurve IfcGradient - however there is rotation or "twist".
Similarly when Z stays 0. throughout the cant development the up direction of Placement.Axis never deviates from the Axis of IfcGradientCurve.
In the docs where it says the rotation is to be interpolated, that interpolation is done according to the segment type, e.g. linear interpolation for IfcClothoid.
By extension I think that the clothoid constant always defines the amount of rotation. If rotation is about low rail then this is the superelevation (elevation difference) at the centerline. If rotation is about centerline then this is the elevation amount that the low rail is "pushed down" and the high rail is "pushed up".
In other words the clothoid constant should never be 0.0 because it always provides the elevation difference corresponding to the required rotation. The Z coordinate of the next segment tells you whether that elevation difference takes place at the CL or the railheads.
@civilx64 I'm starting to come to the same conclusion.
Super elevation is defined by the elevation of the start of segments n and n+1.
Direction and magnitude of tilt is defined by segments n and n+1.
Rate of change of tilt and elevation (if applicable) is defined by the parent curve function.
It is interesting that IfcSegmentedReferenceCurve is the only alignment related curve where the geometry of an individual segment is dependent on the next segment.
I will dig into the C++ implementation over the next couple weeks and make the corrections. If you need the update sooner, let me know and I can reprioritze a few things.
Just as a feedback to the last comment. I agree only partly.
I do agree to:
This means that the business logic concerning the transition curve itself only defines its linear or non-linear behavior between start and end of an individual segment (better said start of the segment and start of the next segment)
I disagree that this is only true for IfcSegmentedReferenceCurve. Although in IfcCompositeCurve and IfcGradientCurve the individual segments define for respectively the x / y and z direction the same units it cannot be trusted that creating the segment (for horizontal or vertical alignment) will automatically generate a continous curve for both IfcCompositeCurve and IfcGradientCurve. The fact that these curves are continuous is however a requirement.
In my perception this gives us the same challenge for segments within an IfcCompositeCurve and IfcGradientCurve. I am not sure everybody is implementing this. We found we require in total three different segment scaling algorithms, there is however no consenses on how to scale a segment curve (maybe I should use the term profile) in cases of segments that do not generate a continuous IfcCompositeCurve, IfcGradientCurve or IfcSegmentedReferenceCurve. For me this is okay, there are several parts in IFC and AP242 where similar cases are not defined and everybody has fixed it somehow in their implementation.
We are in the middle of the Tunnel delivery, so bare with me. I have just partially read the original post. Maybe this was already answered.
The superelevation is the difference in elevation between the IfcGradientCurve and the IfcSegmentedReferenceCurve.
This is not always the case as different locales use their own approaches. Hence the rate of change of cant is just the rate of change of the inclination between the horizontal plane and the angle of the plane of the rails. This means that the IfcCurveSegment.Placement.Axis and .RefDirection are inclined at the cant angle as it is at the start of the segment. The next segment defines the next absolute cant value. Between these, the transition segment type (in your case a clothoid) defines the rate of change of this inclination angle (your cant).
2. Superelevation only along the segment
This is not defined by the IfcSegmentedReferenceCurve. As stated above, it is unfortunately not the same in all countries. The inclination angle (the cant), however, is always the definition written above.
both cases, the clothoid constant has a positive value. I think the second clothoid constant should have a negative value.
This is definitely weird since it seems that the exact same segment of the clothoid is used at the start and at the end. If it was cut in the opposite direction (-40 to 0), it would be okay. This would be much more visible if parameter (since we would have curvatures as values and it would be clearly visible that it goes from a certain radius to 0) values instead of length measures were used.
@peterrdf
... it cannot be trusted that creating the segment (for horizontal or vertical alignment) will automatically generate a continous curve for both IfcCompositeCurve and IfcGradientCurve. The fact that these curves are continuous is however a requirement.
Where in the documentation is continuity a requirement for IfcCompositeCurve and IfcGradientCurve? IfcTransitionCode allows for varying degrees of continuity between the segments that make up these overall curves. Perhaps this is a requirement specific to the rail domain?
In my experience with roads and bridges it very common to have angular breaks between alignment segments. This most commonly occurs with vertical alignments but can happen with horizontal as well. I have also seen multiple examples (including a major program currently in design) with a complete break in the horizontal alignment location where it shifts from a crown line to an outside pavement edge 12 ft (3.6 m) to the left or right.
In the documentation https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/HTML/lexical/IfcCompositeCurve.htm it states: "An [IfcCompositeCurve] is a continuous curve composed of curve segments."
Thanks to everyone for your feedback. I think I better understand cant and IfcSegmentedReferenceCurve. The only thing that still confuses me as why the clothoid constant is always positive in the linear-placement-of-signal.ifc example.
This is definitely weird since it seems that the exact same segment of the clothoid is used at the start and at the end. If it was cut in the opposite direction (-40 to 0), it would be okay.
If the cut were from (-40 to 0), the direction of the cut is the same as if it were cut from (0 to 40). The derivative of the clothoid function is the same in both cases indicated an increase in tilt rotation.
If the cut were from (-40 to 0), the direction of the cut is the same as if it were cut from (0 to 40). The derivative of the clothoid function is the same in both cases indicated an increase in tilt rotation.
You are right of course. I had two parallel data streams in my mind where I was first thinking of a cut from 40 to 0, but then thought of -40 to 0 as being the option I wanted to bring up. Unfortunately, I started writing the former scenario first and did not correct back.
In my excuse, I was working on something else and wrote the answers on the side. đŸ˜„
Back to the original, if the cut is from -40 to 0, the derivative is the same, I agree but the curvature starts at negative curvature (radius of curvature) and increases to 0 (straight). Not having the information to which side (CW or CCW) the end of the circular arc transitions to the straight, two options are viable. Actually even four because we could cut the same clothoid in the negative direction. But the results are two, either we turn CW or CCW to get to the straight.
I am not arguing against a negative clothoid constant. Just trying to explain that there are two alternatives to transition to the straight.
EDIT: In the end, it is all about the parametrisation of the segment. The IfcCurveSegment.Placement has to have the right RefDirection set.
Hi @RickBrice
If NO for all three, I'll close this issue
@evandroAlfieri
After the discussion above, do you still have doubts on this issue?
Yes. The concerns with superelevation have been resolved, though I think some work is needed on the documentation. In an offline conversation with @civilx64, I think he is working on this.
Do you still think the linear-placement-of-signal.ifc example is wrong?
Yes. I think the clothoid constants for #2632 and #2676 should be negative values. Segments #2676 and #2671 are transitioning from a full twist section to a no-twist section. The rate of change is decreasing, so the clothoid constant should be a negative value.
Do you think there is the need to improve the documentation? And where?
Yes. I think @civilx64 is working on this with respect to cases with rotation centered on the base curve. Some opportunities for improving the documentation exist. Below are things I have struggled with in IfcSegmentedReferenceCurve but haven't had an opportunity to draft revised text.
A deviating explicit position of a curve segment (IfcCurveSegment.Placement) from the axis of the base curve produces a superelevation i.e. depression or elevation from the axis of the base curve. The superelevation rate of change is directly proportionate to the curve segment parent curve curvature gradient equation (IfcCurveSegment.ParentCurve) in the linear parameter space of the base curve.
This is confusing. The curve segment parent curve curvature gradient equation in the linear parameter space of the base curve only defines the superelevation rate of change when there is different deviating explicit position of the curve segment from the axis of the basis curve for consecutive segments. In other words, the slope of the parent curve function defines the superelevation rate of change only when consecutive segments have different values of IfcCurveSegemnt.Placement.Location[2] (the "Y" ordinate), otherwise the superelevation along the segment is constant (either zero for twist about the base curve or some non-zero value for twist about one of the rail heads, or other location).
If no deviation in the position of the curve segment to the base curve axis is specified, the axes (Axis and RefDirection) directions of IfcAxis2Placement are interpolated between the initial curve segment placement and the placement of the subsequent curve segment.
Also confusing and possibly inaccurate. Does "no deviation specified" mean defined with a value of exactly 0.0? The Axis and RefDirection define the rotation of the rail heads relative to the base curve. As I understand IfcSegmentedReferenceCurve, the rotation at the start of each segment, and the rate of change along the segment are independent of the superelevation. IfcCurveSegmentPlacement.Location[2] defines superelevation and IfcCurveSegment.Placement.Axis defines rotation.
After all my questions about IfcSegmentedReferenceCurve and the feedback I've received from some very dedicated and generous individuals in the bSI community, I think I understand this topic well. I apologize for not having the time to go back and resolve all my github issues on this topic. I plan to write up resolutions to all of them and close them out.
This is confusing.
The wording chosen is confusing, I agree. The rate of change should be guiding the IfcCurveSegment.Placement.Axis
. I have no idea where this documentation is from but the reason you state is exactly why originally I did not document it like that.
As I understand IfcSegmentedReferenceCurve, the rotation at the start of each segment, and the rate of change along the segment are independent of the superelevation. IfcCurveSegmentPlacement.Location[2] defines superelevation and IfcCurveSegment.Placement.Axis defines rotation.
Yes.
originally I did not document it like that
how did you document it originally?
The rate of change should be guiding the
IfcCurveSegment.Placement.Axis
.
If IfcCurveSegment.Placement.Location[2] is different for consecutive segments is the superelevation rate of change is the same rate as for IfcCurveSegment.Placement.Axis
? I've assumed yes. So, if the parent curve is IfcThirdOrderPolynomialSpiral
, the superelevation along the segment would vary as shown below. If not, what is the rate of change of superelevation? linear?
@RickBrice you can make your proposal directly here
Feel free to coordinate with @civilx64 to add his 2 new figures
At the same link you can go back in time to see the history of that definition.
I'm not sure if there are problems with the linear-placement-of-signal.ifc example or a lack of understanding of IfcSegmentedReferenceCurve and cant on my part. It may be both. I make this post to begin the discussion.
Issue 1 - Clothoid constant for linear transitions
Here is a plot of cant values based on the business logic defined in the IfcAlignmentCantSegment entitites.
There are clearly regions where the cant is increasing, constant, then decreasing. The geometry of the first transition is defined by
The cant is then constant then decreases back to zero. The decreasing cant geometry is defined by
In both cases, the clothoid constant has a positive value. I think the second clothoid constant should have a negative value. Such is the case for the ACCA sleeper linear placement example from https://github.com/buildingSMART/ifc-gherkin-rules/issues/213#issue-2350530096.
Issue 2 - Point of rotation
From the graph above based on the business logic, the point of rotation is at the mid-point between the rails. For the first curve, the right rail goes up and the left rail goes down equal amounts meaning the (1/2)Cant value from Figure 8.9.3.62.A is equal to zero. However, this figure implies the point of rotation is at one of the rails.
My understanding of cant is that the IfcSegmentedReferenceCurve.CurveSegment.ParentCurve provides the geometric definition for both the superelevation and the cross-slope (Axis direction) between rail heads along the length of the segment.
From IfcSegmentedReferenceCurve
The superelevation is the difference in elevation between the IfcGradientCurve and the IfcSegmentedReferenceCurve. All of the IfcCurveSegment for this IfcSegmentedReferenceCurve have Position with z=0.0 which suggests there is no superelevation at the start of each segment. For segments with IfcLine parent curves, the superelvation remains 0.0 over the length of the segment. However, for segments with IfcClothoid parent curve, the cant should increase (or decrease if negative constants are used) over the length of the segment. This is not consistent with the rotation at the mid-point between the rails.
Here is the plot the elevations for the IfcSegmentReferenceCurve using IfcOpenShell based on my understanding of IfcSegmentedReferenceCurve. There are linearly increasing elevations wherever the parent curve is IfcClothoid.
Additionally, from IfcSegmentedReferenceCurve
For all of the segments, deviation is specified as 0.0 so I take that to be "no deviation". In this case, the Axis and RefDirection are to be interpolated in an unspecified way. The parent curve provides that interpolation regardless of the curve segment position as discussed at the end of https://github.com/buildingSMART/IFC4.x-IF/issues/145#issuecomment-2169089806.
It seems that there are cases when the IfcSegmentedReferenceCurve.IfcCurveSegment.Parent curve defines
The ACCA sleeper example seems to be Case 1. The linear-placement-of-signal example seems to be Case 3. Case 2 seems to occur only if "no deviation in the position of the curve segment to the base curve axis is specified".
How are these three cases distinguished using only the geometric representation?
@civilx64 @evandroAlfieri @michelangelo-acca @peterrdf @aothms