Updates alignment api

Fixes mapping of vertical alignment parabola business logic to geometry. Adds creation function of h and v alignment. Adds stationing referent at start of alignment. Fixes utility functions
This commit is contained in:
Richard Brice
2025-02-22 16:16:59 -08:00
parent 12f8a1f769
commit 8c16f394c1
4 changed files with 525 additions and 30 deletions
+8
View File
@@ -1,8 +1,16 @@
#include "function_item_evaluator.h"
#include "profile_helper.h"
#include <boost/math/quadrature/trapezoidal.hpp>
using namespace ifcopenshell::geometry;
double ifcopenshell::geometry::polynomial_length(double A, double B, double C, double horizontal_length) {
auto fn = [A, B, C](double x) -> double { return sqrt(pow(B + 2 * C * x, 2.0) + 1.0); };
auto l = boost::math::quadrature::trapezoidal(fn, 0.0, horizontal_length);
return l;
}
struct functor_fn_evaluator : public fn_evaluator {
functor_fn_evaluator(taxonomy::functor_item::const_ptr fn, const ifcopenshell::geometry::Settings& settings) : fn_evaluator(settings),
+11
View File
@@ -7,6 +7,17 @@
namespace ifcopenshell { namespace geometry {
/// @brief Computes the curve length of a polynomial of the form y = A + Bx + Cx^2
/// This function is needed on the python side. To do this computation, a large library like scipy
/// is needed. That is too much overhead. For this reason, a simple function is here on the C++ side
/// that the python side can call
/// @param A constant term
/// @param B linear term
/// @param C quadradic term
/// @param horizontal_length length of the polynomal projected onto the horizontal axis
/// @return curve length
double polynomial_length(double A, double B, double C,double horizontal_length);
/// @brief Abstract class for evaluating a function_item. This class is specialized for each of the function_item types.
struct fn_evaluator {
fn_evaluator(const ifcopenshell::geometry::Settings& settings) : settings_(settings) {
+498 -17
View File
@@ -28,6 +28,8 @@ import ifcopenshell.guid
import ifcopenshell.template
from ifcopenshell import entity_instance
from ifcopenshell import ifcopenshell_wrapper
import ifcopenshell.util
import ifcopenshell.util.stationing
def evaluate_representation(shape_rep: entity_instance, dist_along: float) -> np.ndarray:
@@ -46,10 +48,10 @@ def evaluate_representation(shape_rep: entity_instance, dist_along: float) -> np
# TODO: confirm point is not beyond limits of alignment
s = ifcopenshell.geom.settings()
piecewise_function = ifcopenshell_wrapper.map_shape(s, shape_rep.wrapped_data)
pwf_evaluator = ifcopenshell_wrapper.piecewise_function_evaluator(piecewise_function, s)
function_item = ifcopenshell_wrapper.map_shape(s, shape_rep.wrapped_data)
evaluator = ifcopenshell_wrapper.function_item_evaluator(s, function_item)
trans_matrix = pwf_evaluator.evaluate(dist_along)
trans_matrix = evaluator.evaluate(dist_along)
return np.array(trans_matrix, dtype=np.float64).T
@@ -68,10 +70,10 @@ def evaluate_segment(segment: entity_instance, dist_along: float) -> np.ndarray:
raise ValueError(f"Provided value {dist_along=} is beyond the end of the segment ({segment.SegmentLength}).")
s = ifcopenshell.geom.settings()
piecewise_function = ifcopenshell_wrapper.map_shape(s, segment.wrapped_data)
pwf_evaluator = ifcopenshell_wrapper.piecewise_function_evaluator(piecewise_function, s)
function_item = ifcopenshell_wrapper.map_shape(s, segment.wrapped_data)
evaluator = ifcopenshell_wrapper.function_item_evaluator(s, function_item)
trans_matrix = pwf_evaluator.evaluate(dist_along)
trans_matrix = evaluator.evaluate(dist_along)
return np.array(trans_matrix, dtype=np.float64).T
@@ -90,7 +92,8 @@ def generate_vertices(rep_curve: entity_instance, distance_interval: float = 5.0
raise ValueError("Alignment representation not found.")
s = ifcopenshell.geom.settings()
s.set("PIECEWISE_STEP_PARAM", distance_interval)
s.set("piecewise-step-type",0) # 0 = step-size is maximum step size, 1 = step-size is mininimum number of steps
s.set("piecewise-step-size", distance_interval)
shape = ifcopenshell.geom.create_shape(s, rep_curve)
vertices = shape.verts
if len(vertices) == 0:
@@ -185,6 +188,129 @@ class IfcAlignmentHelper:
alignment_segment.ObjectPlacement = global_placement
alignment_segment.Representation = product
def _map_alignment_vertical_segment(self, segment: entity_instance) -> Sequence[entity_instance]:
segment_type = segment.is_a().upper()
expected_type = "IFCALIGNMENTVERTICALSEGMENT"
if not segment_type == expected_type:
raise TypeError(f"Expected to see type '{expected_type}', instead received '{segment_type}'.")
start_distance_along = segment.StartDistAlong
horizontal_length = segment.HorizontalLength
start_height = segment.StartHeight
start_gradient = segment.StartGradient
end_gradient = segment.EndGradient
radius_of_curvature = segment.RadiusOfCurvature
if math.isclose(horizontal_length, 0):
# set transition value based on whether this is the final zero-length segment
transition = "DISCONTINUOUS"
else:
transition = "CONTSAMEGRADIENTSAMECURVATURE"
_type = segment.PredefinedType
match _type:
case "CONSTANTGRADIENT":
parent_curve = self._file.create_entity(
type="IfcLine",
Pnt=self._file.create_entity(type="IfcCartesianPoint",Coordinates=(0.0,0.0),),
Dir=self._file.create_entity(type="IfcVector",
Orientation=self._file.create_entity(type="IfcDirection",DirectionRatios=(1.0,0.0),),
Magnitude=1.0,),
)
dx = math.cos(math.atan(start_gradient))
dy = math.sin(math.atan(start_gradient))
curve_segment_length = horizontal_length/dx
curve_segment = self._file.create_entity(
type="IfcCurveSegment",
Transition=transition,
Placement=self._file.create_entity(
type="IfcAxis2Placement2D",
Location=self._file.create_entity(type="IfcCartesianPoint",Coordinates=(start_distance_along,start_height)),
RefDirection=self._file.createIfcDirection((dx,dy)),
),
SegmentStart=self._file.createIfcLengthMeasure(0.0),
SegmentLength=self._file.createIfcLengthMeasure(curve_segment_length),
ParentCurve=parent_curve,
)
result = (curve_segment, None)
case "PARABOLICARC":
A = start_height
B = start_gradient
C = (end_gradient - start_gradient)/(2.0*horizontal_length)
parent_curve = self._file.create_entity(
type="IfcPolynomialCurve",
Position=self._file.create_entity(
type="IfcAxis2Placement2D",
Location=self._file.create_entity(type="IfcCartesianPoint",Coordinates=(0.0,0.0)),
RefDirection=self._file.createIfcDirection((1.0, 0.0),),
),
CoefficientsX=(0.0,1.0),
CoefficientsY=(A,B,C),
)
dx = math.cos(math.atan(start_gradient))
dy = math.sin(math.atan(start_gradient))
curve_segment_length = ifcopenshell_wrapper.polynomial_length(A,B,C,horizontal_length)
curve_segment = self._file.create_entity(
type="IfcCurveSegment",
Transition=transition,
Placement=self._file.create_entity(
type="IfcAxis2Placement2D",
Location=self._file.create_entity(type="IfcCartesianPoint",Coordinates=(start_distance_along,start_height)),
RefDirection=self._file.createIfcDirection((dx,dy)),
),
SegmentStart=self._file.createIfcLengthMeasure(0.0),
SegmentLength=self._file.createIfcLengthMeasure(curve_segment_length),
ParentCurve=parent_curve,
)
result = (curve_segment, None)
case "CIRCULARARC":
start_angle = math.atan(start_gradient)
end_angle = math.atan(end_gradient)
if start_angle < end_angle:
radius = horizontal_length/(math.sin(end_angle) - math.sin(start_angle))
else:
radius = horizontal_length/(math.sin(start_angle) - math.sin(end_angle))
parent_curve = self._file.create_entity(
type="IfcCircle",
Position=self._file.create_entity(
type="IfcAxis2Placement2D",
Location=self._file.create_entity(type="IfcCartesianPoint",Coordinates=(0.0,0.0)),
RefDirection=self._file.createIfcDirection((1.0, 0.0),),
),
Radius=radius,
)
segment_curve_length = radius*math.fabs(end_angle - start_angle)
curve_segment = self._file.create_entity(
type="IfcCurveSegment",
Transition=transition,
Placement=self._file.create_entity(
type="IfcAxis2Placement2D",
Location=self._file.create_entity(type="IfcCartesianPoint",Coordinates=(start_distance_along,start_height)),
RefDirection=self._file.createIfcDirection((1.0,0.0),
),
),
SegmentStart=self._file.createIfcLengthMeasure(0.0),
SegmentLength=self._file.createIfcLengthMeasure(curve_segment_length),
ParentCurve=parent_curve,
)
result = (curve_segment, None)
case _:
result = (None, None)
return result
def _map_alignment_horizontal_segment(self, segment: entity_instance) -> Sequence[entity_instance]:
segment_type = segment.is_a().upper()
expected_type = "IFCALIGNMENTHORIZONTALSEGMENT"
@@ -550,10 +676,11 @@ class IfcAlignmentHelper:
alignment.Representation = product_definition_shape
# create referent for start station
start_station_name = "Start Station ({})".format(ifcopenshell.util.stationing.station_as_string(start_station))
start_referent = self._file.createIfcReferent(
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name="Start Station",
Name=start_station_name,
Description=None,
ObjectType=None,
ObjectPlacement=self._file.createIfcLinearPlacement(
@@ -571,6 +698,8 @@ class IfcAlignmentHelper:
Representation=None,
PredefinedType="STATION",
)
pset_stationing = ifcopenshell.api.pset.add_pset(self._file,product=start_referent,name="Pset_Stationing")
ifcopenshell.api.pset.edit_pset(self._file,pset=pset_stationing,properties={"Station":start_station})
# nest the horizontal and the referent under the alignment
nesting_of_alignment = self._file.create_entity(
@@ -594,12 +723,11 @@ class IfcAlignmentHelper:
return alignment
def add_vertical_alignment(
def _create_vertical_alignment(
self,
name: str,
description: str,
composite_curve: entity_instance,
vpoints: Sequence[Sequence[float]],
vclengths: Sequence[Sequence[float]],
lengths: Sequence[float],
include_geometry: bool = True,
):
"""
@@ -608,12 +736,353 @@ class IfcAlignmentHelper:
@param name: value for Name attribute
@param description: value for Description attribute
@param vpoints: (distance_along, Z_height) pairs denoting the location of the vertical PIs, including start and end.
@param vclengths: radii values to use for transition
@param vclengths: horizontal length of parabolic vertical curves
@param include_geometry: optionally create the alignment geometric representation as well as the semantic business logic
"""
pass
vertical_segments = list() # business logic
vertical_curve_segments = list() # geometry
xPBG, yPBG = vpoints[0]
xPVI, yPVI = vpoints[1]
i = 1
for length in lengths:
# back gradient
dxBG = xPVI - xPBG
dyBG = yPVI - yPBG
start_slope = math.tan(math.atan2(dyBG,dxBG))
def add_alignment(
#forward gradient
i += 1
xPFG, yPFG = vpoints[i]
dxFG = xPFG - xPVI
dyFG = yPFG - yPVI
end_slope = math.tan(math.atan2(dyFG,dxFG))
xEVC = xPVI + length/2.0
yEVC = yPVI + end_slope * length/2.0
# create gradient
gradient_length = dxBG - length/2.0
design_parameters = self._file.create_entity(
type="IfcAlignmentVerticalSegment",
StartTag=None,
EndTag=None,
StartDistAlong=xPBG,
HorizontalLength=gradient_length,
StartHeight=yPBG,
StartGradient=start_slope,
EndGradient=start_slope,
RadiusOfCurvature=None,
PredefinedType="CONSTANTGRADIENT"
)
alignment_segment = self._file.create_entity(
type="IfcAlignmentSegment",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=None,
Description=None,
ObjectType=None,
ObjectPlacement=None,
Representation=None,
DesignParameters=design_parameters,
)
vertical_segments.append(alignment_segment)
if include_geometry:
vertical_curve_segments.append(self._map_alignment_vertical_segment(design_parameters)[0])
# create vertical curve
k = (end_slope - start_slope)/length
xBVC = xPVI - length/2.0
yBVC = yPVI - start_slope*length/2.0
design_parameters = self._file.create_entity(
type="IfcAlignmentVerticalSegment",
StartTag=None,
EndTag=None,
StartDistAlong=xBVC,
HorizontalLength=length,
StartHeight=yBVC,
StartGradient=start_slope,
EndGradient=end_slope,
RadiusOfCurvature=1/k,
PredefinedType="PARABOLICARC"
)
alignment_segment = self._file.create_entity(
type="IfcAlignmentSegment",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=None,
Description=None,
ObjectType=None,
ObjectPlacement=None,
Representation=None,
DesignParameters=design_parameters,
)
vertical_segments.append(alignment_segment)
if include_geometry:
vertical_curve_segments.append(self._map_alignment_vertical_segment(design_parameters)[0])
# start of next curve is end of this curve
xPBG = xEVC
yPBG = yEVC
xPVI = xPFG
yPVI = yPFG
# create last gradient run
dx = xPVI - xPBG
dy = yPVI - yPBG
slope = math.tan(math.atan2(dy,dx))
gradient_length = dx
design_parameters = self._file.create_entity(
type="IfcAlignmentVerticalSegment",
StartTag=None,
EndTag=None,
StartDistAlong=xPBG,
HorizontalLength=gradient_length,
StartHeight=yPBG,
StartGradient=slope,
EndGradient=slope,
RadiusOfCurvature=None,
PredefinedType="CONSTANTGRADIENT"
)
alignment_segment = self._file.create_entity(
type="IfcAlignmentSegment",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=None,
Description=None,
ObjectType=None,
ObjectPlacement=None,
Representation=None,
DesignParameters=design_parameters,
)
vertical_segments.append(alignment_segment)
if include_geometry:
vertical_curve_segments.append(self._map_alignment_vertical_segment(design_parameters)[0])
# create zero length terminator segment
design_parameters = self._file.create_entity(
type="IfcAlignmentVerticalSegment",
StartTag="VPOE",
EndTag="VPOE",
StartDistAlong=xPVI,
HorizontalLength=0.0,
StartHeight=yPVI,
StartGradient=slope,
EndGradient=slope,
RadiusOfCurvature=None,
PredefinedType="CONSTANTGRADIENT"
)
alignment_segment = self._file.create_entity(
type="IfcAlignmentSegment",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=None,
Description=None,
ObjectType=None,
ObjectPlacement=None,
Representation=None,
DesignParameters=design_parameters,
)
vertical_segments.append(alignment_segment)
if include_geometry:
vertical_curve_segments.append(self._map_alignment_vertical_segment(design_parameters)[0])
if include_geometry:
gradient_curve = self._file.create_entity(
type="IfcGradientCurve",
Segments=vertical_curve_segments,
SelfIntersect=False,
BaseCurve=composite_curve,
EndPoint=None
)
else:
gradient_curve = None
return vertical_segments, vertical_curve_segments, gradient_curve
def create_alignment_by_pi_method(
self,
alignment_name: str,
points: Sequence[Sequence[float]],
radii: Sequence[float],
vpoints: Sequence[Sequence[float]],
lengths: Sequence[float],
alignment_description: str = None,
start_station: float = 1000.0,
include_geometry: bool = True
):
"""
Create an alignment using the PI layout method for both horizontal and vertical alignments.
@param alignment_name: value for Name attribute
@param alignment_description: value for Description attribute
@param points: (X,Y) pairs denoting the location of the horizontal PIs, including start and end
@param radii: radii values to use for transition
@param vpoints: (distance_along, Z_height) pairs denoting the location of the vertical PIs, including start and end.
@param lengths: parabolic vertical curve horizontal length values to use for transition
@param start_station: ??? NOT USED AT THIS TIME ???
@param include_geometry: optionally create the alignment geometric representation as well as the semantic business logic
"""
horizontal_segments, horizontal_curve_segments, composite_curve = self._create_horizontal_alignment(alignment_name,alignment_description,points,radii,include_geometry)
vertical_segments, vertical_curve_segments, gradient_curve = self._create_vertical_alignment(composite_curve,vpoints,lengths)
name_segments(prefix="H",segments=horizontal_segments)
name_segments(prefix="V",segments=vertical_segments)
# Create the horizontal alignment (IfcAlignmentHorizontal) and nest alignment segments
horizontal_alignment = self._file.create_entity(
type="IfcAlignmentHorizontal",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=f"{alignment_name} - Horizontal",
Description=alignment_description,
ObjectType=None,
ObjectPlacement=None,
Representation=None,
)
nests_horizontal_segments = self._file.create_entity(
type="IfcRelNests",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name="Nests horizontal alignment segments under horizontal alignment",
RelatingObject=horizontal_alignment,
RelatedObjects=horizontal_segments,
)
# Create the vertical alignment (IfcAlignmentVertical) and nest alignment segments
vertical_alignment = self._file.create_entity(
type="IfcAlignmentVertical",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=f"{alignment_name} - Vertical",
Description=alignment_description,
ObjectType=None,
ObjectPlacement=None,
Representation=None,
)
nests_vertical_segments = self._file.create_entity(
type="IfcRelNests",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name="Nests vertical alignment segments under vertical alignment",
RelatingObject=vertical_alignment,
RelatedObjects=vertical_segments,
)
# create the alignment
placement = self._file.createIfcLocalPlacement(
PlacementRelTo=None,
RelativePlacement=self._file.createIfcAxis2Placement2D(
Location=self._file.createIfcCartesianPoint(Coordinates=(0.0, 0.0))
),
)
alignment = self._file.create_entity(
type="IfcAlignment",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=alignment_name,
Description=alignment_description,
ObjectType=None,
ObjectPlacement=placement,
Representation=None,
PredefinedType=None,
)
# create referent for start station
start_station_name = "Start Station ({})".format(ifcopenshell.util.stationing.station_as_string(start_station))
start_referent = self._file.createIfcReferent(
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name=start_station_name,
Description=None,
ObjectType=None,
ObjectPlacement=self._file.createIfcLinearPlacement(
RelativePlacement=self._file.createIfcAxis2PlacementLinear(
Location=self._file.createIfcPointByDistanceExpression(
DistanceAlong=self._file.createIfcLengthMeasure(0.0),
OffsetLateral=None,
OffsetVertical=None,
OffsetLongitudinal=None,
BasisCurve=composite_curve,
),
),
CartesianPosition=None,
),
Representation=None,
PredefinedType="STATION",
)
pset_stationing = ifcopenshell.api.pset.add_pset(self._file,product=start_referent,name="Pset_Stationing")
ifcopenshell.api.pset.edit_pset(self._file,pset=pset_stationing,properties={"Station":start_station})
# nest the horizontal, vertical and the referent under the alignment
nesting_of_alignment = self._file.create_entity(
type="IfcRelNests",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name="Nests horizontal alignment, vertical alginment, and referents under overall alignment",
RelatingObject=alignment,
RelatedObjects=(horizontal_alignment, vertical_alignment, start_referent),
)
# aggregate the alignment under the project
project = self._file.by_type("IfcProject")[0]
alignment_within_project = self._file.createIfcRelAggregates(
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=None,
Name="Aggregates alignment under the project",
RelatingObject=project,
RelatedObjects=(alignment,),
)
# create geometric representation
if include_geometry:
# create the footprint representation
footprint_shape_representation = self._file.create_entity(
type="IfcShapeRepresentation",
ContextOfItems=self._axis_geom_subcontext,
RepresentationIdentifier="FootPrint",
RepresentationType="Curve2D",
Items=(composite_curve,),
)
# create the Curve3D representation
axis3d_shape_representation = self._file.create_entity(
type="IfcShapeRepresentation",
ContextOfItems=self._axis_geom_subcontext,
RepresentationIdentifier="Axis",
RepresentationType="Curve3D",
Items=(gradient_curve,),
)
# create the alignment product definition
product_definition_shape = self._file.create_entity(
type="IfcProductDefinitionShape",
Name="Alignment Product Definition Shape",
Description=None,
Representations=(footprint_shape_representation,axis3d_shape_representation,),
)
# create representations for each segment
self._create_segment_representations(placement, horizontal_curve_segments, horizontal_segments)
self._create_segment_representations(placement, vertical_curve_segments, vertical_segments)
# add the representation to the alignment
alignment.Representation = product_definition_shape
return alignment
def create_horizontal_alignment_by_pi_method(
self,
name: str,
hpoints: Sequence[Sequence[float]],
@@ -625,7 +1094,7 @@ class IfcAlignmentHelper:
"""
Create a new alignment with a horizontal alignment using the PI layout method
"""
self._add_horizontal_alignment(
return self._add_horizontal_alignment(
alignment_name=name,
points=hpoints,
radii=radii,
@@ -642,7 +1111,19 @@ if __name__ == "__main__":
import sys
from matplotlib import pyplot as plt
f = ifcopenshell.open(sys.argv[1])
f = ifcopenshell.file(schema="IFC4X3_ADD2")
project = f.create_entity(type="IfcProject",GlobalId=ifcopenshell.guid.new())
context = f.create_entity(type="IfcGeometricRepresentationContext")
points=[(0.,0.),(100.,0.),(200.,150.)]
radii=[(50.)]
helper = IfcAlignmentHelper(f)
helper.create_horizontal_alignment_by_pi_method(
name="MyAlignment",hpoints = points,radii = radii
)
#f = ifcopenshell.open(sys.argv[1])
print_structure(f.by_type("IfcAlignment")[0])
al_hor_rep = f.by_type("IfcCompositeCurve")[0]
+8 -13
View File
@@ -208,7 +208,7 @@ Ifc4x3_add2::IfcAlignment* addHorizontalAlignment(IfcHierarchyHelper<Ifc4x3_add2
placement = file.addLocalPlacement();
// the alignment has two representations, a plan view footprint
// the alignment has a plan view footprint representation
typename aggregate_of<Ifc4x3_add2::IfcRepresentation>::ptr alignment_representations(new aggregate_of<Ifc4x3_add2::IfcRepresentation>());
alignment_representations->push(footprint_shape_representation); // 2D footprint
@@ -258,7 +258,6 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
// create gradient
{
file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xPBG, yPBG);
auto gradient_length = dxBG - length/2;
auto design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xPBG, gradient_length, yPBG, start_slope, start_slope, boost::none, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CONSTANTGRADIENT);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
@@ -274,8 +273,6 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
double xBVC = xPVI - length / 2;
double yBVC = yPVI - start_slope * length / 2;
file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xBVC, yBVC);
auto design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xBVC, length, yBVC, start_slope, end_slope, 1 / k, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_PARABOLICARC);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
vertical_segments->push(alignment_segment);
@@ -296,7 +293,6 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
auto slope = tan(atan2(dy,dx));
auto gradient_length = dx;
file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xPBG, yPBG);
auto design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xPBG, gradient_length, yPBG, slope, slope, boost::none, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CONSTANTGRADIENT);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
vertical_segments->push(alignment_segment);
@@ -305,7 +301,6 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
}
// create zero length terminator segment
file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xPVI, yPVI);
design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xPVI, 0.0, yPVI, slope, slope, boost::none, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CONSTANTGRADIENT);
alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
vertical_segments->push(alignment_segment);
@@ -358,14 +353,14 @@ Ifc4x3_add2::IfcAlignment* addAlignment(IfcHierarchyHelper<Ifc4x3_add2>& file, c
typename aggregate_of<Ifc4x3_add2::IfcRepresentationItem>::ptr alignment_representation_items(new aggregate_of<Ifc4x3_add2::IfcRepresentationItem>());
alignment_representation_items->push(composite_curve);
// create the footprint representation
auto footprint_shape_representation = new Ifc4x3_add2::IfcShapeRepresentation(axis_model_representation_subcontext, std::string("FootPrint"), std::string("Curve2D"), alignment_representation_items);
file.addEntity(footprint_shape_representation);
// the gradient curve is a representation item
typename aggregate_of<typename Ifc4x3_add2::IfcRepresentationItem>::ptr profile_representation_items(new aggregate_of<Ifc4x3_add2::IfcRepresentationItem>());
profile_representation_items->push(gradient_curve);
// create footprint representation
auto footprint_shape_representation = new Ifc4x3_add2::IfcShapeRepresentation(axis_model_representation_subcontext, std::string("FootPrint"), std::string("Curve2D"), alignment_representation_items);
file.addEntity(footprint_shape_representation);
// create the axis representation
auto axis3d_shape_representation = new Ifc4x3_add2::IfcShapeRepresentation(axis_model_representation_subcontext, std::string("Axis"), std::string("Curve3D"), profile_representation_items);
file.addEntity(axis3d_shape_representation);
@@ -375,10 +370,10 @@ Ifc4x3_add2::IfcAlignment* addAlignment(IfcHierarchyHelper<Ifc4x3_add2>& file, c
_createSegmentRepresentations(file, placement, axis_model_representation_subcontext, horizontal_curve_segments, horizontal_segments);
_createSegmentRepresentations(file, placement, axis_model_representation_subcontext, vertical_curve_segments, vertical_segments);
// the alignment has two representations, a plan view footprint and a 3d curve
// the alignment has a 3d curve representation
typename aggregate_of<typename Ifc4x3_add2::IfcRepresentation>::ptr alignment_representations(new aggregate_of<Ifc4x3_add2::IfcRepresentation>());
alignment_representations->push(footprint_shape_representation); // 2D footprint
alignment_representations->push(axis3d_shape_representation); // 3D curve
alignment_representations->push(footprint_shape_representation); // 2D curve
alignment_representations->push(axis3d_shape_representation); // 3D curve
// create the alignment product definition
product_definition_shape = new Ifc4x3_add2::IfcProductDefinitionShape(std::string("Alignment Product Definition Shape"), boost::none, alignment_representations);