Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need help computing cant geometry from IfcSegmentedReferenceCurve #128

Closed
RickBrice opened this issue Nov 17, 2023 · 7 comments
Closed

Need help computing cant geometry from IfcSegmentedReferenceCurve #128

RickBrice opened this issue Nov 17, 2023 · 7 comments

Comments

@RickBrice
Copy link

Based on our conversation during the Nov 16, 2023 IF meeting, the following are hand calculations for the Cartesian Position of Sleeper_01 listed at https://github.com/buildingSMART/IFC4.x-IF/tree/main/IFC-files/Linear-placement-sleepers/ACCA.

@peterrdf Please help me understand how to perform these calculations correctly.

The IfcLinearPlacement for Sleeper_01 is defined as

#2707 = IFCLINEARPLACEMENT(#2708, #2712, $);
#2708 = IFCLOCALPLACEMENT(#2495, #2711);
#2709 = IFCDIRECTION((0., 0., 1.));
#2710 = IFCDIRECTION((1., 0., 0.));
#2711 = IFCAXIS2PLACEMENT3D(#15, #2709, #2710);
#2712 = IFCAXIS2PLACEMENTLINEAR(#2713, #2714, $);
#2713 = IFCPOINTBYDISTANCEEXPRESSION(IFCNONNEGATIVELENGTHMEASURE(425.), 0., $, 0., #2617);

The IfcLinearPlacement.RelativePlacement.Axis vector is prescribed. IfcLinearPlacement.RelativePlacement.RefDirection is not provided and is therefore tangent to the curve (See 8.9.3.4 "If RefDirection is omitted, the direction is taken from the curve tangent at Location."). Since IfcLinearPlacement.RelativePlacement.Location is an IfcPointByDistanceExpression with BasisCurve referencing#2617, the IfcSegmentedReferenceCurve, the IfcLinearPlacement.RelativePlacement.RefDirection is tangent to the curve which should include a non-zero Z component because the cant segment is changing the basis curve elevation from 0.0 to 0.5 between u = 400 and u = 449.99999. These calculations and the reported example placements do not have non-zero RefDirection.Z.

Plan View - IfcCompositeCurve

#2569 = IFCCOMPOSITECURVE((#2570, #2581, #2591), .U.);
#2570 = IFCCURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE., #2573, IFCNONNEGATIVELENGTHMEASURE(0.), IFCNONNEGATIVELENGTHMEASURE(400.), #2574);
#2571 = IFCCARTESIANPOINT((0., 0.));
#2572 = IFCDIRECTION((1., 0.));
#2573 = IFCAXIS2PLACEMENT2D(#2571, #2572);
#2574 = IFCLINE(#2575, #2576);
#2575 = IFCCARTESIANPOINT((0., 0.));
#2576 = IFCVECTOR(#2577, 1.);
#2577 = IFCDIRECTION((1., 0.));
#2581 = IFCCURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE., #2584, IFCLENGTHMEASURE(0.), IFCLENGTHMEASURE(150.), #2585);
#2582 = IFCCARTESIANPOINT((400., 0.));
#2583 = IFCDIRECTION((1., 0.));
#2584 = IFCAXIS2PLACEMENT2D(#2582, #2583);
#2585 = IFCCLOTHOID(#2588, -273.861278752584);
#2586 = IFCCARTESIANPOINT((0., 0.));
#2587 = IFCDIRECTION((1., 0.));
#2588 = IFCAXIS2PLACEMENT2D(#2586, #2587);
#2591 = IFCCURVESEGMENT(.DISCONTINUOUS., #2594, IFCLENGTHMEASURE(0.), IFCLENGTHMEASURE(-400.), #2595);
#2592 = IFCCARTESIANPOINT((549.662851380011, -7.48795505445));
#2593 = IFCDIRECTION((9.88771077936042E-1, -1.49438132473604E-1));
#2594 = IFCAXIS2PLACEMENT2D(#2592, #2593);
#2595 = IFCCIRCLE(#2598, 500.000000000002);
#2596 = IFCCARTESIANPOINT((-74.7190662368024, -494.385538968023));
#2597 = IFCDIRECTION((1.49438132473604E-1, 9.88771077936042E-1));
#2598 = IFCAXIS2PLACEMENT2D(#2596, #2597);

PlanView

Compute placement at u = 425 m along the composite curve

