Skip to content

Towards a common understanding of IfcLinearPlacement, IfcAxis2PlacementLinear, IfcPointByDistanceExpression, IfcOffsetCurveByDistances, IfcSectionedSurface, and IfcSectionedSolidHorizontal #1151

Description

@RickBrice

This issue consolidates discussions regarding IfcLinearPlacement, IfcAxis2PlacementLinear, and IfcPointByDistanceExpression in
buildingSMART/IFC4.x-IF#169
buildingSMART/ifc-gherkin-rules#506
buildingSMART/IFC4.x-IF#125
#732
#731
jwouellette/TPF-5_372-Unit_Test_Suite#15 (comment)

It also brings IfcOffsetCurveByDistances, IfcSectionedSurface and IfcSectionedSolidHorizontal into the discussion, with issues raised in https://github.com/RickBrice/IFC-Alignment-Geometry-Implementation-Guide/blob/main/5_OffsetCurves.md, https://github.com/RickBrice/IFC-Alignment-Geometry-Implementation-Guide/blob/main/8_LinearPlacement.md, and https://github.com/RickBrice/IFC-Alignment-Geometry-Implementation-Guide/blob/main/10_Sectioned_Surfaces_and_Solids.md.

IfcLinearPlacement, IfcAxis2PlacementLinear, IfcPointByDistanceExpression, IfcOffsetCurveByDistances, IfcSectionedSurface, and IfcSectionedSolidHorizontal all work together in many complex ways. A holistic discussion is needed.

To facilitate that discussion, @michelangelo-acca has developed a simple example. The example covers the following scenarios:

1 - User wants to place a sleeper along a track with cant

	- Parameters:
	
		- DistanceAlong 200
		- OffsetLateral 0
		- OffsetVertical 0
		- Rotation 0

	- The good:

		- The "tilt" is calculated automatically on import and not written in the file
	
	- The bad:
	
		- If the alignment changes, the sleeper correctly positions in its new place, but if fallback coordinates were originally written, they should be overridden with new ones 
	
2 - User wants to place a "vertical" object (i.e. a Sign) along the alignment

	- Parameters:
	
		- DistanceAlong 201
		- OffsetLateral 2
		- OffsetVertical 2.5
		- Rotation 0
		
	- The good:
	
		- We can override local Z axis to make global Z for making the object not be inclined by the slope at that point of the alignment
		
	- The bad:
	
		- In order to have a truly vertical OffsetVertical, we need to put 0 there, and the 2.5 in a LocalPlacement relative to the LinearPlacement, so the user will not see its 2.5 in the UI in correspondence of OffsetVertical
		
3 - User wants to place a rotated "vertical" object (i.e. a Sign) along the alignment	

	- Parameters:
	
		- DistanceAlong 202
		- OffsetLateral 2
		- OffsetVertical 2.5
		- Rotation 45
		
	- The good:
	
		- Same as previous case
		
	- The bad:
	
		- Same as previous case

Reference image

Image

Scenarios 2 and 3 are common. The IFC coding of Michaelangelo's solution is not (in my opinion) obvious or convenient. I've added two additional scenarios, 4 and 5 which are the same as 2 and 3 except that (a) the signs are on the right side of the alignment and (b) the local placement with z=2.5 is not used because the vertical offset is handled in the point by distance expression.

4 - User wants to place a "vertical" object (i.e. a Sign) along the alignment

	- Parameters:
	
		- DistanceAlong 201
		- OffsetLateral -2
		- OffsetVertical 2.5
		- Rotation 0
		
	- The good:
	
		- We can directly specify the lateral and vertical offset in IfcPointByDistanceExpression consistent with common civil engineering thinking.
		
	- The bad:
	
		- Validation Service and several implementations do not evaluate OffsetVertical in the global Z direction.
		
5 - User wants to place a rotated "vertical" object (i.e. a Sign) along the alignment	

	- Parameters:
	
		- DistanceAlong 202
		- OffsetLateral -2
		- OffsetVertical 2.5
		- Rotation 45
		
	- The good:
	
		- Same as previous case
		
	- The bad:
	
		- Same as previous case

The example model
UTAlignmentSimpleSlope_Modified.zip

From my background in highway and bridge engineering, I would instinctively locate the sign relative to the gradient curve with

#15296 = IFCSIGNAL('3S_c_fxJD5UuVShHH7YMXt', #1, 'a vertical sign (right)', $, $, #15297, #15306, $, .VISUAL.);
#15297 = IFCLINEARPLACEMENT($, #15303, #15351);
#15303 = IFCAXIS2PLACEMENTLINEAR(#15304, #15305, $);
#15304 = IFCPOINTBYDISTANCEEXPRESSION(IFCLENGTHMEASURE(201.), -2., 2.5, 0., #5208); /* REQUIRES OffsetVertical TO BE GLOBAL-Z DIRECTION */
#15305 = IFCDIRECTION((0., 0., 1.)); /* Forces the orientation of the placed sign to be vertical */
#15306 = IFCPRODUCTDEFINITIONSHAPE($, $, (#15312));
#15307 = IFCMAPPEDITEM(#4073, #15308);
#15308 = IFCCARTESIANTRANSFORMATIONOPERATOR3DNONUNIFORM(#15309, #15310, #15, 1., #15311, 1., 1.);
#15309 = IFCDIRECTION((1., 0., 0.));
#15310 = IFCDIRECTION((0., 1., 0.));
#15311 = IFCDIRECTION((0., 0., 1.));
#15312 = IFCSHAPEREPRESENTATION(#17, 'Body', 'MappedRepresentation', (#15307));
#15351 = IFCAXIS2PLACEMENT3D(#15352, #15353, #15354); /* FALLBACK POSITION IS EXPECTED VALUE */
#15352 = IFCCARTESIANPOINT((201., -2., 52.75));
#15353 = IFCDIRECTION((0., 0., 1.));
#15354 = IFCDIRECTION((1., 0., 0.));

