Integrated generic resource: Geometric and topological representation ISO 10303-42:2021(E)
© ISO

Cover page
Table of contents
Copyright
Foreword
Introduction
1 Scope
2 Normative references
3 Terms, definitions and abbreviated terms
    3.1 Terms and definitions
    3.2 Abbreviated terms

4 Geometry
   4.1 General
   4.2 Fundamental concepts and assumptions
   4.3 Geometry constant definition
   4.4 Geometry type definitions
   4.5 Geometry entity definitions
   4.6 Geometry function definitions
   4.7 Geometry rule definitions
5 Topology
   5.1 General
   5.2 Fundamental concepts and assumptions
   5.3 Topology constant definition
   5.4 Topology type definitions
   5.5 Topology entity definitions
   5.6 Topology function definitions
6 Geometric model
   6.1 General
   6.2 Fundamental concepts and assumptions
   6.3 Geometric model type definitions
   6.4 Geometric model entity definitions
   6.5 Geometric model function definitions
7 Scan data 3d shape model
   7.1 General
   7.2 Fundamental concepts and assumptions
   7.3 Scan data 3d shape model type definition
   7.4 Scan data 3d shape model entity definitions
   7.5 Scan data 3d shape model function definitions

A Short names of entities
B Information object registration
C Computer interpretable listings
D EXPRESS-G diagrams
E Change history
Bibliography
Index

(*
ISO/TC 184/SC 4/WG 12 N10585 - ISO 10303-42 Geometric and topological representation - EXPRESS
Supersedes ISO/TC 184/SC 4/WG 12 N10468
*)



SCHEMA geometry_schema;

REFERENCE FROM geometric_model_schema   -- ISO 10303-42
  (block,
   boolean_result,
   cyclide_segment_solid,
   eccentric_cone,
   edge_based_wireframe_model,
   ellipsoid,
   face_based_surface_model,
   faceted_primitive,
   geometric_set,
   half_space_solid,
   primitive_2d,
   rectangular_pyramid,
   right_angular_wedge,
   right_circular_cone,
   right_circular_cylinder,
   shell_based_surface_model,
   shell_based_wireframe_model,
   solid_model,
   sphere,
   tessellated_item,
   torus);

REFERENCE FROM measure_schema   -- ISO 10303-41
  (global_unit_assigned_context,
   length_measure,
   parameter_value,
   plane_angle_measure,
   plane_angle_unit,
   positive_length_measure,
   positive_plane_angle_measure);

REFERENCE FROM representation_schema   -- ISO 10303-43
  (definitional_representation,
   founded_item,
   functionally_defined_transformation,
   item_in_context,
   representation,
   representation_context,
   representation_item,
   using_representations);

REFERENCE FROM scan_data_3d_shape_model_schema   -- ISO 10303-42
  (scanned_data_item);

REFERENCE FROM topology_schema   -- ISO 10303-42
  (edge_curve,
   face_surface,
   poly_loop,
   vertex_point,
   volume_with_faces);


CONSTANT
  dummy_gri : geometric_representation_item := representation_item('')|| geometric_representation_item();
END_CONSTANT;

TYPE axis2_placement = SELECT
   (axis2_placement_2d,
    axis2_placement_3d);
END_TYPE;

TYPE b_spline_curve_form = ENUMERATION OF
   (polyline_form,
    circular_arc,
    elliptic_arc,
    parabolic_arc,
    hyperbolic_arc,
    unspecified);
END_TYPE;

TYPE b_spline_surface_form = ENUMERATION OF
   (plane_surf,
    cylindrical_surf,
    conical_surf,
    spherical_surf,
    toroidal_surf,
    surf_of_revolution,
    ruled_surf,
    generalised_cone,
    quadric_surf,
    surf_of_linear_extrusion,
    unspecified);
END_TYPE;

TYPE curve_on_surface = SELECT
   (composite_curve_on_surface,
    pcurve,
    surface_curve);
END_TYPE;

TYPE dimension_count = INTEGER;
WHERE
  WR1: SELF > 0;
END_TYPE;

TYPE extent_enumeration = ENUMERATION OF
   (invalid,
    zero,
    finite_non_zero,
    infinite);
END_TYPE;

TYPE knot_type = ENUMERATION OF
   (uniform_knots,
    quasi_uniform_knots,
    piecewise_bezier_knots,
    unspecified);
END_TYPE;

TYPE linearly_independent_enum = ENUMERATION OF
   (independent,
    not_independent,
    not_tested);
END_TYPE;

TYPE locally_refined_spline_type_enum = ENUMERATION OF
   (analysis_suitable_t_spline,
    hierarchical_b_spline,
    lr_b_spline,
    semi_standard_t_spline,
    standard_t_spline);
END_TYPE;

TYPE pcurve_or_surface = SELECT
   (pcurve,
    surface);
END_TYPE;

TYPE preferred_surface_curve_representation = ENUMERATION OF
   (curve_3d,
    pcurve_s1,
    pcurve_s2);
END_TYPE;

TYPE spline_knot_values = LIST[2:?] OF REAL;
WHERE
  WR1: increasing_values_in_list(SELF);
END_TYPE;

TYPE surface_boundary = SELECT
   (boundary_curve,
    degenerate_pcurve);
END_TYPE;

TYPE transition_code = ENUMERATION OF
   (discontinuous,
    continuous,
    cont_same_gradient,
    cont_same_gradient_same_curvature);
END_TYPE;

TYPE trimming_preference = ENUMERATION OF
   (cartesian,
    parameter,
    unspecified);
END_TYPE;

TYPE trimming_select = SELECT
   (cartesian_point,
    parameter_value);
END_TYPE;

TYPE vector_or_direction = SELECT
   (direction,
    vector);
END_TYPE;

ENTITY geometric_representation_context
  SUBTYPE OF (representation_context);
  coordinate_space_dimension : dimension_count;
END_ENTITY;

ENTITY geometric_representation_item
  SUPERTYPE OF (ONEOF (point,
                       direction,
                       vector,
                       placement,
                       cartesian_transformation_operator,
                       curve,
                       surface,
                       edge_curve,
                       face_surface,
                       poly_loop,
                       vertex_point,
                       solid_model,
                       boolean_result,
                       sphere,
                       right_circular_cone,
                       right_circular_cylinder,
                       torus,
                       block,
                       primitive_2d,
                       right_angular_wedge,
                       ellipsoid,
                       faceted_primitive,
                       rectangular_pyramid,
                       cyclide_segment_solid,
                       volume,
                       half_space_solid,
                       shell_based_surface_model,
                       face_based_surface_model,
                       shell_based_wireframe_model,
                       edge_based_wireframe_model,
                       geometric_set,
                       tessellated_item,
                       volume_with_faces,
                       scanned_data_item))
  SUBTYPE OF (representation_item);
DERIVE
  dim : dimension_count := dimension_of(SELF);
WHERE
  WR1: SIZEOF (QUERY (using_rep <* using_representations (SELF) | NOT ('GEOMETRY_SCHEMA.GEOMETRIC_REPRESENTATION_CONTEXT' IN TYPEOF (using_rep.context_of_items)))) = 0;
END_ENTITY;

ENTITY point
  SUPERTYPE OF (ONEOF (cartesian_point,
                       point_on_curve,
                       point_on_surface,
                       point_in_volume,
                       point_replica,
                       degenerate_pcurve))
  SUBTYPE OF (geometric_representation_item);
END_ENTITY;

ENTITY cartesian_point
  SUPERTYPE OF (ONEOF (cylindrical_point,
                       polar_point,
                       spherical_point))
  SUBTYPE OF (point);
  coordinates : LIST[1:3] OF length_measure;
END_ENTITY;

ENTITY cylindrical_point
  SUBTYPE OF (cartesian_point);
  r : length_measure;
  theta : plane_angle_measure;
  z : length_measure;
DERIVE
  SELF\cartesian_point.coordinates : LIST[3:3] OF length_measure := [r*cos(theta), r*sin(theta), z];
WHERE
  WR1: r >= 0.0;
END_ENTITY;

ENTITY spherical_point
  SUBTYPE OF (cartesian_point);
  r : length_measure;
  theta : plane_angle_measure;
  phi : plane_angle_measure;
DERIVE
  SELF\cartesian_point.coordinates : LIST[3:3] OF length_measure := [r*sin(theta)*cos(phi), r*sin(theta)*sin(phi), r*cos(theta)];
WHERE
  WR1: r >= 0.0;
END_ENTITY;

ENTITY polar_point
  SUBTYPE OF (cartesian_point);
  r : length_measure;
  theta : plane_angle_measure;
DERIVE
  SELF\cartesian_point.coordinates : LIST[2:2] OF length_measure := [r*cos(theta), r*sin(theta)];
WHERE
  WR1: r >= 0.0;
END_ENTITY;

ENTITY point_on_curve
  SUBTYPE OF (point);
  basis_curve : curve;
  point_parameter : parameter_value;
END_ENTITY;

ENTITY point_on_surface
  SUBTYPE OF (point);
  basis_surface : surface;
  point_parameter_u : parameter_value;
  point_parameter_v : parameter_value;
END_ENTITY;

ENTITY point_in_volume
  SUBTYPE OF (point);
  basis_volume : volume;
  point_parameter_u : parameter_value;
  point_parameter_v : parameter_value;
  point_parameter_w : parameter_value;
END_ENTITY;

ENTITY point_replica
  SUBTYPE OF (point);
  parent_pt : point;
  transformation : cartesian_transformation_operator;
WHERE
  WR1: transformation.dim = parent_pt.dim;
  WR2: acyclic_point_replica (SELF,parent_pt);
END_ENTITY;

ENTITY degenerate_pcurve
  SUBTYPE OF (point);
  basis_surface : surface;
  reference_to_curve : definitional_representation;
WHERE
  WR1: SIZEOF(reference_to_curve\representation.items) = 1;
  WR2: 'GEOMETRY_SCHEMA.CURVE' IN TYPEOF (reference_to_curve\representation.items[1]);
  WR3: reference_to_curve\representation. items[1]\geometric_representation_item.dim =2;
END_ENTITY;

ENTITY evaluated_degenerate_pcurve
  SUBTYPE OF (degenerate_pcurve);
  equivalent_point : cartesian_point;
END_ENTITY;

ENTITY direction
  SUBTYPE OF (geometric_representation_item);
  direction_ratios : LIST[2:3] OF REAL;
WHERE
  WR1: SIZEOF(QUERY(tmp <* direction_ratios | tmp <> 0.0)) > 0;
END_ENTITY;

ENTITY vector
  SUBTYPE OF (geometric_representation_item);
  orientation : direction;
  magnitude : length_measure;