Distance along curve $$d=425-400=25.0$$

Compute coordinate at d.
$$x=C_x + A\sqrt{\pi}(\int_{0}^{u}\cos(\pi\frac{At^2}{2|A|})dt)$$

$$y=C_y+A\sqrt{\pi}(\int_{0}^{u}\sin(\pi\frac{At^2}{2|A|})dt)$$ $$C_x = 400.0, C_y=0.0$$ $$A=-273.861278752584$$ $$s=Au\sqrt{\pi}, u=1.0, s=-273.861278752584\sqrt{\pi}=-485.40647841 $$

Parametric value at end of curve $$u = \frac{25.0}{485.40647841}=0.051503226$$

Point on clothoid
$$x=C_x + A\sqrt{\pi}(\int_{0}^{u}\cos(\pi\frac{At^2}{2|A|})dt) = 400.0 + (-273.861278752584)\sqrt{\pi}(\int_{0}^{0.051503226}\sin(\pi\frac{-273.861278752584t^2}{2|-273.861278752584|})dt)=424.999956527$$

$$y=C_y + A\sqrt{\pi}(\int_{0}^{u}\cos(\pi\frac{At^2}{2|A|})dt) = 0.0 + (-273.861278752584)\sqrt{\pi}(\int_{0}^{0.051503226}\cos(\pi\frac{-273.861278752584t^2}{2|-273.861278752584|})dt)=-0.034722183$$

$$z=0.00$$

Compute tangent to curve at d=25.0 (this is the RefDirection)

Radius at end of curve $$R=\frac{A^2}{L} = \frac{(-273.861278752584)^2}{150}=500.0$$

Total sweep angle of clothoid (use negative Radius for curve to right)
$$\Delta=\frac{L}{2R}=\frac{150}{(2)(-500)}=-0.15$$

Sweep angle from start to d=25.0
$$\delta={(\frac{d}{L})}^2\Delta=({\frac{25}{150}})^2(-0.15)=-0.0041666666$$

Tangent vector
$$dx = cos(-0.004166666)=0.999991319$$
$$dy = sin(-0.004166666)=-0.00416665$$

Placement at d=25.0

  • Axis [0,0,1]
  • RefDirection [ 0.999991319, -0.004166655, 0]
  • Location [424.999956527, -0.034722183, 0]

Profile Elevation View - IfcGradientCurve

#2603 = IFCGRADIENTCURVE((#2604), .U., #2569, #2616);
#2604 = IFCCURVESEGMENT(.DISCONTINUOUS., #2607, IFCNONNEGATIVELENGTHMEASURE(0.), IFCNONNEGATIVELENGTHMEASURE(950.), #2608);
#2605 = IFCCARTESIANPOINT((0., 0.));
#2606 = IFCDIRECTION((1., 0.));
#2607 = IFCAXIS2PLACEMENT2D(#2605, #2606);
#2608 = IFCLINE(#2609, #2610);
#2609 = IFCCARTESIANPOINT((0., 0.));
#2610 = IFCVECTOR(#2611, 1.);
#2611 = IFCDIRECTION((1., 0.));
#2614 = IFCCARTESIANPOINT((950., 0.));
#2615 = IFCDIRECTION((1., 0.));
#2616 = IFCAXIS2PLACEMENT2D(#2614, #2615);

Profile

u = 426 m along the BaseCurve (which is the IfcCompositeCurve). Because the gradient curve is flat at elevation 0.0, the Cartesian position is the same as for the composite curve

  • Axis [0,0,1]
  • RefDirection [ 0.999991319, -0.004166655, 0]
  • Location [424.999956527, -0.034722183, 0]

Cant - IfcSegmentedReferenceCurve