In my mind, I see that as:

Measure 201. along the projection of the gradient curve onto the horizontal plane
Measure 2.0 to the left (or -2.0 to the right), normal to the projection of the gradient curve onto the horizontal plane
Measure 2.5 up in the global Z direction from the gradient curve.
I want the sign to be vertical, so I explicitly set the Axis to (0,0,1)

NOTE: The current implementation of Blender/Bonsai with IfcOpenShell and usBIM.browser resolve the scenario 4 sign position to (200.39, -2, 52.675) instead of the desired (201., -2., 52.75). The Validation Service uses IfcOpenShell on the backend and flags the fallback position as an error since it computes the position as (200.39, -2, 52.675). These implementations are based on a contested interpretation of IfcPointByDistanceExpression.OffsetVertical. These implementations have chosen to treat OffsetVertical as local Z instead of global Z.

Before we can go further, there needs to be a consensus agreement on the direction of OffsetVertical

I propose the following to be the accepted interpretation for IfcLinearPlacement, IfcAxis2PlacementLinear, IfcPointByDistanceExpression, IfcOffsetCurveByDistances, IfcSectionedSurface.CrossSectionPositions, and IfcSectionedSolidHorizontal.CrossSectionPositions:

  1. IfcPointByDistanceExpression.DistanceAlong is a curvilinear distance measured along the projection of IfcCompositeCurve (or its subclasses IfcGradientCurve and IfcSegmentedReferenceCurve) onto the global XY plane. (e.g. distance along the alignment curve in plan view)
  2. IfcPointByDistanceExpression.OffsetLateral is an offset normal to the basis curve at DistanceAlong in a plane that is parallel to the global XY plane (e.g. measured normal to the plan view of the basis curve at DistanceAlong)
  3. IfcPointByDistanceExpression.OffsetVertical is an offset from the basis curve in the global Z direction. (e.g. as viewed in a "DistanceAlong,Elevation" profile view of the basis curve, the vertical offset is up or down in the "Elevation" direction and not affected by the slope of the basis curve at that point.
  4. IfcPointByDistanceExpression.OffsetLongitudinal is an offset in the plan view tangent direction from the point established by DistanceAlong, OffsetLateral and OffsetVertical.
  5. The default IfcAxis2PlacementLinear.Axis is perpendicular to the basis curve (e.g. the local Z direction). IfcAxis2PlacementLinear.Axis = CurveTangent.Cross(Y) where Y = Z.Cross(CurveTangent), Z = (0,0,1) and CurveTangent is the vector that is tangent to the 3D basis curve at Location.DistanceAlong. CurveTangent rather than RefDirection is purposefully used to establish the default Axis direction - In all other IfcAxis2PlacementXXX, the Axis direction is the dominate factor and not influenced by RefDirection - For other IfcAxis2PlacementXXX, RefDirection and Axis establish Y then Axis and Y establish X if RefDirection is not orthogonal. The same semantics should apply to IfcAxis2PlacementLinear. IfcAxis2PlacementLinear is the only IfcAxis2PlacementXXX that does not require either both or neither Axis and RefDirection defined. If only IfcAxis2PlacementLinear.RefDirection is defined, it does not define IfcAxis2PlacementLinear.Axis.
  6. The default IfcAxis2PlacementLinear.RefDirection is the vector that is tangent to the 3D basis curve at Location.DistanceAlong. This is the same as CurveTangent. This interpretation of default IfcAxis2PlacementLinear.Axis and .RefDirection allows for an object to be place and automatically get cant slope rotation as in Scenario 1 in the example above and also for IfcSectionedSurface and IfcSectionedSolidHorizontal as discussed in https://github.com/RickBrice/IFC-Alignment-Geometry-Implementation-Guide/blob/main/10_Sectioned_Surfaces_and_Solids.md#10611-minimal-definition and https://github.com/RickBrice/IFC-Alignment-Geometry-Implementation-Guide/blob/main/10_Sectioned_Surfaces_and_Solids.md#10621-minimal-definition, respectively
  7. IfcLinearPlacement.PlacementRelTo should typically be omitted (or required to be omitted). The purpose of IfcLinearPlacement is to place something relative to a curve, not to define a placement relative to the start of a curve and then treat it as a delta placement relative to another placement. This is what is being done in Scenarios 2 and 3.
  8. IfcOffsetCurveByDistances.OffsetValues with IfcPointByDistanceExpression.OffsetLateral/OffsetVertical as defined above would be consistent with traditional engineering analysis. Lateral is in a horizontal plane, vertical is in the direction of Elevation.
  9. IfcSectionedSurface.CrossSectionPositions and IfcSectionSolidHorizontal.CrossSectionPositions must use an explicit IfcAxis2PlacementLinear.Axis = (0,0,1) when the plane of the cross section is to be vertical, such as in the case of a roadway layer cross section or a retaining wall cross section. Otherwise, the orientation of the cross-section plane will rotate with the gradient and cross slope (in the case of cant) along the length of the basis curve.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ( ! )IFTo be checked with IFC Implementers Forumbefore-NWIIssue to be resolved before the IFC NWI (New Work Item) submission to the next ISO cycle.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions