Schema: geometry_schema

Source : ISO 10303-42



SCHEMA geometry_schema;

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

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 topology_schema   -- ISO 10303-42
  (edge_curve,
   face_surface,
   poly_loop,
   vertex_point);

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,
   half_space_2d,
   primitive_2d,
   rectangular_pyramid,
   right_angular_wedge,
   right_circular_cone,
   right_circular_cylinder,
   shell_based_surface_model,
   shell_based_wireframe_model,
   solid_model,
   sphere,
   torus);


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
   (pcurve,
    surface_curve,
    composite_curve_on_surface);
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 pcurve_or_surface = SELECT
   (pcurve,
    surface);
END_TYPE;

TYPE preferred_surface_curve_representation = ENUMERATION OF
   (curve_3d,
    pcurve_s1,
    pcurve_s2);
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
   (vector,
    direction);
END_TYPE;

ENTITY geometric_representation_context
  SUBTYPE OF (representation_context);
  coordinate_space_dimension : dimension_count;
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: 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: 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: 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 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 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;
  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 := 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(b_spline_surface.u_degree, knot_u_upper, SELF\b_spline_surface.u_upper, u_multiplicities, u_knots);
  WR2: constraints_param_b_spline(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 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;
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 := 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(b_spline_volume.u_degree, knot_u_upper, SELF\b_spline_volume.u_upper, u_multiplicities, u_knots);
  WR2: constraints_param_b_spline(b_spline_volume.v_degree, knot_v_upper, SELF\b_spline_volume.v_upper, v_multiplicities, v_knots);
  WR3: constraints_param_b_spline(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_curve
  SUBTYPE OF (b_spline_curve);
END_ENTITY;

ENTITY bezier_surface
  SUBTYPE OF (b_spline_surface);
END_ENTITY;

ENTITY bezier_volume
  SUBTYPE OF (b_spline_volume);
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 boundary_curve
  SUBTYPE OF (composite_curve_on_surface);
WHERE
  WR1: composite_curve.closed_curve;
END_ENTITY;

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

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

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

ENTITY bounded_surface_curve
  SUBTYPE OF (surface_curve, bounded_curve);
WHERE
  WR1: ('GEOMETRY_SCHEMA.BOUNDED_CURVE' IN TYPEOF(surface_curve.curve_3d));
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 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_2d
  SUBTYPE OF (cartesian_transformation_operator);
DERIVE
  u : LIST[2:2] OF direction := base_axis(2,cartesian_transformation_operator.axis1, SELF\cartesian_transformation_operator.axis2,?);
WHERE
  WR1: geometric_representation_item.dim = 2;
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,cartesian_transformation_operator.axis1, SELF\cartesian_transformation_operator.axis2,axis3);
WHERE
  WR1: geometric_representation_item.dim = 3;
END_ENTITY;

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

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

ENTITY clothoid
  SUBTYPE OF (curve);
  position : axis2_placement;
  clothoid_constant : length_measure;
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_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 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 conic
  SUPERTYPE OF (ONEOF (circle,
                       ellipse,
                       hyperbola,
                       parabola))
  SUBTYPE OF (curve);
  position : axis2_placement;
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 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 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] <> SELF.basis_surface))) = 0;
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 cylindrical_point
  SUBTYPE OF (cartesian_point);
  r : length_measure;
  theta : plane_angle_measure;
  z : length_measure;
DERIVE
  cartesian_point.coordinates : LIST[1:3] OF length_measure := [r*cos(theta), r*sin(theta), z];
WHERE
  WR1: r >= 0.0;
END_ENTITY;

ENTITY cylindrical_surface
  SUBTYPE OF (elementary_surface);
  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 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 degenerate_toroidal_surface
  SUBTYPE OF (toroidal_surface);
  select_outer : BOOLEAN;
WHERE
  WR1: major_radius < minor_radius;
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 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 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 elementary_surface
  SUPERTYPE OF (ONEOF (plane,
                       cylindrical_surface,
                       conical_surface,
                       spherical_surface,
                       toroidal_surface))
  SUBTYPE OF (surface);
  position : axis2_placement_3d;
END_ENTITY;

ENTITY ellipse
  SUBTYPE OF (conic);
  semi_axis_1 : positive_length_measure;
  semi_axis_2 : positive_length_measure;
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 evaluated_degenerate_pcurve
  SUBTYPE OF (degenerate_pcurve);
  equivalent_point : cartesian_point;
END_ENTITY;

ENTITY fixed_reference_swept_surface
  SUBTYPE OF (swept_surface);
  directrix : curve;
  fixed_reference : direction;
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,
                       half_space_2d,
                       shell_based_surface_model,
                       face_based_surface_model,
                       shell_based_wireframe_model,
                       edge_based_wireframe_model,
                       geometric_set))
  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 line
  SUBTYPE OF (curve);
  pnt : cartesian_point;
  dir : vector;
WHERE
  WR1: dir.dim = pnt.dim;
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 hyperbola
  SUBTYPE OF (conic);
  semi_axis : positive_length_measure;
  semi_imag_axis : positive_length_measure;
END_ENTITY;

ENTITY intersection_curve
  SUBTYPE OF (surface_curve);
WHERE
  WR1: SIZEOF(surface_curve.associated_geometry) = 2;
  WR2: associated_surface(surface_curve.associated_geometry[1]) <> associated_surface(SELF\surface_curve.associated_geometry[2]);
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 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 outer_boundary_curve
  SUBTYPE OF (boundary_curve);
END_ENTITY;

ENTITY parabola
  SUBTYPE OF (conic);
  focal_dist : length_measure;
WHERE
  WR1: focal_dist <> 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 placement
  SUPERTYPE OF (ONEOF (axis1_placement,
                       axis2_placement_2d,
                       axis2_placement_3d))
  SUBTYPE OF (geometric_representation_item);
  location : cartesian_point;
END_ENTITY;

ENTITY plane
  SUBTYPE OF (elementary_surface);
END_ENTITY;

ENTITY polar_point
  SUBTYPE OF (cartesian_point);
  r : length_measure;
  theta : plane_angle_measure;
DERIVE
  cartesian_point.coordinates : LIST[1:3] OF length_measure := [r*cos(theta), r*sin(theta)];
WHERE
  WR1: r >= 0.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 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_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_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 polyline
  SUBTYPE OF (bounded_curve);
  points : LIST[2:?] OF cartesian_point;
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 quasi_uniform_curve
  SUBTYPE OF (b_spline_curve);
END_ENTITY;

ENTITY quasi_uniform_surface
  SUBTYPE OF (b_spline_surface);
END_ENTITY;

ENTITY quasi_uniform_volume
  SUBTYPE OF (b_spline_volume);
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(b_spline_curve. control_points_list);
  WR2: curve_weights_positive(SELF);
END_ENTITY;

ENTITY rational_b_spline_surface
  SUBTYPE OF (b_spline_surface);
  weights_data : LIST[2:?] OF REAL;
DERIVE
  weights : ARRAY[0:u_upper] OF REAL := make_array_of_array(weights_data,0,u_upper,0,v_upper);
WHERE
  WR1: (SIZEOF(weights_data) = SIZEOF(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 rational_b_spline_volume
  SUBTYPE OF (b_spline_volume);
  weights_data : LIST[2:?] OF REAL;
DERIVE
  weights : ARRAY[0:u_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(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 rectangular_composite_surface
  SUBTYPE OF (bounded_surface);
  segments : LIST[1:?] OF LIST;
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 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 reparametrised_composite_curve_segment
  SUBTYPE OF (composite_curve_segment);
  param_length : parameter_value;
WHERE
  WR1: param_length > 0.0;
END_ENTITY;

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

ENTITY spherical_point
  SUBTYPE OF (cartesian_point);
  r : length_measure;
  theta : plane_angle_measure;
  phi : plane_angle_measure;
DERIVE
  cartesian_point.coordinates : LIST[1: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 spherical_surface
  SUBTYPE OF (elementary_surface);
  radius : positive_length_measure;
END_ENTITY;

ENTITY spherical_volume
  SUBTYPE OF (volume);
  position : axis2_placement_3d;
  radius : positive_length_measure;
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 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 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 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_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 surface_replica
  SUBTYPE OF (surface);
  parent_surface : surface;
  transformation : cartesian_transformation_operator_3d;
WHERE
  WR1: acyclic_surface_replica(SELF, parent_surface);
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 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 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 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 toroidal_surface
  SUBTYPE OF (elementary_surface);
  major_radius : positive_length_measure;
  minor_radius : positive_length_measure;
END_ENTITY;

ENTITY uniform_curve
  SUBTYPE OF (b_spline_curve);
END_ENTITY;

ENTITY uniform_surface
  SUBTYPE OF (b_spline_surface);
END_ENTITY;

ENTITY uniform_volume
  SUBTYPE OF (b_spline_volume);
END_ENTITY;

ENTITY vector
  SUBTYPE OF (geometric_representation_item);
  orientation : direction;
  magnitude : length_measure;
WHERE
  WR1: magnitude >= 0.0;
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))
  SUBTYPE OF (geometric_representation_item);
WHERE
  WR1: geometric_representation_item.dim = 3;
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;

RULE compatible_dimension FOR
(cartesian_point,direction,representation_context,geometric_representation_context);
WHERE
  WR1: SIZEOF(QUERY(x <* cartesian_point| SIZEOF(QUERY (y <* geometric_representation_context | item_in_context(x,y) AND (HIINDEX(x.coordinates) <> y.coordinate_space_dimension))) > 0)) =0;
  WR2: SIZEOF(QUERY(x <* direction | SIZEOF(QUERY (y <* geometric_representation_context | item_in_context(x,y) AND (HIINDEX(x.direction_ratios) <> y.coordinate_space_dimension))) > 0)) = 0;
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.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)).orientation, d1]);      
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 OF INTEGER; knots : LIST 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_rectangular_composite_surface
 (s : rectangular_composite_surface) : BOOLEAN;
(* Check the surface types *)
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 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_surface_weights
 (u_upper : INTEGER; v_upper : INTEGER) : ARRAY[0:u_upper] OF REAL;
RETURN([[1:v_upper + 1]:u_upper +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 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. Note that the *)
(* RULE compatible_dimension ensures that the context_of_items *)
(* is of type geometric_representation_context and has *)
(* the same dimension_count for all values of x. *)
(* The SET x is non-empty since this is required by WR1 of *)
(* representation_item. *)
y := x[1].context_of_items;
dim := y\geometric_representation_context.coordinate_space_dimension;
RETURN (dim);      
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 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 list_to_array
 (lis : LIST[0:?] OF GENERIC; low : INTEGER; u : INTEGER) : ARRAY[low:u] OF GENERIC;
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 GENERIC; low1 : INTEGER; u1 : INTEGER; low2 : INTEGER; u2 : INTEGER) : ARRAY[low1:u1] OF GENERIC;
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 GENERIC; low1 : INTEGER; u1 : INTEGER; low2 : INTEGER; u2 : INTEGER; low3 : INTEGER; u3 : INTEGER) : ARRAY[low1:u1] OF GENERIC;
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;
result : vector_or_direction;
vec : vector;
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.orientation.direction_ratios);
IF arg.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.orientation.direction_ratios);
mag := scalar * vec.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.magnitude;
vec1 := arg1.orientation;
ELSE
mag1 := 1.0;
vec1 := arg1;
END_IF;
IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg2) THEN
mag2 := arg2.magnitude;
vec2 := arg2.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.magnitude;
vec1 := arg1.orientation;
ELSE
mag1 := 1.0;
vec1 := arg1;
END_IF;
IF 'GEOMETRY_SCHEMA.VECTOR' IN TYPEOF(arg2) THEN
mag2 := arg2.magnitude;
vec2 := arg2.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;

END_SCHEMA;  -- geometry_schema