#2617 = IFCSEGMENTEDREFERENCECURVE((#2618, #2628, #2639, #2650), .U., #2603, #2666);
#2618 = IFCCURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE., #2621, IFCNONNEGATIVELENGTHMEASURE(0.), IFCNONNEGATIVELENGTHMEASURE(400.), #2622);
#2619 = IFCDIRECTION((0., 0., 1.));
#2620 = IFCDIRECTION((1., 0., 0.));
#2621 = IFCAXIS2PLACEMENT3D(#15, #2619, #2620);
#2622 = IFCLINE(#2623, #2624);
#2623 = IFCCARTESIANPOINT((0., 0.));
#2624 = IFCVECTOR(#2625, 1.);
#2625 = IFCDIRECTION((1., 0.));
#2628 = IFCCURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE., #2632, IFCNONNEGATIVELENGTHMEASURE(0.), IFCNONNEGATIVELENGTHMEASURE(49.999993741124), #2633);
#2629 = IFCCARTESIANPOINT((400., 0., 0.));
#2630 = IFCDIRECTION((0., 0., 1.));
#2631 = IFCDIRECTION((9.99950003737172E-1, 9.99950128908449E-3, 0.));
#2632 = IFCAXIS2PLACEMENT3D(#2629, #2630, #2631);
#2633 = IFCCLOTHOID(#2636, 70.7106692672674);
#2634 = IFCCARTESIANPOINT((0., 0.));
#2635 = IFCDIRECTION((1., 0.));
#2636 = IFCAXIS2PLACEMENT2D(#2634, #2635);
#2639 = IFCCURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE., #2643, IFCNONNEGATIVELENGTHMEASURE(0.), IFCNONNEGATIVELENGTHMEASURE(100.000006258876), #2644);
#2640 = IFCCARTESIANPOINT((449.999993741124, 5.E-1, 0.));
#2641 = IFCDIRECTION((0., -5.54700196225229E-1, 8.32050294337844E-1));
#2642 = IFCDIRECTION((1., 0., 0.));
#2643 = IFCAXIS2PLACEMENT3D(#2640, #2641, #2642);
#2644 = IFCLINE(#2645, #2646);
#2645 = IFCCARTESIANPOINT((0., 5.E-1));
#2646 = IFCVECTOR(#2647, 1.);
#2647 = IFCDIRECTION((1., 0.));
#2650 = IFCCURVESEGMENT(.DISCONTINUOUS., #2654, IFCNONNEGATIVELENGTHMEASURE(0.), IFCNONNEGATIVELENGTHMEASURE(400.), #2655);
#2651 = IFCCARTESIANPOINT((550., 5.E-1, 0.));
#2652 = IFCDIRECTION((-6.93374703582761E-4, -5.54699762866209E-1, 8.32050294337844E-1));
#2653 = IFCDIRECTION((9.99999218750915E-1, -1.24999902343864E-3, 0.));
#2654 = IFCAXIS2PLACEMENT3D(#2651, #2652, #2653);
#2655 = IFCCLOTHOID(#2658, -565.685424949238);
#2656 = IFCCARTESIANPOINT((0., 1.25E-3));
#2657 = IFCDIRECTION((1., 0.));
#2658 = IFCAXIS2PLACEMENT2D(#2656, #2657);
#2663 = IFCCARTESIANPOINT((950., 0., 0.));
#2664 = IFCDIRECTION((0., 0., 1.));
#2665 = IFCDIRECTION((1., 0., 0.));
#2666 = IFCAXIS2PLACEMENT3D(#2663, #2664, #2665);

Profile_with_cant