WHERE
  WR1: magnitude >= 0.0;
END_ENTITY;

ENTITY placement
  SUPERTYPE OF (ONEOF (axis1_placement,
                       axis2_placement_2d,
                       axis2_placement_3d))
  SUBTYPE OF (geometric_representation_item);
  location : cartesian_point;
END_ENTITY;

ENTITY axis1_placement
  SUBTYPE OF (placement);
  axis : OPTIONAL direction;
DERIVE
  z : direction := NVL(normalise(axis), dummy_gri || direction([0.0,0.0,1.0]));
WHERE
  WR1: SELF\geometric_representation_item.dim = 3;
END_ENTITY;

ENTITY axis2_placement_2d
  SUBTYPE OF (placement);
  ref_direction : OPTIONAL direction;
DERIVE
  p : LIST[2:2] OF direction := build_2axes(ref_direction);
WHERE
  WR1: SELF\geometric_representation_item.dim = 2;
END_ENTITY;

ENTITY axis2_placement_3d
  SUBTYPE OF (placement);
  axis : OPTIONAL direction;
  ref_direction : OPTIONAL direction;
DERIVE
  p : LIST[3:3] OF direction := build_axes(axis,ref_direction);
WHERE
  WR1: SELF\placement.location.dim = 3;
  WR2: (NOT (EXISTS (axis))) OR (axis.dim = 3);
  WR3: (NOT (EXISTS (ref_direction))) OR (ref_direction.dim = 3);
  WR4: (NOT (EXISTS (axis))) OR (NOT (EXISTS (ref_direction))) OR (cross_product(axis,ref_direction).magnitude > 0.0);
END_ENTITY;

ENTITY cartesian_transformation_operator
  SUPERTYPE OF (ONEOF (cartesian_transformation_operator_2d,
                       cartesian_transformation_operator_3d))
  SUBTYPE OF (geometric_representation_item, functionally_defined_transformation);
  axis1 : OPTIONAL direction;
  axis2 : OPTIONAL direction;
  local_origin : cartesian_point;
  scale : OPTIONAL REAL;
DERIVE
  scl : REAL := NVL(scale, 1.0);
WHERE
  WR1: scl > 0.0;
END_ENTITY;

ENTITY cartesian_transformation_operator_3d
  SUBTYPE OF (cartesian_transformation_operator);
  axis3 : OPTIONAL direction;
DERIVE
  u : LIST[3:3] OF direction := base_axis(3,SELF\cartesian_transformation_operator.axis1, SELF\cartesian_transformation_operator.axis2,axis3);
WHERE
  WR1: SELF\geometric_representation_item.dim = 3;
END_ENTITY;

ENTITY cartesian_transformation_operator_2d
  SUBTYPE OF (cartesian_transformation_operator);
DERIVE
  u : LIST[2:2] OF direction := base_axis(2,SELF\cartesian_transformation_operator.axis1, SELF\cartesian_transformation_operator.axis2,?);
WHERE
  WR1: SELF\geometric_representation_item.dim = 2;
END_ENTITY;

ENTITY curve
  SUPERTYPE OF (ONEOF (line,
                       conic,
                       clothoid,
                       circular_involute,
                       pcurve,
                       surface_curve,
                       offset_curve_2d,
                       offset_curve_3d,
                       curve_replica))
  SUBTYPE OF (geometric_representation_item);
END_ENTITY;

ENTITY line
  SUBTYPE OF (curve);
  pnt : cartesian_point;
  dir : vector;
WHERE
  WR1: dir.dim = pnt.dim;
END_ENTITY;

ENTITY conic
  SUPERTYPE OF (ONEOF (circle,
                       ellipse,
                       hyperbola,
                       parabola))
  SUBTYPE OF (curve);
  position : axis2_placement;
END_ENTITY;

ENTITY circle
  SUBTYPE OF (conic);
  radius : positive_length_measure;
END_ENTITY;

ENTITY ellipse
  SUBTYPE OF (conic);
  semi_axis_1 : positive_length_measure;
  semi_axis_2 : positive_length_measure;
END_ENTITY;

ENTITY hyperbola
  SUBTYPE OF (conic);
  semi_axis : positive_length_measure;
  semi_imag_axis : positive_length_measure;
END_ENTITY;

ENTITY parabola
  SUBTYPE OF (conic);
  focal_dist : length_measure;
WHERE
  WR1: focal_dist <> 0.0;
END_ENTITY;

ENTITY clothoid
  SUBTYPE OF (curve);
  position : axis2_placement;
  clothoid_constant : length_measure;
END_ENTITY;

ENTITY circular_involute
  SUBTYPE OF (curve);
  position : axis2_placement;
  base_radius : positive_length_measure;
END_ENTITY;

ENTITY bounded_curve
  SUPERTYPE OF (ONEOF (polyline,
                       b_spline_curve,
                       trimmed_curve,
                       bounded_pcurve,
                       bounded_surface_curve,
                       composite_curve,
                       locally_refined_spline_curve))
  SUBTYPE OF (curve);
END_ENTITY;

ENTITY polyline
  SUBTYPE OF (bounded_curve);
  points : LIST[2:?] OF cartesian_point;
END_ENTITY;

ENTITY b_spline_curve
  SUPERTYPE OF (ONEOF (uniform_curve,
                       b_spline_curve_with_knots,
                       quasi_uniform_curve,
                       bezier_curve)
               ANDOR rational_b_spline_curve)
  SUBTYPE OF (bounded_curve);
  degree : INTEGER;
  control_points_list : LIST[2:?] OF cartesian_point;
  curve_form : b_spline_curve_form;
  closed_curve : LOGICAL;
  self_intersect : LOGICAL;
DERIVE
  upper_index_on_control_points : INTEGER := (SIZEOF(control_points_list) - 1);
  control_points : ARRAY[0:upper_index_on_control_points] OF cartesian_point := list_to_array(control_points_list,0, upper_index_on_control_points);
WHERE
  WR1: ('GEOMETRY_SCHEMA.UNIFORM_CURVE' IN TYPEOF(self)) OR ('GEOMETRY_SCHEMA.QUASI_UNIFORM_CURVE' IN TYPEOF(self)) OR ('GEOMETRY_SCHEMA.BEZIER_CURVE' IN TYPEOF(self)) OR ('GEOMETRY_SCHEMA.B_SPLINE_CURVE_WITH_KNOTS' IN TYPEOF(self));
END_ENTITY;

ENTITY b_spline_curve_with_knots
  SUBTYPE OF (b_spline_curve);
  knot_multiplicities : LIST[2:?] OF INTEGER;
  knots : LIST[2:?] OF parameter_value;
  knot_spec : knot_type;
DERIVE
  upper_index_on_knots : INTEGER := SIZEOF(knots);
WHERE
  WR1: constraints_param_b_spline(degree, upper_index_on_knots, upper_index_on_control_points, knot_multiplicities, knots);
  WR2: SIZEOF(knot_multiplicities) = upper_index_on_knots;
END_ENTITY;

ENTITY uniform_curve
  SUBTYPE OF (b_spline_curve);
END_ENTITY;

ENTITY quasi_uniform_curve
  SUBTYPE OF (b_spline_curve);
END_ENTITY;

ENTITY bezier_curve
  SUBTYPE OF (b_spline_curve);
END_ENTITY;

ENTITY rational_b_spline_curve
  SUBTYPE OF (b_spline_curve);
  weights_data : LIST[2:?] OF REAL;
DERIVE
  weights : ARRAY[0:upper_index_on_control_points] OF REAL := list_to_array(weights_data,0, upper_index_on_control_points);
WHERE
  WR1: SIZEOF(weights_data) = SIZEOF(SELF\b_spline_curve. control_points_list);
  WR2: curve_weights_positive(SELF);
END_ENTITY;

ENTITY local_b_spline
  SUBTYPE OF (representation_item);
  degree : INTEGER;
  knots : LIST[2:?] OF INTEGER;
  multiplicities : LIST[2:?] OF INTEGER;
WHERE
  WR1: degree > 0;
  WR2: SIZEOF(knots) = SIZEOF(multiplicities);
  WR3: constraints_param_local_b_spline(degree, knots, multiplicities);
END_ENTITY;

ENTITY locally_refined_spline_curve
  SUBTYPE OF (bounded_curve);
  b_splines : LIST[2:?] OF local_b_spline;
  knot_values : spline_knot_values;
  control_points_list : LIST[2:?] OF cartesian_point;
  scaling_factors : LIST[2:?] OF REAL;
  closed_curve : LOGICAL;
  locally_refined_spline_type : locally_refined_spline_type_enum;
  self_intersect : LOGICAL;
  domain : LIST[2:2] OF REAL;
WHERE
  WR1: SIZEOF(b_splines) = SIZEOF(control_points_list);
  WR2: SIZEOF(scaling_factors) = SIZEOF(control_points_list);
  WR3: constraints_scaling(scaling_factors);
END_ENTITY;

ENTITY rational_locally_refined_spline_curve
  SUBTYPE OF (locally_refined_spline_curve);
  weights_data : LIST[2:?] OF REAL;
WHERE
  WR1: SIZEOF(weights_data) = SIZEOF(SELF\locally_refined_spline_curve. control_points_list);
  WR2: weights_positive(weights_data);
END_ENTITY;

ENTITY trimmed_curve
  SUBTYPE OF (bounded_curve);
  basis_curve : curve;
  trim_1 : SET[1:2] OF trimming_select;
  trim_2 : SET[1:2] OF trimming_select;
  sense_agreement : BOOLEAN;
  master_representation : trimming_preference;
WHERE
  WR1: (HIINDEX(trim_1) = 1) OR (TYPEOF(trim_1[1]) <> TYPEOF(trim_1[2]));
  WR2: (HIINDEX(trim_2) = 1) OR (TYPEOF(trim_2[1]) <> TYPEOF(trim_2[2]));
END_ENTITY;

ENTITY composite_curve
  SUBTYPE OF (bounded_curve);
  segments : LIST[1:?] OF composite_curve_segment;
  self_intersect : LOGICAL;
DERIVE
  n_segments : INTEGER := SIZEOF(segments);
  closed_curve : LOGICAL := segments[n_segments].transition <> discontinuous;
WHERE
  WR1: ((NOT closed_curve) AND (SIZEOF(QUERY(temp <* segments | temp.transition = discontinuous)) = 1)) OR ((closed_curve) AND (SIZEOF(QUERY(temp <* segments | temp.transition = discontinuous)) = 0));
END_ENTITY;

ENTITY composite_curve_segment
  SUBTYPE OF (founded_item);
  transition : transition_code;
  same_sense : BOOLEAN;
  parent_curve : curve;
INVERSE
  using_curves : BAG[1:?] OF composite_curve FOR segments;
WHERE
  WR1: ('GEOMETRY_SCHEMA.BOUNDED_CURVE' IN TYPEOF(parent_curve));
END_ENTITY;

ENTITY reparametrised_composite_curve_segment
  SUBTYPE OF (composite_curve_segment);
  param_length : parameter_value;
WHERE
  WR1: param_length > 0.0;
END_ENTITY;

ENTITY pcurve
  SUBTYPE OF (curve);
  basis_surface : surface;
  reference_to_curve : definitional_representation;
WHERE
  WR1: SIZEOF(reference_to_curve\representation.items) = 1;
  WR2: 'GEOMETRY_SCHEMA.CURVE' IN TYPEOF (reference_to_curve\representation.items[1]);
  WR3: reference_to_curve\representation.items[1]\ geometric_representation_item.dim =2;
END_ENTITY;

ENTITY bounded_pcurve
  SUBTYPE OF (pcurve, bounded_curve);
WHERE
  WR1: ('GEOMETRY_SCHEMA.BOUNDED_CURVE' IN TYPEOF(SELF\pcurve.reference_to_curve.items[1]));
END_ENTITY;

ENTITY surface_curve
  SUPERTYPE OF (ONEOF (intersection_curve,
                       seam_curve)
               ANDOR bounded_surface_curve)
  SUBTYPE OF (curve);
  curve_3d : curve;
  associated_geometry : LIST[1:2] OF pcurve_or_surface;
  master_representation : preferred_surface_curve_representation;
DERIVE
  basis_surface : SET[1:2] OF surface := get_basis_surface(SELF);
WHERE
  WR1: curve_3d.dim = 3;
  WR2: ('GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(associated_geometry[1])) OR (master_representation <> pcurve_s1);
  WR3: ('GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(associated_geometry[2])) OR (master_representation <> pcurve_s2);
  WR4: NOT ('GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(curve_3d));
END_ENTITY;

ENTITY intersection_curve
  SUBTYPE OF (surface_curve);
WHERE
  WR1: SIZEOF(SELF\surface_curve.associated_geometry) = 2;
  WR2: associated_surface(SELF\surface_curve.associated_geometry[1]) <> associated_surface(SELF\surface_curve.associated_geometry[2]);
END_ENTITY;

ENTITY seam_curve
  SUBTYPE OF (surface_curve);
WHERE
  WR1: SIZEOF(SELF\surface_curve.associated_geometry) = 2;
  WR2: associated_surface(SELF\surface_curve.associated_geometry[1]) = associated_surface(SELF\surface_curve.associated_geometry[2]);
  WR3: 'GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(SELF\surface_curve.associated_geometry[1]);
  WR4: 'GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(SELF\surface_curve.associated_geometry[2]);
END_ENTITY;

ENTITY bounded_surface_curve
  SUBTYPE OF (surface_curve, bounded_curve);
WHERE
  WR1: ('GEOMETRY_SCHEMA.BOUNDED_CURVE' IN TYPEOF(SELF\surface_curve.curve_3d));
END_ENTITY;

ENTITY composite_curve_on_surface
  SUPERTYPE OF (boundary_curve)
  SUBTYPE OF (composite_curve);
DERIVE
  basis_surface : SET[0:2] OF surface := get_basis_surface(SELF);
WHERE
  WR1: SIZEOF(basis_surface) > 0;
  WR2: constraints_composite_curve_on_surface(SELF);
END_ENTITY;

ENTITY offset_curve_2d
  SUBTYPE OF (curve);
  basis_curve : curve;
  distance : length_measure;
  self_intersect : LOGICAL;
WHERE
  WR1: basis_curve.dim = 2;
END_ENTITY;

ENTITY offset_curve_3d
  SUBTYPE OF (curve);
  basis_curve : curve;
  distance : length_measure;
  self_intersect : LOGICAL;
  ref_direction : direction;
WHERE
  WR1: (basis_curve.dim = 3) AND (ref_direction.dim = 3);
END_ENTITY;

ENTITY curve_replica
  SUBTYPE OF (curve);
  parent_curve : curve;
  transformation : cartesian_transformation_operator;
WHERE
  WR1: transformation.dim = parent_curve.dim;
  WR2: acyclic_curve_replica (SELF, parent_curve);
END_ENTITY;

ENTITY surface
  SUPERTYPE OF (ONEOF (elementary_surface,
                       swept_surface,
                       bounded_surface,
                       offset_surface,
                       surface_replica))
  SUBTYPE OF (geometric_representation_item);
END_ENTITY;

ENTITY elementary_surface
  SUPERTYPE OF (ONEOF (plane,
                       cylindrical_surface,
                       conical_surface,
                       spherical_surface,
                       toroidal_surface))
  SUBTYPE OF (surface);
  position : axis2_placement_3d;
END_ENTITY;

ENTITY plane
  SUBTYPE OF (elementary_surface);
END_ENTITY;

ENTITY cylindrical_surface
  SUBTYPE OF (elementary_surface);
  radius : positive_length_measure;
END_ENTITY;

ENTITY conical_surface
  SUBTYPE OF (elementary_surface);
  radius : length_measure;
  semi_angle : plane_angle_measure;
WHERE
  WR1: radius >= 0.0;
END_ENTITY;

ENTITY spherical_surface
  SUBTYPE OF (elementary_surface);
  radius : positive_length_measure;
END_ENTITY;

ENTITY toroidal_surface
  SUBTYPE OF (elementary_surface);
  major_radius : positive_length_measure;
  minor_radius : positive_length_measure;
END_ENTITY;

ENTITY degenerate_toroidal_surface
  SUBTYPE OF (toroidal_surface);
  select_outer : BOOLEAN;
WHERE
  WR1: major_radius < minor_radius;
END_ENTITY;

ENTITY dupin_cyclide_surface
  SUBTYPE OF (elementary_surface);
  generalised_major_radius : positive_length_measure;
  generalised_minor_radius : positive_length_measure;
  skewness : length_measure;
WHERE
  WR1: skewness >= 0.0;
END_ENTITY;

ENTITY swept_surface
  SUPERTYPE OF (ONEOF (surface_of_linear_extrusion,
                       surface_of_revolution,
                       surface_curve_swept_surface,
                       fixed_reference_swept_surface))
  SUBTYPE OF (surface);
  swept_curve : curve;
END_ENTITY;

ENTITY surface_of_linear_extrusion
  SUBTYPE OF (swept_surface);
  extrusion_axis : vector;
END_ENTITY;

ENTITY surface_of_revolution
  SUBTYPE OF (swept_surface);
  axis_position : axis1_placement;
DERIVE
  axis_line : line := representation_item('')|| geometric_representation_item()|| curve()|| line(axis_position.location, representation_item('')|| geometric_representation_item()|| vector(axis_position.z, 1.0));
END_ENTITY;

ENTITY surface_curve_swept_surface
  SUBTYPE OF (swept_surface);
  directrix : curve;
  reference_surface : surface;
WHERE
  WR1: (NOT ('GEOMETRY_SCHEMA.SURFACE_CURVE' IN TYPEOF(directrix))) OR (reference_surface IN (directrix\surface_curve.basis_surface));
END_ENTITY;

ENTITY fixed_reference_swept_surface
  SUBTYPE OF (swept_surface);
  directrix : curve;
  fixed_reference : direction;
END_ENTITY;

ENTITY bounded_surface
  SUPERTYPE OF (ONEOF (b_spline_surface,
                       rectangular_trimmed_surface,
                       curve_bounded_surface,
                       rectangular_composite_surface,
                       locally_refined_spline_surface))
  SUBTYPE OF (surface);
END_ENTITY;

ENTITY b_spline_surface
  SUPERTYPE OF (ONEOF (b_spline_surface_with_knots,
                       uniform_surface,
                       quasi_uniform_surface,
                       bezier_surface)
               ANDOR rational_b_spline_surface)
  SUBTYPE OF (bounded_surface);
  u_degree : INTEGER;
  v_degree : INTEGER;
  control_points_list : LIST[2:?] OF LIST[2:?] OF cartesian_point;
  surface_form : b_spline_surface_form;
  u_closed : LOGICAL;
  v_closed : LOGICAL;
  self_intersect : LOGICAL;
DERIVE
  u_upper : INTEGER := SIZEOF(control_points_list) - 1;
  v_upper : INTEGER := SIZEOF(control_points_list[1]) - 1;
  control_points : ARRAY[0:u_upper] OF ARRAY[0:v_upper] OF cartesian_point := make_array_of_array(control_points_list, 0,u_upper,0,v_upper);
WHERE
  WR1: ('GEOMETRY_SCHEMA.UNIFORM_SURFACE' IN TYPEOF(SELF)) OR ('GEOMETRY_SCHEMA.QUASI_UNIFORM_SURFACE' IN TYPEOF(SELF)) OR ('GEOMETRY_SCHEMA.BEZIER_SURFACE' IN TYPEOF(SELF)) OR ('GEOMETRY_SCHEMA.B_SPLINE_SURFACE_WITH_KNOTS' IN TYPEOF(SELF));
END_ENTITY;

ENTITY b_spline_surface_with_knots
  SUBTYPE OF (b_spline_surface);
  u_multiplicities : LIST[2:?] OF INTEGER;
  v_multiplicities : LIST[2:?] OF INTEGER;
  u_knots : LIST[2:?] OF parameter_value;
  v_knots : LIST[2:?] OF parameter_value;
  knot_spec : knot_type;
DERIVE
  knot_u_upper : INTEGER := SIZEOF(u_knots);
  knot_v_upper : INTEGER := SIZEOF(v_knots);
WHERE
  WR1: constraints_param_b_spline(SELF\b_spline_surface.u_degree, knot_u_upper, SELF\b_spline_surface.u_upper, u_multiplicities, u_knots);
  WR2: constraints_param_b_spline(SELF\b_spline_surface.v_degree, knot_v_upper, SELF\b_spline_surface.v_upper, v_multiplicities, v_knots);
  WR3: SIZEOF(u_multiplicities) = knot_u_upper;
  WR4: SIZEOF(v_multiplicities) = knot_v_upper;
END_ENTITY;

ENTITY uniform_surface
  SUBTYPE OF (b_spline_surface);
END_ENTITY;

ENTITY quasi_uniform_surface
  SUBTYPE OF (b_spline_surface);
END_ENTITY;

ENTITY bezier_surface
  SUBTYPE OF (b_spline_surface);
END_ENTITY;

ENTITY rational_b_spline_surface
  SUBTYPE OF (b_spline_surface);
  weights_data : LIST[2:?] OF LIST[2:?] OF REAL;
DERIVE
  weights : ARRAY[0:u_upper] OF ARRAY[0:v_upper] OF REAL := make_array_of_array(weights_data,0,u_upper,0,v_upper);
WHERE
  WR1: (SIZEOF(weights_data) = SIZEOF(SELF\b_spline_surface.control_points_list)) AND (SIZEOF(weights_data[1]) = SIZEOF(SELF\b_spline_surface.control_points_list[1]));
  WR2: surface_weights_positive(SELF);
END_ENTITY;

ENTITY locally_refined_spline_surface
  SUBTYPE OF (bounded_surface);
  u_b_splines : LIST[4:?] OF local_b_spline;
  v_b_splines : LIST[4:?] OF local_b_spline;
  u_knots : spline_knot_values;
  v_knots : spline_knot_values;
  control_points_list : LIST[4:?] OF cartesian_point;
  scaling_factors : LIST[4:?] OF REAL;
  linearly_independent : linearly_independent_enum;
  locally_refined_spline_type : locally_refined_spline_type_enum;
  self_intersect : LOGICAL;
  u_closed : LOGICAL;
  v_closed : LOGICAL;
  domain : LIST[2:2] OF LIST[2:2] OF REAL;
WHERE
  WR1: SIZEOF(u_b_splines) = SIZEOF(control_points_list);
  WR2: SIZEOF(v_b_splines) = SIZEOF(control_points_list);
  WR3: SIZEOF(scaling_factors) = SIZEOF(control_points_list);
  WR4: constraints_scaling(scaling_factors);
END_ENTITY;

ENTITY rational_locally_refined_spline_surface
  SUBTYPE OF (locally_refined_spline_surface);
  weights_data : LIST[4:?] OF REAL;
WHERE
  WR1: SIZEOF(weights_data) = SIZEOF(SELF\locally_refined_spline_surface. control_points_list);
  WR2: weights_positive(weights_data);
END_ENTITY;

ENTITY rectangular_trimmed_surface
  SUBTYPE OF (bounded_surface);
  basis_surface : surface;
  u1 : parameter_value;
  u2 : parameter_value;
  v1 : parameter_value;
  v2 : parameter_value;
  usense : BOOLEAN;
  vsense : BOOLEAN;
WHERE
  WR1: u1 <> u2;
  WR2: v1 <> v2;
  WR3: (('GEOMETRY_SCHEMA.ELEMENTARY_SURFACE' IN TYPEOF(basis_surface)) AND (NOT ('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(basis_surface)))) OR ('GEOMETRY_SCHEMA.SURFACE_OF_REVOLUTION' IN TYPEOF(basis_surface)) OR (usense = (u2 > u1));
  WR4: (('GEOMETRY_SCHEMA.SPHERICAL_SURFACE' IN TYPEOF(basis_surface)) OR ('GEOMETRY_SCHEMA.TOROIDAL_SURFACE' IN TYPEOF(basis_surface))) OR (vsense = (v2 > v1));
END_ENTITY;

ENTITY curve_bounded_surface
  SUBTYPE OF (bounded_surface);
  basis_surface : surface;
  boundaries : SET[1:?] OF boundary_curve;
  implicit_outer : BOOLEAN;
WHERE
  WR1: (NOT implicit_outer) OR (SIZEOF (QUERY (temp <* boundaries | 'GEOMETRY_SCHEMA.OUTER_BOUNDARY_CURVE' IN TYPEOF(temp))) = 0);
  WR2: (NOT(implicit_outer)) OR ('GEOMETRY_SCHEMA.BOUNDED_SURFACE' IN TYPEOF(basis_surface));
  WR3: SIZEOF(QUERY(temp <* boundaries | 'GEOMETRY_SCHEMA.OUTER_BOUNDARY_CURVE' IN TYPEOF(temp))) <= 1;
  WR4: SIZEOF(QUERY(temp <* boundaries | (temp\composite_curve_on_surface.basis_surface [1] <> basis_surface))) = 0;
END_ENTITY;

ENTITY boundary_curve
  SUBTYPE OF (composite_curve_on_surface);
WHERE
  WR1: SELF\composite_curve.closed_curve;
END_ENTITY;

ENTITY outer_boundary_curve
  SUBTYPE OF (boundary_curve);
END_ENTITY;

ENTITY rectangular_composite_surface
  SUBTYPE OF (bounded_surface);
  segments : LIST[1:?] OF LIST[1:?] OF surface_patch;
DERIVE
  n_u : INTEGER := SIZEOF(segments);
  n_v : INTEGER := SIZEOF(segments[1]);
WHERE
  WR1: SIZEOF(QUERY (s <* segments | n_v <> SIZEOF (s))) = 0;
  WR2: constraints_rectangular_composite_surface(SELF);
END_ENTITY;

ENTITY surface_patch
  SUBTYPE OF (founded_item);
  parent_surface : bounded_surface;
  u_transition : transition_code;
  v_transition : transition_code;
  u_sense : BOOLEAN;
  v_sense : BOOLEAN;
INVERSE
  using_surfaces : BAG[1:?] OF rectangular_composite_surface FOR segments;
WHERE
  WR1: (NOT ('GEOMETRY_SCHEMA.CURVE_BOUNDED_SURFACE' IN TYPEOF(parent_surface)));
END_ENTITY;

ENTITY offset_surface
  SUBTYPE OF (surface);
  basis_surface : surface;
  distance : length_measure;
  self_intersect : LOGICAL;
END_ENTITY;

ENTITY oriented_surface
  SUBTYPE OF (surface);
  orientation : BOOLEAN;
END_ENTITY;

ENTITY surface_replica
  SUBTYPE OF (surface);
  parent_surface : surface;
  transformation : cartesian_transformation_operator_3d;
WHERE
  WR1: acyclic_surface_replica(SELF, parent_surface);
END_ENTITY;

ENTITY volume
  SUPERTYPE OF (ONEOF (block_volume,
                       wedge_volume,
                       spherical_volume,
                       cylindrical_volume,
                       eccentric_conical_volume,
                       toroidal_volume,
                       pyramid_volume,
                       b_spline_volume,
                       ellipsoid_volume,
                       tetrahedron_volume,
                       hexahedron_volume,
                       locally_refined_spline_volume))
  SUBTYPE OF (geometric_representation_item);
WHERE
  WR1: SELF\geometric_representation_item.dim = 3;
END_ENTITY;

ENTITY block_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  x : positive_length_measure;
  y : positive_length_measure;
  z : positive_length_measure;
END_ENTITY;

ENTITY wedge_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  x : positive_length_measure;
  y : positive_length_measure;
  z : positive_length_measure;
  ltx : length_measure;
WHERE
  WR1: ((0.0 <= ltx) AND (ltx < x));
END_ENTITY;

ENTITY pyramid_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  xlength : positive_length_measure;
  ylength : positive_length_measure;
  height : positive_length_measure;
END_ENTITY;

ENTITY tetrahedron_volume
  SUBTYPE OF (volume);
  point_1 : cartesian_point;
  point_2 : cartesian_point;
  point_3 : cartesian_point;
  point_4 : cartesian_point;
WHERE
  WR1: point_1.dim = 3;
  WR2: above_plane(point_1, point_2, point_3, point_4) <> 0.0;
END_ENTITY;

ENTITY hexahedron_volume
  SUBTYPE OF (volume);
  points : LIST[8:8] OF cartesian_point;
WHERE
  WR1: above_plane(points[1], points[2], points[3], points[4]) = 0.0;
  WR2: above_plane(points[5], points[8], points[7], points[6]) = 0.0;
  WR3: above_plane(points[1], points[4], points[8], points[5]) = 0.0;
  WR4: above_plane(points[4], points[3], points[7], points[8]) = 0.0;
  WR5: above_plane(points[3], points[2], points[6], points[7]) = 0.0;
  WR6: above_plane(points[1], points[5], points[6], points[2]) = 0.0;
  WR7: same_side([points[1], points[2], points[3]], [points[5], points[6], points[7], points[8]]);
  WR8: same_side([points[1], points[4], points[8]], [points[3], points[7], points[6], points[2]]);
  WR9: same_side([points[1], points[2], points[5]], [points[3], points[7], points[8], points[4]]);
  WR10: same_side([points[5], points[6], points[7]], [points[1], points[2], points[3], points[4]]);
  WR11: same_side([points[3], points[7], points[6]], [points[1], points[4], points[8], points[5]]);
  WR12: same_side([points[3], points[7], points[8]], [points[1], points[5], points[6], points[2]]);
  WR13: points[1].dim = 3;
END_ENTITY;

ENTITY spherical_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  radius : positive_length_measure;
END_ENTITY;

ENTITY cylindrical_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  radius : positive_length_measure;
  height : positive_length_measure;
END_ENTITY;

ENTITY eccentric_conical_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  semi_axis_1 : positive_length_measure;
  semi_axis_2 : positive_length_measure;
  height : positive_length_measure;
  x_offset : length_measure;
  y_offset : length_measure;
  ratio : REAL;
WHERE
  WR1: ratio >= 0.0;
END_ENTITY;

ENTITY toroidal_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  major_radius : positive_length_measure;
  minor_radius : positive_length_measure;
WHERE
  WR1: minor_radius < major_radius;
END_ENTITY;

ENTITY ellipsoid_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  semi_axis_1 : positive_length_measure;
  semi_axis_2 : positive_length_measure;
  semi_axis_3 : positive_length_measure;
END_ENTITY;

ENTITY b_spline_volume
  SUPERTYPE OF (ONEOF (b_spline_volume_with_knots,
                       uniform_volume,
                       quasi_uniform_volume,
                       bezier_volume)
               ANDOR rational_b_spline_volume)
  SUBTYPE OF (volume);
  u_degree : INTEGER;
  v_degree : INTEGER;
  w_degree : INTEGER;
  control_points_list : LIST[2:?] OF LIST[2:?] OF LIST[2:?] OF cartesian_point;
DERIVE
  u_upper : INTEGER := SIZEOF(control_points_list) - 1;
  v_upper : INTEGER := SIZEOF(control_points_list[1]) - 1;
  w_upper : INTEGER := SIZEOF(control_points_list[1][1]) - 1;
  control_points : ARRAY[0:u_upper] OF ARRAY[0:v_upper] OF ARRAY[0:w_upper] OF cartesian_point := make_array_of_array_of_array (control_points_list, 0,u_upper,0,v_upper, 0,w_upper );
WHERE
  WR1: ('GEOMETRY_SCHEMA.BEZIER_VOLUME' IN TYPEOF(SELF)) OR ('GEOMETRY_SCHEMA.UNIFORM_VOLUME' IN TYPEOF(SELF)) OR ('GEOMETRY_SCHEMA.QUASI_UNIFORM_VOLUME' IN TYPEOF(SELF)) OR ('GEOMETRY_SCHEMA.B_SPLINE_VOLUME_WITH_KNOTS' IN TYPEOF(SELF));
END_ENTITY;

ENTITY b_spline_volume_with_knots
  SUBTYPE OF (b_spline_volume);
  u_multiplicities : LIST[2:?] OF INTEGER;
  v_multiplicities : LIST[2:?] OF INTEGER;
  w_multiplicities : LIST[2:?] OF INTEGER;
  u_knots : LIST[2:?] OF parameter_value;
  v_knots : LIST[2:?] OF parameter_value;
  w_knots : LIST[2:?] OF parameter_value;
DERIVE
  knot_u_upper : INTEGER := SIZEOF(u_knots);
  knot_v_upper : INTEGER := SIZEOF(v_knots);
  knot_w_upper : INTEGER := SIZEOF(w_knots);
WHERE
  WR1: constraints_param_b_spline(SELF\b_spline_volume.u_degree, knot_u_upper, SELF\b_spline_volume.u_upper, u_multiplicities, u_knots);
  WR2: constraints_param_b_spline(SELF\b_spline_volume.v_degree, knot_v_upper, SELF\b_spline_volume.v_upper, v_multiplicities, v_knots);
  WR3: constraints_param_b_spline(SELF\b_spline_volume.w_degree, knot_w_upper, SELF\b_spline_volume.w_upper, w_multiplicities, w_knots);
  WR4: SIZEOF(u_multiplicities) = knot_u_upper;
  WR5: SIZEOF(v_multiplicities) = knot_v_upper;
  WR6: SIZEOF(w_multiplicities) = knot_w_upper;
END_ENTITY;

ENTITY bezier_volume
  SUBTYPE OF (b_spline_volume);
END_ENTITY;

ENTITY uniform_volume
  SUBTYPE OF (b_spline_volume);
END_ENTITY;

ENTITY quasi_uniform_volume
  SUBTYPE OF (b_spline_volume);
END_ENTITY;

ENTITY rational_b_spline_volume
  SUBTYPE OF (b_spline_volume);
  weights_data : LIST[2:?] OF LIST[2:?] OF LIST[2:?] OF REAL;
DERIVE
  weights : ARRAY[0:u_upper] OF ARRAY[0:v_upper] OF ARRAY[0:w_upper] OF REAL := make_array_of_array_of_array (weights_data,0,u_upper,0,v_upper,0,w_upper);
WHERE
  WR1: (SIZEOF(weights_data) = SIZEOF(SELF\b_spline_volume.control_points_list)) AND (SIZEOF(weights_data[1]) = SIZEOF(SELF\b_spline_volume.control_points_list[1])) AND (SIZEOF(weights_data[1][1]) = SIZEOF(SELF\b_spline_volume.control_points_list[1][1]));
  WR2: volume_weights_positive(SELF);
END_ENTITY;

ENTITY locally_refined_spline_volume
  SUBTYPE OF (volume);
  u_b_splines : LIST[8:?] OF local_b_spline;
  v_b_splines : LIST[8:?] OF local_b_spline;
  w_b_splines : LIST[8:?] OF local_b_spline;
  u_knots : spline_knot_values;
  v_knots : spline_knot_values;
  w_knots : spline_knot_values;
  control_points_list : LIST[8:?] OF cartesian_point;
  scaling_factors : LIST[8:?] OF REAL;
  linearly_independent : linearly_independent_enum;
  locally_refined_spline_type : locally_refined_spline_type_enum;
  domain : LIST[3:3] OF LIST[2:2] OF REAL;
WHERE
  WR1: SIZEOF(u_b_splines) = SIZEOF(control_points_list);
  WR2: SIZEOF(v_b_splines) = SIZEOF(control_points_list);
  WR3: SIZEOF(w_b_splines) = SIZEOF(control_points_list);
  WR4: SIZEOF(scaling_factors) = SIZEOF(control_points_list);
  WR5: constraints_scaling(scaling_factors);
END_ENTITY;

ENTITY rational_locally_refined_spline_volume
  SUBTYPE OF (locally_refined_spline_volume);
  weights_data : LIST[8:?] OF REAL;
WHERE
  WR1: SIZEOF(weights_data) = SIZEOF(SELF\locally_refined_spline_volume.control_points_list);
  WR2: weights_positive(weights_data);
END_ENTITY;

RULE compatible_dimension FOR
(cartesian_point,direction,geometric_representation_context);
WHERE
  WR1: ((SIZEOF(cartesian_point) = 0) AND (SIZEOF(direction) = 0) AND (SIZEOF(geometric_representation_context) = 0)) OR check_geometric_dimension(cartesian_point, direction, geometric_representation_context);
END_RULE;

FUNCTION above_plane
 (p1 : cartesian_point; p2 : cartesian_point; p3 : cartesian_point; p4 : cartesian_point) : REAL;
LOCAL
     dir2, dir3, dir4 : direction :=
                 dummy_gri || direction([1.0, 0.0, 0.0]);
     val, mag         : REAL;
   END_LOCAL;

   IF (p1.dim <> 3) THEN
     RETURN(?);
   END_IF;
   REPEAT i := 1 TO 3;
     dir2.direction_ratios[i] := p2.coordinates[i] - p1.coordinates[i];
     dir3.direction_ratios[i] := p3.coordinates[i] - p1.coordinates[i];
     dir4.direction_ratios[i] := p4.coordinates[i] - p1.coordinates[i];
     mag := dir4.direction_ratios[i]*dir4.direction_ratios[i];
  END_REPEAT;
  mag := sqrt(mag);
  val := mag*dot_product(dir4, cross_product(dir2, dir3).orientation);
  RETURN(val);
END_FUNCTION;

FUNCTION acyclic_curve_replica
 (rep : curve_replica; parent : curve) : BOOLEAN;
IF NOT (('GEOMETRY_SCHEMA.CURVE_REPLICA') IN TYPEOF(parent)) THEN
      RETURN (TRUE);
   END_IF;
 (* Return TRUE if the parent is not of type curve_replica *)
   IF (parent :=: rep) THEN
      RETURN (FALSE);
  (* Return FALSE if the parent is the same curve_replica, otherwise,
   call function again with the parents own parent_curve.     *)
    ELSE
    RETURN(acyclic_curve_replica(rep,
               parent\curve_replica.parent_curve));
    END_IF;
END_FUNCTION;

FUNCTION acyclic_point_replica
 (rep : point_replica; parent : point) : BOOLEAN;
IF NOT (('GEOMETRY_SCHEMA.POINT_REPLICA') IN TYPEOF(parent)) THEN
      RETURN (TRUE);
   END_IF;
 (* Return TRUE if the parent is not of type point_replica *)
   IF (parent :=: rep) THEN
      RETURN (FALSE);
  (* Return FALSE if the parent is the same point_replica, otherwise,
   call function again with the parents own parent_pt.     *)
    ELSE RETURN(acyclic_point_replica(rep, parent\point_replica.parent_pt));
    END_IF;
END_FUNCTION;

FUNCTION acyclic_surface_replica
 (rep : surface_replica; parent : surface) : BOOLEAN;
IF NOT (('GEOMETRY_SCHEMA.SURFACE_REPLICA') IN TYPEOF(parent)) THEN
      RETURN (TRUE);
   END_IF;
 (* Return TRUE if the parent is not of type surface_replica *)
   IF (parent :=: rep) THEN
      RETURN (FALSE);
  (* Return FALSE if the parent is the same surface_replica, otherwise,
   call function again with the parents own parent_surface.     *)
    ELSE RETURN(acyclic_surface_replica(rep,
                   parent\surface_replica.parent_surface));
    END_IF;
END_FUNCTION;

FUNCTION associated_surface
 (arg : pcurve_or_surface) : surface;
LOCAL
     surf : surface;
   END_LOCAL;
   
   IF 'GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(arg) THEN
     surf := arg\pcurve.basis_surface;
   ELSE
     surf := arg;
   END_IF;
   RETURN(surf);
END_FUNCTION;

FUNCTION base_axis
 (dim : INTEGER; axis1 : direction; axis2 : direction; axis3 : direction) : LIST[2:3] OF direction;
LOCAL
    u      : LIST [2:3] OF direction;
    factor : REAL;
    d1, d2 : direction;
  END_LOCAL;
  
  IF (dim = 3) THEN
    d1 := NVL(normalise(axis3),  dummy_gri || direction([0.0,0.0,1.0]));
    d2 := first_proj_axis(d1,axis1);
    u := [d2, second_proj_axis(d1,d2,axis2), d1];
  ELSE
     IF EXISTS(axis1) THEN
      d1 := normalise(axis1);
      u := [d1, orthogonal_complement(d1)];
      IF EXISTS(axis2) THEN
        factor := dot_product(axis2,u[2]);
        IF (factor < 0.0) THEN
          u[2].direction_ratios[1] := -u[2].direction_ratios[1];
          u[2].direction_ratios[2] := -u[2].direction_ratios[2];
        END_IF;
      END_IF;
    ELSE
      IF EXISTS(axis2) THEN
        d1 := normalise(axis2);
        u := [orthogonal_complement(d1), d1]; 
        u[1].direction_ratios[1] := -u[1].direction_ratios[1];
        u[1].direction_ratios[2] := -u[1].direction_ratios[2];
      ELSE
        u := [dummy_gri || direction([1.0, 0.0]), dummy_gri ||
                                                direction([0.0, 1.0])];
      END_IF;
    END_IF;
  END_IF;
  RETURN(u);
END_FUNCTION;

FUNCTION build_2axes
 (ref_direction : direction) : LIST[2:2] OF direction;
LOCAL
     d : direction := NVL(normalise(ref_direction),
                          dummy_gri || direction([1.0,0.0]));
   END_LOCAL;

   RETURN([d, orthogonal_complement(d)]);
END_FUNCTION;

FUNCTION build_axes
 (axis : direction; ref_direction : direction) : LIST[3:3] OF direction;
LOCAL
       d1, d2 : direction;
     END_LOCAL;
    d1 := NVL(normalise(axis), dummy_gri || direction([0.0,0.0,1.0]));
    d2 := first_proj_axis(d1, ref_direction);
    RETURN([d2, normalise(cross_product(d1,d2))\vector.orientation, d1]);
END_FUNCTION;

FUNCTION check_geometric_dimension
 (capt : SET[0:?] OF cartesian_point; dir : SET[0:?] OF direction; grc : SET[1:?] OF geometric_representation_context) : BOOLEAN;
LOCAL
  globaldim    : INTEGER := 0; (* means mixed dimensionality *)
  reps         : SET [0:?] OF representation := [];
  result       : BOOLEAN := TRUE; (* means no error *)
END_LOCAL;

globaldim:= geometric_dimensionalities_in_contexts(grc);

IF (globaldim > 0) then
(* Same dimension for all contexts; only one check needed. *)
  IF (SIZEOF(capt) > 0) THEN
    REPEAT i := 1 TO HIINDEX(capt);
      IF (HIINDEX(capt[i].coordinates) <> globaldim) THEN
        RETURN(FALSE);
      END_IF;
    END_REPEAT;
  END_IF;
  IF (SIZEOF(dir) > 0) THEN
    REPEAT i := 1 TO HIINDEX(dir);
      IF  (HIINDEX(dir[i].direction_ratios) <> globaldim) THEN
        RETURN(FALSE);
      END_IF;
    END_REPEAT;
  END_IF;
  RETURN(result);
ELSE
(*  globaldim=0, mixed dimensions for contexts; check needed for context of each representation in which gri is used. *)
  IF (SIZEOF(capt) > 0) THEN
    REPEAT i := 1 TO HIINDEX(capt);
      reps := using_representations(capt[i]);
      IF (SIZEOF(reps) > 0) THEN
        REPEAT j := 1 TO HIINDEX(reps);
          IF (HIINDEX(capt[i].coordinates) <> reps[j].context_of_items\geometric_representation_context.coordinate_space_dimension) THEN
            RETURN(FALSE);
          END_IF;
        END_REPEAT;
      ELSE (* zero reps *)
        RETURN(FALSE);
      END_IF;
    END_REPEAT;
  END_IF;
  IF (SIZEOF(dir) > 0) THEN
    REPEAT i := 1 TO HIINDEX(dir);
    (*  globaldim=0, Mixed dimensions for  contexts, check needed for context of each representation in which gri is used *)
      reps := using_representations(dir[i]);
      IF (SIZEOF(reps) > 0) THEN
        REPEAT j := 1 TO HIINDEX(reps);
          IF (HIINDEX(dir[i].direction_ratios) <> reps[j].context_of_items\geometric_representation_context.coordinate_space_dimension) THEN
            RETURN(FALSE);
          END_IF;
        END_REPEAT;
      ELSE (* zero reps *)
        RETURN(FALSE);
      END_IF;
    END_REPEAT;
  END_IF;
END_IF;

RETURN(result);
END_FUNCTION;

FUNCTION constraints_composite_curve_on_surface
 (c : composite_curve_on_surface) : BOOLEAN;
LOCAL
     n_segments : INTEGER := SIZEOF(c.segments);
   END_LOCAL;
        
   REPEAT k := 1 TO n_segments;
     IF (NOT('GEOMETRY_SCHEMA.PCURVE' IN 
           TYPEOF(c\composite_curve.segments[k].parent_curve))) AND
        (NOT('GEOMETRY_SCHEMA.SURFACE_CURVE' IN 
           TYPEOF(c\composite_curve.segments[k].parent_curve))) AND
        (NOT('GEOMETRY_SCHEMA.COMPOSITE_CURVE_ON_SURFACE' IN
           TYPEOF(c\composite_curve.segments[k].parent_curve)))  THEN
       RETURN (FALSE);
     END_IF;
   END_REPEAT;
   RETURN(TRUE);
END_FUNCTION;

FUNCTION constraints_param_b_spline
 (degree : INTEGER; up_knots : INTEGER; up_cp : INTEGER; knot_mult : LIST[0:?] OF INTEGER; knots : LIST[0:?] OF parameter_value) : BOOLEAN;
LOCAL
     result  : BOOLEAN := TRUE;
     k, sum  : INTEGER;
   END_LOCAL;
   
   (* Find sum of knot multiplicities. *)
   sum := knot_mult[1];
   
   REPEAT i := 2 TO up_knots;
     sum := sum + knot_mult[i];
   END_REPEAT;
   
   (* Check limits holding for all B-spline parametrisations *)
   IF (degree < 1) OR (up_knots < 2) OR (up_cp < degree) OR
         (sum <> (degree + up_cp + 2)) THEN
     result := FALSE;
     RETURN(result);
   END_IF;
   
   k := knot_mult[1];
   
   IF (k < 1) OR (k > degree + 1) THEN
     result := FALSE;
     RETURN(result);
   END_IF;
      
   REPEAT i := 2 TO up_knots;
     IF (knot_mult[i] < 1) OR (knots[i] <= knots[i-1]) THEN
       result := FALSE;
       RETURN(result);
     END_IF;
        
     k := knot_mult[i];
     
     IF (i < up_knots) AND (k > degree) THEN
       result := FALSE;
       RETURN(result);
     END_IF;
        
     IF (i = up_knots) AND (k > degree + 1) THEN
       result := FALSE;
       RETURN(result);
     END_IF;
   END_REPEAT;
   RETURN(result);
END_FUNCTION;

FUNCTION constraints_param_local_b_spline
 (degree : INTEGER; knot_mult : LIST[0:?] OF INTEGER; knots : LIST[0:?] OF INTEGER) : BOOLEAN;
LOCAL
  result : BOOLEAN := TRUE;
  k, up_knots, sum : INTEGER;
END_LOCAL;
(* Find sum of knot multiplicities. *)
  up_knots := SIZEOF(knots);
  sum := knot_mult[1];
REPEAT i := 2 TO up_knots;
  sum := sum + knot_mult[i];
END_REPEAT;
(* Check limits holding for all B-spline parametrisations *)
IF (degree < 1) OR (up_knots < 2) OR 
(sum <> (degree + 2)) THEN
  result := FALSE;
RETURN(result);
END_IF;
k := knot_mult[1];
IF (k < 1) OR (k > degree + 1) THEN
  result := FALSE;
  RETURN(result);
END_IF;
(* first pointer shall be 1 or more *)
IF (knots[1] < 1) THEN
 result :=  FALSE;
END_IF;
REPEAT i := 2 TO up_knots;
 IF (knot_mult[i] < 1) OR (knots[i] <= knots[i-1]) THEN
 result := FALSE;
 RETURN(result);
END_IF;
k := knot_mult[i];
IF (i < up_knots) AND (k > degree) THEN
 result := FALSE;
 RETURN(result);
END_IF;
IF (i = up_knots) AND (k > degree + 1) THEN
 result := FALSE;
 RETURN(result);
END_IF;
END_REPEAT;
RETURN(result);
END_FUNCTION;

FUNCTION constraints_rectangular_composite_surface
 (s : rectangular_composite_surface) : BOOLEAN;
REPEAT i := 1 TO s.n_u;
       REPEAT j := 1 TO s.n_v;
         IF NOT (('GEOMETRY_SCHEMA.B_SPLINE_SURFACE' IN TYPEOF
                    (s.segments[i][j].parent_surface)) OR
                 ('GEOMETRY_SCHEMA.RECTANGULAR_TRIMMED_SURFACE' IN TYPEOF
                    (s.segments[i][j].parent_surface))) THEN
           RETURN(FALSE);
       END_IF;
     END_REPEAT;
   END_REPEAT;

   (* Check the transition codes, omitting the last row or column *)
   REPEAT i := 1 TO s.n_u-1;
     REPEAT j := 1 TO s.n_v;
       IF s.segments[i][j].u_transition = discontinuous THEN
         RETURN(FALSE);
       END_IF;
     END_REPEAT;
   END_REPEAT;
   
   REPEAT i := 1 TO s.n_u;
     REPEAT j := 1 TO s.n_v-1;
       IF s.segments[i][j].v_transition = discontinuous THEN
         RETURN(FALSE);
       END_IF;
     END_REPEAT;
   END_REPEAT;
   RETURN(TRUE);
END_FUNCTION;

FUNCTION constraints_scaling
 (factors : LIST[0:?] OF REAL) : BOOLEAN;
LOCAL
result : BOOLEAN := TRUE;
END_LOCAL;
REPEAT i := 1 TO SIZEOF(factors);
IF NOT({0.0 < factors[i] <= 1.0}) THEN
result := FALSE;
RETURN(result);
END_IF;
END_REPEAT;
RETURN(result);
END_FUNCTION;

FUNCTION cross_product
 (arg1 : direction; arg2 : direction) : vector;
LOCAL
    mag    : REAL;
    res    : direction;
    v1,v2  : LIST[3:3] OF REAL;
    result : vector;
  END_LOCAL;
  
  IF ( NOT EXISTS (arg1) OR (arg1.dim = 2)) OR
     ( NOT EXISTS (arg2) OR (arg2.dim = 2)) THEN
    RETURN(?);
  ELSE
    BEGIN
      v1  := normalise(arg1).direction_ratios;
      v2  := normalise(arg2).direction_ratios;
      res := dummy_gri || direction([(v1[2]*v2[3] - v1[3]*v2[2]),
            (v1[3]*v2[1] - v1[1]*v2[3]), (v1[1]*v2[2] - v1[2]*v2[1])]);
      mag := 0.0;
      REPEAT i := 1 TO 3;
        mag := mag + res.direction_ratios[i]*res.direction_ratios[i];
      END_REPEAT;
      IF (mag > 0.0) THEN
        result := dummy_gri || vector(res, SQRT(mag));
      ELSE
        result := dummy_gri || vector(arg1, 0.0);
      END_IF;
      RETURN(result);
    END;
  END_IF;
END_FUNCTION;

FUNCTION curve_weights_positive
 (b : rational_b_spline_curve) : BOOLEAN;
LOCAL
     result : BOOLEAN := TRUE;
   END_LOCAL;

   REPEAT i := 0 TO b.upper_index_on_control_points;
     IF b.weights[i] <= 0.0  THEN
       result := FALSE;
       RETURN(result);
     END_IF;
   END_REPEAT;
   RETURN(result);
END_FUNCTION;

FUNCTION default_b_spline_curve_weights
 (up_cp : INTEGER) : ARRAY[0:up_cp] OF REAL;
RETURN([1:up_cp + 1]);
END_FUNCTION;

FUNCTION default_b_spline_knot_mult
 (degree : INTEGER; up_knots : INTEGER; uniform : knot_type) : LIST[2:?] OF INTEGER;
LOCAL
     knot_mult : LIST [1:up_knots] OF INTEGER;
   END_LOCAL;
        
   IF uniform = uniform_knots THEN
     knot_mult := [1:up_knots];
   ELSE
     IF uniform = quasi_uniform_knots THEN
       knot_mult := [1:up_knots];
       knot_mult[1] := degree + 1;
       knot_mult[up_knots] := degree + 1;
     ELSE
       IF uniform = piecewise_bezier_knots THEN
         knot_mult := [degree:up_knots];
         knot_mult[1] := degree + 1;
         knot_mult[up_knots] := degree + 1;
       ELSE
         knot_mult := [0:up_knots];
       END_IF;
     END_IF;
   END_IF;
   RETURN(knot_mult);
END_FUNCTION;

FUNCTION default_b_spline_knots
 (degree : INTEGER; up_knots : INTEGER; uniform : knot_type) : LIST[2:?] OF parameter_value;
LOCAL
    knots  : LIST [1:up_knots] OF parameter_value := [0:up_knots];
    ishift : INTEGER := 1;
  END_LOCAL;

  IF (uniform = uniform_knots) THEN
     ishift := degree + 1;
  END_if;
  IF (uniform = uniform_knots) OR 
     (uniform = quasi_uniform_knots) OR
     (uniform = piecewise_bezier_knots) THEN
    
    REPEAT i := 1 TO up_knots;
      knots[i] := i - ishift;
    END_REPEAT;
  END_IF;
  RETURN(knots);
END_FUNCTION;

FUNCTION default_b_spline_surface_weights
 (u_upper : INTEGER; v_upper : INTEGER) : ARRAY[0:u_upper] OF ARRAY[0:v_upper] OF REAL;
RETURN([[1:v_upper + 1]:u_upper +1]);
END_FUNCTION;

FUNCTION dimension_of
 (item : geometric_representation_item) : dimension_count;
LOCAL
    x   : SET OF representation;
    y   : representation_context;
    dim : dimension_count;
  END_LOCAL;
  -- For cartesian_point, direction, or vector dimension is determined by
  -- counting components.
    IF 'GEOMETRY_SCHEMA.CARTESIAN_POINT' IN TYPEOF(item) THEN
       dim := SIZEOF(item\cartesian_point.coordinates);
       RETURN(dim);
    END_IF;
    IF 'GEOMETRY_SCHEMA.DIRECTION' IN TYPEOF(item) THEN
       dim := SIZEOF(item\direction.direction_ratios);
       RETURN(dim);
    END_IF;
    IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(item) THEN
       dim := SIZEOF(item\vector.orientation\direction.direction_ratios);
       RETURN(dim);
    END_IF;
  -- For all other types of geometric_representation_item dim is obtained
  -- via context.
  -- Find the set of representation in which the item is used. 

  x := using_representations(item);

  -- Determines the dimension_count of the 
  -- geometric_representation_context.
  -- The SET x is non-empty for legal instances since this is required by WR1 of
  -- representation_item.
    IF (SIZEOF(x) > 0) THEN
       y := x[1].context_of_items;
      dim := y\geometric_representation_context.coordinate_space_dimension;
    RETURN (dim);
    ELSE
      RETURN(?);
    -- mark error by returning indeterminate result
   END_IF;
END_FUNCTION;

FUNCTION dot_product
 (arg1 : direction; arg2 : direction) : REAL;
LOCAL
     scalar : REAL;
     vec1, vec2: direction;
     ndim : INTEGER;
   END_LOCAL;
   
   IF NOT EXISTS (arg1) OR NOT EXISTS (arg2) THEN
     scalar := ?;
     (* When function is called with invalid data an indeterminate result
     is returned *)
   ELSE
     IF (arg1.dim <> arg2.dim) THEN
       scalar := ?;
     (* When function is called with invalid data an indeterminate result
     is returned *)
     ELSE
       BEGIN
         vec1   := normalise(arg1);
         vec2   := normalise(arg2);
         ndim   := arg1.dim;
         scalar := 0.0;
         REPEAT  i := 1 TO ndim;
           scalar := scalar +
                       vec1.direction_ratios[i]*vec2.direction_ratios[i];
         END_REPEAT;
       END;
     END_IF;
   END_IF;
   RETURN (scalar);
END_FUNCTION;

FUNCTION first_proj_axis
 (z_axis : direction; arg : direction) : direction;
LOCAL
    x_axis : direction;
    v      : direction;
    z      : direction;
    x_vec  : vector;
  END_LOCAL;
  
  IF (NOT EXISTS(z_axis)) THEN
    RETURN (?) ;
  ELSE
    z := normalise(z_axis);
    IF NOT EXISTS(arg) THEN
      IF ((z.direction_ratios <> [1.0,0.0,0.0]) AND
          (z.direction_ratios <> [-1.0,0.0,0.0]))  THEN
        v :=  dummy_gri || direction([1.0,0.0,0.0]);
      ELSE
        v := dummy_gri || direction([0.0,1.0,0.0]);
      END_IF;
    ELSE
      IF  (arg.dim <> 3) THEN
        RETURN (?) ;
      END_IF;
      IF ((cross_product(arg,z).magnitude) = 0.0) THEN
        RETURN (?);
      ELSE
        v := normalise(arg);
      END_IF;
    END_IF;
    x_vec := scalar_times_vector(dot_product(v, z), z);
    x_axis := vector_difference(v, x_vec).orientation;
    x_axis := normalise(x_axis);
  END_IF;
  RETURN(x_axis);
END_FUNCTION;

FUNCTION geometric_dimensionalities_in_contexts
 (grcs : SET[1:?] OF geometric_representation_context) : INTEGER;
LOCAL
  grcs_1d : INTEGER := 0;
  grcs_2d : INTEGER := 0;
  grcs_3d : INTEGER := 0;
END_LOCAL;

IF (SIZEOF(grcs) = 1) THEN
  (* only one geometric_context, will be one type of dimension anyway *)
  RETURN(grcs[1]\geometric_representation_context.coordinate_space_dimension);
ELSE
  REPEAT i := 1 TO HIINDEX(grcs);
    IF (grcs[i]\geometric_representation_context.coordinate_space_dimension = 1) THEN
      grcs_1d := grcs_1d + 1;
    ELSE
      IF (grcs[i]\geometric_representation_context.coordinate_space_dimension = 2) THEN
        grcs_2d := grcs_2d + 1;
      ELSE
        IF (grcs[i]\geometric_representation_context.coordinate_space_dimension = 3) THEN
          grcs_3d := grcs_3d + 1;
        END_IF;
      END_IF;
    END_IF;
  END_REPEAT;
END_IF;

IF (grcs_1d + grcs_2d = 0) THEN
  RETURN(3);
ELSE
  IF (grcs_1d + grcs_3d = 0) THEN
    RETURN(2);
  ELSE
    IF (grcs_2d + grcs_3d = 0) THEN
      RETURN(1);
    ELSE
      RETURN(0); (* multiple dimensions *)
    END_IF;
  END_IF;
END_IF;
END_FUNCTION;

FUNCTION get_basis_surface
 (c : curve_on_surface) : SET[0:2] OF surface;
LOCAL
    surfs  : SET[0:2] OF surface;
    n      : INTEGER;
  END_LOCAL;
  surfs := [];
  IF 'GEOMETRY_SCHEMA.PCURVE' IN TYPEOF (c) THEN
    surfs := [c\pcurve.basis_surface];
  ELSE
    IF 'GEOMETRY_SCHEMA.SURFACE_CURVE' IN TYPEOF (c) THEN
      n := SIZEOF(c\surface_curve.associated_geometry);
      REPEAT i := 1 TO n;
      surfs := surfs +
                associated_surface(c\surface_curve.associated_geometry[i]);
      END_REPEAT;
    END_IF;
  END_IF;
  IF 'GEOMETRY_SCHEMA.COMPOSITE_CURVE_ON_SURFACE' IN TYPEOF (c) THEN
   (* For a composite_curve_on_surface the basis_surface is the intersection
    of the basis_surfaces of all the segments. *)
     n := SIZEOF(c\composite_curve.segments);
     surfs := get_basis_surface(
                     c\composite_curve.segments[1].parent_curve);
     IF n > 1 THEN
       REPEAT i := 2 TO n;
         surfs := surfs * get_basis_surface(
                  c\composite_curve.segments[i].parent_curve);
       END_REPEAT;
     END_IF;

  END_IF;
  RETURN(surfs);
END_FUNCTION;

FUNCTION increasing_values_in_list
 (values : LIST[2:?] OF REAL) : BOOLEAN;
LOCAL
result : BOOLEAN := TRUE;
limit : INTEGER := SIZEOF(values);
END_LOCAL;
REPEAT i := 2 TO limit;
 IF values[i] <= values[i-1] THEN
   result := FALSE;
 END_IF;
END_REPEAT;
RETURN(result);
END_FUNCTION;

FUNCTION list_to_array
 (lis : LIST[0:?] OF GENERIC : T; low : INTEGER; u : INTEGER) : ARRAY[low:u] OF GENERIC : T;
LOCAL
     n   : INTEGER;
     res : ARRAY [low:u] OF GENERIC : T;
   END_LOCAL;
      
   n := SIZEOF(lis);
   IF (n <> (u-low +1)) THEN
     RETURN(?);
   ELSE
     res := [lis[1] : n];
     REPEAT i := 2 TO n;
       res[low+i-1] := lis[i];
     END_REPEAT;
     RETURN(res);
   END_IF;
END_FUNCTION;

FUNCTION make_array_of_array
 (lis : LIST[1:?] OF LIST[1:?] OF GENERIC : T; low1 : INTEGER; u1 : INTEGER; low2 : INTEGER; u2 : INTEGER) : ARRAY[low1:u1] OF ARRAY[low2:u2] OF GENERIC : T;
LOCAL
     res   : ARRAY[low1:u1] OF ARRAY [low2:u2] OF GENERIC : T;
   END_LOCAL;

(* Check input dimensions for consistency *)
   IF (u1-low1+1) <> SIZEOF(lis) THEN
     RETURN (?);
   END_IF;
   IF (u2 - low2 + 1 ) <> SIZEOF(lis[1]) THEN
     RETURN (?) ;
   END_IF;
(* Initialise res with values from lis[1] *)
   res := [list_to_array(lis[1], low2, u2) : (u1-low1 + 1)];
   REPEAT i := 2 TO HIINDEX(lis);
     IF (u2-low2+1) <> SIZEOF(lis[i]) THEN
       RETURN (?);
     END_IF;     
     res[low1+i-1] := list_to_array(lis[i], low2, u2);
   END_REPEAT; 
   
   RETURN (res);
END_FUNCTION;

FUNCTION make_array_of_array_of_array
 (lis : LIST[1:?] OF LIST[1:?] OF LIST[1:?] OF GENERIC : T; low1 : INTEGER; u1 : INTEGER; low2 : INTEGER; u2 : INTEGER; low3 : INTEGER; u3 : INTEGER) : ARRAY[low1:u1] OF ARRAY[low2:u2] OF ARRAY[low3:u3] OF GENERIC : T;
LOCAL 
   res   : ARRAY[low1:u1] OF ARRAY [low2:u2] OF
             ARRAY[low3:u3] OF GENERIC : T;
 END_LOCAL;                

(* Check input dimensions for consistency *)
   IF (u1-low1+1) <> SIZEOF(lis) THEN
     RETURN (?);
   END_IF;
   IF (u2-low2+1) <> SIZEOF(lis[1]) THEN
     RETURN (?);
   END_IF;
(* Initialise res with values from lis[1] *)
   res := [make_array_of_array(lis[1], low2, u2, low3, u3) : (u1-low1 + 1)];
   REPEAT i := 2 TO HIINDEX(lis);
     IF (u2-low2+1) <> SIZEOF(lis[i]) THEN
       RETURN (?);
     END_IF;  
     res[low1+i-1] := make_array_of_array(lis[i], low2, u2, low3, u3);
   END_REPEAT; 
   RETURN (res);
END_FUNCTION;

FUNCTION normalise
 (arg : vector_or_direction) : vector_or_direction;
LOCAL
      ndim   : INTEGER;
      v      : direction := dummy_gri || direction ([1.0,0.0,0.0]);
      result : vector_or_direction;
      vec    : vector := dummy_gri || vector (v, 1.0);
      mag    : REAL;
    END_LOCAL;
    
    IF NOT EXISTS (arg) THEN
      result := ?;
  (* When function is called with invalid data a NULL result is returned *)
    ELSE
      ndim := arg.dim;
      IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg) THEN
        BEGIN
              v := dummy_gri || direction(arg\vector.orientation.direction_ratios);
          IF arg\vector.magnitude = 0.0 THEN
            RETURN(?);
          ELSE
           vec := dummy_gri || vector (v, 1.0);
          END_IF;
        END;
      ELSE
        v := dummy_gri || direction (arg.direction_ratios);
      END_IF;
      mag := 0.0;
      REPEAT  i := 1 TO ndim;
        mag := mag + v.direction_ratios[i]*v.direction_ratios[i];
      END_REPEAT;
      IF mag > 0.0 THEN
        mag := SQRT(mag);
        REPEAT  i := 1 TO ndim;
          v.direction_ratios[i] := v.direction_ratios[i]/mag;
        END_REPEAT;
        IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg) THEN
          vec.orientation := v;
          result := vec;
        ELSE
          result := v;
        END_IF;
      ELSE
        RETURN(?);
      END_IF;
    END_IF;
    RETURN (result);
END_FUNCTION;

FUNCTION orthogonal_complement
 (vec : direction) : direction;
LOCAL
     result :  direction ;
   END_LOCAL;

   IF (vec.dim <> 2) OR NOT EXISTS (vec) THEN
     RETURN(?);
   ELSE
     result := dummy_gri || direction([-vec.direction_ratios[2],
                                          vec.direction_ratios[1]]);
     RETURN(result);
   END_IF;
END_FUNCTION;

FUNCTION same_side
 (plane_pts : LIST[3:3] OF cartesian_point; test_points : LIST[2:?] OF cartesian_point) : BOOLEAN;
LOCAL
     val1, val2 : REAL;
     n          : INTEGER;
   END_LOCAL;

   IF (plane_pts[1].dim = 2) OR (test_points[1].dim = 2) THEN
     RETURN(?);
   END_IF;
   n := SIZEOF(test_points);
   val1 := above_plane(plane_pts[1], plane_pts[2], plane_pts[3],
                       test_points[1] );
   REPEAT i := 2 TO n;
     val2 := above_plane(plane_pts[1], plane_pts[2], plane_pts[3],
                       test_points[i] );
     IF (val1*val2 <= 0.0) THEN
       RETURN(FALSE);
     END_IF;
   END_REPEAT;
   RETURN(TRUE);
END_FUNCTION;

FUNCTION scalar_times_vector
 (scalar : REAL; vec : vector_or_direction) : vector;
LOCAL
      v      : direction;
      mag    : REAL;
      result : vector;
    END_LOCAL;
 
    IF NOT EXISTS (scalar) OR NOT EXISTS (vec) THEN
      RETURN (?) ;
     ELSE
      IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF (vec) THEN
        v   := dummy_gri || direction(vec\vector.orientation.direction_ratios);
        mag := scalar * vec\vector.magnitude;
      ELSE
        v   := dummy_gri || direction(vec.direction_ratios);
        mag := scalar;
      END_IF;
      IF (mag < 0.0 ) THEN
        REPEAT i := 1 TO SIZEOF(v.direction_ratios);
          v.direction_ratios[i] := -v.direction_ratios[i];
        END_REPEAT;
        mag := -mag;
      END_IF;
      result := dummy_gri || vector(normalise(v), mag);
    END_IF;
    RETURN (result);
END_FUNCTION;

FUNCTION second_proj_axis
 (z_axis : direction; x_axis : direction; arg : direction) : direction;
LOCAL
     y_axis : vector;
     v      : direction;
     temp   : vector;
   END_LOCAL;
   
   IF NOT EXISTS(arg) THEN
     v := dummy_gri || direction([0.0,1.0,0.0]);
   ELSE
     v := arg;
   END_IF;
   
   temp   := scalar_times_vector(dot_product(v, z_axis), z_axis);
   y_axis := vector_difference(v, temp);
   temp   := scalar_times_vector(dot_product(v, x_axis), x_axis);
   y_axis := vector_difference(y_axis, temp);
   y_axis := normalise(y_axis);
   RETURN(y_axis.orientation);
END_FUNCTION;

FUNCTION surface_weights_positive
 (b : rational_b_spline_surface) : BOOLEAN;
LOCAL
     result        : BOOLEAN := TRUE;
   END_LOCAL;
   
   REPEAT i := 0 TO b.u_upper;
     REPEAT j := 0 TO b.v_upper;
       IF (b.weights[i][j] <= 0.0)  THEN
         result := FALSE;
         RETURN(result);
       END_IF;
     END_REPEAT;
   END_REPEAT;
   RETURN(result);
END_FUNCTION;

FUNCTION vector_difference
 (arg1 : vector_or_direction; arg2 : vector_or_direction) : vector;
LOCAL
      result          : vector;
      res, vec1, vec2 : direction;
      mag, mag1, mag2 : REAL;
      ndim            : INTEGER;
    END_LOCAL;
 
    IF ((NOT EXISTS (arg1)) OR (NOT EXISTS (arg2))) OR (arg1.dim <> arg2.dim)
        THEN
      RETURN (?) ;
     ELSE
      BEGIN
        IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg1) THEN
          mag1 := arg1\vector.magnitude;
          vec1 := arg1\vector.orientation;
        ELSE
          mag1 := 1.0;
          vec1 := arg1;
        END_IF;
        IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg2) THEN
          mag2 := arg2\vector.magnitude;
          vec2 := arg2\vector.orientation;
        ELSE
          mag2 := 1.0;
          vec2 := arg2;
        END_IF;
        vec1 := normalise (vec1);
        vec2 := normalise (vec2);
        ndim := SIZEOF(vec1.direction_ratios);
        mag := 0.0;
        res := dummy_gri || direction(vec1.direction_ratios);
        REPEAT i := 1 TO ndim;
          res.direction_ratios[i] := mag1*vec1.direction_ratios[i] -
                                      mag2*vec2.direction_ratios[i];
          mag := mag + (res.direction_ratios[i]*res.direction_ratios[i]);
        END_REPEAT;
        IF (mag > 0.0 ) THEN
        result := dummy_gri || vector( res, SQRT(mag));
        ELSE
          result := dummy_gri || vector( vec1,  0.0);
        END_IF;
      END;
    END_IF;
    RETURN (result);
END_FUNCTION;

FUNCTION vector_sum
 (arg1 : vector_or_direction; arg2 : vector_or_direction) : vector;
LOCAL
     result          : vector;
     res, vec1, vec2 : direction;
     mag, mag1, mag2 : REAL;
     ndim            : INTEGER;
   END_LOCAL;

   IF ((NOT EXISTS (arg1)) OR (NOT EXISTS (arg2))) OR (arg1.dim <> arg2.dim)
       THEN
     RETURN (?) ;

   ELSE
     BEGIN
       IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg1) THEN
         mag1 := arg1\vector.magnitude;
         vec1 := arg1\vector.orientation;
       ELSE
         mag1 := 1.0;
         vec1 := arg1;
       END_IF;
       IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg2) THEN
         mag2 := arg2\vector.magnitude;
         vec2 := arg2\vector.orientation;
       ELSE
         mag2 := 1.0;
         vec2 := arg2;
       END_IF;
       vec1 := normalise (vec1);
       vec2 := normalise (vec2);
       ndim := SIZEOF(vec1.direction_ratios);
       mag := 0.0;
       res := dummy_gri || direction(vec1.direction_ratios);
       REPEAT i := 1 TO ndim;
         res.direction_ratios[i] := mag1*vec1.direction_ratios[i] +
                                      mag2*vec2.direction_ratios[i];
         mag := mag + (res.direction_ratios[i]*res.direction_ratios[i]);
       END_REPEAT;
       IF (mag > 0.0 ) THEN
       result := dummy_gri || vector( res, SQRT(mag));
       ELSE
         result := dummy_gri || vector( vec1,  0.0);
       END_IF;
     END;
   END_IF;
   RETURN (result);
END_FUNCTION;

FUNCTION volume_weights_positive
 (b : rational_b_spline_volume) : BOOLEAN;
LOCAL
       result   : BOOLEAN := TRUE;
     END_LOCAL;

     REPEAT i := 0 TO b.u_upper;
       REPEAT j := 0 TO b.v_upper;
         REPEAT k := 0 TO b.w_upper;
           IF (b.weights[i][j][k] <= 0.0)  THEN
             result := FALSE;
             RETURN(result);
           END_IF;
         END_REPEAT;
       END_REPEAT;
     END_REPEAT;
     RETURN(result);
END_FUNCTION;

FUNCTION weights_positive
 (weights : LIST[0:?] OF REAL) : BOOLEAN;
LOCAL
result : BOOLEAN := TRUE;
END_LOCAL;
REPEAT i := 1 TO SIZEOF(weights);
IF weights[i] <= 0.0 THEN
result := FALSE;
RETURN(result);
END_IF;
END_REPEAT;
RETURN(result);
END_FUNCTION;

END_SCHEMA;  -- geometry_schema


© ISO 2021 — All rights reserved