At start of cant segment 2 (#2628), u = 400 m

  • Axis [0,0,1]
  • RefDirection [9.99950003737172E-1, 9.99950128908449E-3, 0.]
  • Location [400., 0., 0.]

At start of cant segment 3 (#2639), u = 449.999993741124 m

  • Axis [0., -5.54700196225229E-1, 8.32050294337844E-1]
  • RefDirection [1., 0., 0.]
  • Location [449.999993741124, 5.E-1, 0.]

Assume linear transition along cant segment 2. Compute Axis, RefDirection, and Location at u = 425 m

Let d = 425 - 400 = 25 m, distance from start of cant segment 2

  • Axis.X = 0 + (0-0)(25/49.99999) = 0
  • Axis.Y = 0 + (-5.54700196225229E-1 - 0)(25/49.99999) = -0.27735013
  • Axis.Z = 1 + (8.32050294337844E-1 - 1)(25/49.99999) = 0.91602514

Repeat with similar calculations for RefDirection and Location

  • Axis [0.0, -0.27735013, 0.91602514]
  • RefDirection [0.99997500, 0.004999753, 0.000000000]
  • Location [424.9999969, 0.250000031, 0]

At this point, I don't know what to do. How are the Axis, RefDirection, and Location determined from the IfcSegmentReferenceCurve.Segments combined with the Axis, RefDirection, and Location from the IfcGradientCurve.Segments to get the resulting IfcLinearPlacement for Sleeper_01?

My best guess is shown in the following calculations, but the end result does not match those reported for the sleeper placement example.

Gradient Curve

  • Axis [0,0,1]
  • RefDirection [ 0.999991319, -0.004166655, 0]
  • Location [424.999956527, -0.034722183, 0]
In matrix form, g = [ 0.999991319     0.004166655    0   424.999956527 ]
                    [ -0.004166655    0.999991319    0   -0.034722183  ]
                    [     0               0          1         0       ]
                    [     0               0          0         1       ]

Segmented Reference Curve, cant

  • Axis [0.0, -0.27735013, 0.91602514]
  • RefDirection [0.99997500, 0.004999753, 0.000000000]
  • Location [424.9999969, 0.250000031, 0]
                       RefDir             Y             Axis          Location
In matrix form, c = [0.99997500    -0.004999753          0           424.9999969 ]
                    [0.004999753    0.91602514     -0.27735013       0.250000031 ]
                    [    0          0.27735013      0.91602514            0      ]
                    [    0               0               0                1      ]

My best guess is to do the following:

  • Set c(1,4) = 0 so Location.X from matrix [g] is not altered
  • Swap c(2,4) and c(3,4) because Y in the "Distance along - Elevation" Plane is Location.Z in 3D
  • Let c' = the modified matrix [c]
  • Multiply [g][c'] to apply cross slope and tilt due to cant to the gradient curve position
Let c' = c modified as described above.

        RefDir             Y           Axis          Location
c' = [0.99997500    -0.004999753          0               0     ]
     [0.004999753    0.91602514     -0.27735013           0     ]
     [    0          0.27735013      0.91602514     0.250000031 ]
     [    0               0               0               1     ]

                  RefDir           Y          Axis          Location
p = [g][c'] = [ 0.999999653  -0.00118305  -0.001107643  424.999956527 ]
              [ 0.000833167   0.91602514  -0.27735013    -0.034722183 ]
              [ 0.000000000   0.27735013   0.91602514     0.250000031 ]
              [ 0.000000000   0.00000000   0.000000000    1.000000000 ]

My calculations for Sleeper_01 placement is:

  • Axis (-0.001107643, -0.27735013, 0.91602514)
  • RefDirection (0.999999653, 0.000833167, 0.0)
  • Location (424.999956527, -0.034722183, 0.250000031)

Compare to the value reported at https://github.com/buildingSMART/IFC4.x-IF/tree/main/IFC-files/Linear-placement-sleepers/ACCA

Sleeper_01

  • Axis (-1.41984738033722E-3, -2.89780705497746E-1, 9.57092015824312E-1)
  • RefDirection (9.99987996536315E-1, -4.89967175285863E-3, 0.)
  • Location (424.999956597257, -3.47221791639346E-2, 2.50000031294384E-1)

The values are similar but not exactly the same. The RefDirection.Y values have opposite signs - this is concerning.

@michelangelo-acca I am puzzled why the RefDirection for Sleeper_01 and Sleeper_02 are the same when the sleepers are 1 m apart on a curve. Also, why are the RefDirection.Z values equal to zero. The IfcLinearPlacement.RelativePlacement.RefDirection is not provided so the default is tangent to the curve, which is increasing in elevation between u = 400 and u = 499.99999.

@peterrdf
Copy link
Collaborator

peterrdf commented Nov 17, 2023

Hi @RickBrice, thank you for your very detailed example. Sorry I have to break it down a bit to understand where the differences start.

Except for some very small differences we agree on the location of Sleeper_01 (first looking at the GradientCurve). The first noticible difference is in the RefDirection values. I will check them and also take into account you valid point on having the same RefDirection for both placements (that are 1 meter apart) what does not make sense (it looks like the RefDirection could be derived from the segmented curve instead of from the calculated curve, what is of course incorrect).

Thanks, I will first investigate these 2 points and come back on this ASAP. Afterwards we can go into the SegmentedReference curve

@RickBrice
Copy link
Author

<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script>

@peterrdf - You said something during the IF meeting last week that I didn't understand. After listening to the recording several times the light came on. I am now able to match the published Cartesian Position data very closely. Thank you for your help

The calculations that follow highlight what I was doing incorrectly, implements the calculation you suggested, and ends with some items that are problematic.

Plan View - IfcCompositeCurve

No change to the calculations from earlier post

Placement at u = 425 along curve, d=25.0 from start of clothoid

  • Axis [0,0,1]
  • RefDirection [ 0.999991319, -0.004166655, 0]
  • Location [424.999956527, -0.034722183, 0]

Profile Elevation View - IfcGradientCurve

No change to the calculations from earlier post

u = 425 m along the BaseCurve (which is the IfcCompositeCurve). Because the gradient curve is flat at elevation 0.0, the Cartesian position is the same as for the composite curve

  • Axis [0,0,1]
  • RefDirection [ 0.999991319, -0.004166655, 0]
  • Location [424.999956527, -0.034722183, 0]
In matrix form, g = [ 0.999991319     0.004166655    0   424.999956527 ]
                    [ -0.004166655    0.999991319    0   -0.034722183  ]
                    [     0               0          1         0       ]
                    [     0               0          0         1       ]

Cant - IfcSegmentedReferenceCurve

Profile_with_cant

Compute the placement for Sleeper_01.

The linear placement is

#2706 = IFCTRACKELEMENT('3aHDScfgLAZv4MSOT7htTa', #1, 'Sleeper_01', $, $, #2707, #2715, $, .SLEEPER.);
#2707 = IFCLINEARPLACEMENT(#2708, #2712, $);
#2708 = IFCLOCALPLACEMENT(#2495, #2711);
#2709 = IFCDIRECTION((0., 0., 1.));
#2710 = IFCDIRECTION((1., 0., 0.));
#2711 = IFCAXIS2PLACEMENT3D(#15, #2709, #2710);
#2712 = IFCAXIS2PLACEMENTLINEAR(#2713, #2714, $);
#2713 = IFCPOINTBYDISTANCEEXPRESSION(IFCNONNEGATIVELENGTHMEASURE(425.), 0., $, 0., #2617);
#2714 = IFCDIRECTION((-1.10764345921695E-3, -2.89782067028521E-1, 9.57092015824312E-1));

Note IfcAxis2PlacementLinear.RefDirection is not provided (#2712)

At start of cant segment 2 (#2628), u = 400 m

  • Axis [0,0,1]
  • RefDirection [9.99950003737172E-1, 9.99950128908449E-3, 0.]
  • Location [400., 0., 0.]

At start of cant segment 3 (#2639), u = 449.999993741124 m

  • Axis [0., -5.54700196225229E-1, 8.32050294337844E-1]
  • RefDirection [1., 0., 0.]
  • Location [449.999993741124, 5.E-1, 0.]

Assume linear transition along cant segment 2. Compute Axis, RefDirection, and Location at u = 425 m

Let d = 425 - 400 = 25 m, distance from start of cant segment 2

This is where I went wrong

The components of the Axis vector should not be linearly interpolated

  • Axis.X = 0 + (0-0)(25/49.99999) = 0 Wrong
  • Axis.Y = 0 + (-5.54700196225229E-1 - 0)(25/49.99999) = -0.27735013 Wrong
  • Axis.Z = 1 + (8.32050294337844E-1 - 1)(25/49.99999) = 0.91602514 Wrong

The Axis vector is in a plane that is orthogonal to the cant adjusted gradient curve at u = 425.

Axis

The angle that the Axis vector makes with the Z axis is linearly interpolated.

$$ \theta_{400} = tan^{-1}(\frac{1}{0}) = \frac{\pi}{2} = 1.5707963 $$

$$ \theta_{449.99} = tan^{-1}(\frac{-0.5547}{0.83205}) = 2.1587989 $$

Linearly interpolate the tilt angle

$$ \theta_{425} = 1.5707963 + (2.1587989-1.5707963)*25/49.99999 = 1.8647976 $$

  • Axis.X = 0
  • Axis.Y = cos(1.8647976) = -0.289784
  • Axis.Z = sin(1.8647976) = 0.957092

The cant causes an elevation change of 0.5 between u = 400 and u = 449.999999.

The slope along the curve is

$$ slope = \frac{0.5}{(449.9999 - 400)} = 0.01 $$

The change in gradient curve elevation due to cant is

$$ Location.Y = 0 + slope*25 = 0.25000031 $$

The cant matrix is

                       RefDir             Y             Axis          Location
In matrix form, c = [    1                0              0               0      ]
                    [    0           -0.957092      -0.289784       0.250000031 ]
                    [    0           -0.289784       0.957092            0      ]
                    [    0               0               0               1      ]

This matrix has elevation as Y because of the 2.5D approach to alignments. Move Location.Y to Location.Z and call the resulting matrix [c']

                       RefDir             Y             Axis          Location
In matrix form, c' = [    1               0               0               0      ]
                     [    0           -0.957092      -0.289784            0      ]
                     [    0           -0.289784       0.957092       0.250000031 ]
                     [    0               0               0               1      ]

The position of the Sleeper_01 is the product of [g][c']

                  RefDir           Y          Axis          Location
p = [g][c'] = [ 0.999991319   0.003987872  -0.001107643  424.999956527 ]
              [ -0.00416665   0.957083713  -0.289782067   -0.034722183 ]
              [ 0.000000000   0.289784168   0.957092016    0.250000031 ]
              [ 0.000000000   0.00000000    0.000000000    1.000000000 ]

The position for Sleeper_01 is:

  • Axis (-0.001107643, -0.289782067, 0.95709201)
  • RefDirecition (0.999991319, -0.00416665, 0.0)
  • Location (424.999956527, -0.034722183, 0.250000031)

Compare to the value reported at https://github.com/buildingSMART/IFC4.x-IF/tree/main/IFC-files/Linear-placement-sleepers/ACCA

Sleeper_01

  • Axis (-1.41984738033722E-3, -2.89780705497746E-1, 9.57092015824312E-1)
  • RefDirection (9.99987996536315E-1, -4.89967175285863E-3, 0.)
  • Location (424.999956597257, -3.47221791639346E-2, 2.50000031294384E-1)

There is now very good argeement in the results.

However, this is more to the story

Item 1

The exact direction of IfcLinearPlacement.RelativePlacement.Axis is given as:
#2714 = IFCDIRECTION((-1.10764345921695E-3, -2.89782067028521E-1, 9.57092015824312E-1));

The resulting placement of Sleeper_01 should match this exactly. The datum Axis from the ACCA file has Axis.X = -0.001419. Close to -0.0011076, but not exactly the same.

Item 2

IfcLinearPlacement.RelativePlacement.RefDirection is not povided and therefore defaults to the tangent to the curve. The segmented reference curve defines an uphill change in elevation from 0.0 to 0.5 between 400 to 499.99999. The RefDirection vector should have a non-zero Z component.

Accounting for the slope, Sleeper_01 Cartesian Position is

  • Axis (-0.001107643, -0.289782067, 0.957092016)
  • RefDirection (0.999941324, -0.004166446, 0.009999501)
  • Location (424.999956527, -0.034722183, 0.250000031)
  • Y (0.001090047, 0.957091684, 0.289783228)

Item 3
Placements are reported for Sleeper_01 at 425 m along the curve and Sleeper_02 at 426 m along the curve. The plan view of the curve, defined by IfcCompositeCurve, is a clothoid at these locations. RefDirection is tangent to the curve at these locations and should not be the same for both sleepers.

I calculation the Cartesian Position of Sleeper_02, accounting for the uphill slope along the curve as discussed in Item 2, as

  • Axis (-0.001150588, -0.301017141, 0.953618035,)
  • RefDirection (0.999939849, -0.004506426, 0.009999501)
  • Location (425.999947108, -0.039057726, 0.260000033)
  • Y (0.001287449, 0.953617430, 0.301018503)

Item 4
The second segment of the segment reference curve is a clothoid.
#2633 = IFCCLOTHOID(#2636, 70.7106692672674);

The clothoid constant A = 70.7106682672674 is not used in any of the calculations.

What is this value supposed to be used for?

@peterrdf
Copy link
Collaborator

@RickBrice thank you for finding this. Indeed we calculated values imprecise, i.e. based on segmented curves.

Whit a partly fix we find the following IfcLinearPlacement.CartesianPosition, please for no ignore the normal vectors

Sleeper 01:
#2789 = IFCAXIS2PLACEMENT3D(#2790, #2791, #2792);
#2790 = IFCCARTESIANPOINT((424.999956597257, -3.47221791639345E-2, 2.50000031294384E-1));
#2791 = IFCDIRECTION((-1.20743060590207E-3, -2.89781668427605E-1, 9.57092015824312E-1));
#2792 = IFCDIRECTION((9.9994132362817E-1, -4.16644629319093E-3, 9.9995012890845E-3));

Sleeper 02:
#2793 = IFCAXIS2PLACEMENT3D(#2794, #2795, #2796);
#2794 = IFCCARTESIANPOINT((425.999947193934, -3.90577211160139E-2, 2.60000032546159E-1));
#2795 = IFCDIRECTION((-1.35658923194275E-3, -3.01016282796109E-1, 9.53618035251677E-1));
#2796 = IFCDIRECTION((9.99939849239849E-1, -4.50642609585363E-3, 9.9995012890845E-3));

As mentioned the normal vectors are still off, this is for sure at least partly on our side. Position and Tangent seem to be 'almost' the same as your values. The difference is slightly larger than expected rounding issues but equal enough to think we are calculating the values in the same way.

So in this update we calculate for all transition curve types in horizontal alignment values exactly, we do not do this for vertical alignment and cant alignment yet (in this example no issue as wertical alignment and cant alignment have both a linear change)

Will fix this and come back to the other questions. Sorry it takes some time, I try to fix the found issues in the code and this takes some time.

@peterrdf
Copy link
Collaborator

Hi @RickBrice
I am now getting also similar Y vector, however the first component of the normal vector is quite different. I guess this is due to rounding issues, also as the determinant of your matrix is not exactly 1 with a difference of 0.0001.
Here my values
Axis {x=-0.010777806681878093 y=-0.28975610843763611 z=0.95703983015661631 }
RefDirection {x=0.99994132362816956 y=-0.0041664462931909289 z=0.0099995012890844968 }
Location {x=424.99995659725710 y=-0.034722179163934483 z=0.25000003129438392 }
Y {x=0.0010900384729498611 y=0.957
AddLinearPlacementCartesianPosition-20231129.zip
09144722349437 z=0.28978401175317564 }

Compared to your values:
Axis (-0.001107643, -0.289782067, 0.957092016)
RefDirection (0.999941324, -0.004166446, 0.009999501)
Location (424.999956527, -0.034722183, 0.250000031)
Y (0.001090047, 0.957091684, 0.289783228)

Attached the mini solution generating these values.

@RickBrice
Copy link
Author

Hi @peterrdf
This is great that we are getting similar results.

I'll look more closely to determine why the determinant of my matrix is not 1.0.

Regarding the normal vector being quite different, I understand this to mean the Axis vector. From the ACCA input file, the exact direction of the Axis vector is given

#2714 = IFCDIRECTION((-1.10764345921695E-3, -2.89782067028521E-1, 9.57092015824312E-1));

I expect the resulting matrix to have exactly these values. In your case, they are different. What could be the explanation for that?

@RickBrice
Copy link
Author

@peterrdf
I figured out why the determinant of my position matrix is not 1.0. For the given IfcAxis2PlacementLinear

#2712 = IFCAXIS2PLACEMENTLINEAR(#2713, #2714, $);

The IfcAxis2PlacementLinear.Axis is given and IfcAxis2PlacementLinear.RefDirection is omitted. First, I don't think this is valid (see #125).

IfcAxis2PlacementLinear.Axis is given as

#2714 = IFCDIRECTION((-1.10764345921695E-3, -2.89782067028521E-1, 9.57092015824312E-1));

By the specifications, the default IfcAxis2PlacementLinear.RefDirection is the tangent to the curve. We both compute it as

RefDirection {x=0.99994132362816956 y=-0.0041664462931909289 z=0.0099995012890844968}

Axis and RefDirection are not orthogonal. The dot product is 0.00967, leading to the determinant to be 0.99995.

The Axis you report differs from mine, which is why your get a determinant of 1.0. In my view, since the exact direction of Axis is given and it is not orthogonal to the required default RefDirection, the error is in the modeling, not the calculation of the placement.

If both IfcAxis2PlacementLinear.Axis and IfcAxis2PlacementLinear.RefDirection are omitted, then I compute Axis to be

Axis {x=-0.011206784726867754, y=-0.28972551595900053,z=0.95704416480033805}

which closely matches, but not exactly, your values

Axis {x=-0.010777806681878093 y=-0.28975610843763611 z=0.95703983015661631 }

We are getting closer, but many questions remain.

@RickBrice
Copy link
Author

The computation of cant geometry is explained with an example in #160 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants