SCHEMA machining_schema;

(* Version 5 date: 2002-02-06 
 * Author: ISO TC184/SC1/WG7 
 *) 
 
(* ************************************************************ *) 
(* CONSTANT from geometry_schema                   ISO 10303-42 *) 
(* ************************************************************ *) 
 
CONSTANT 
dummy_gri : geometric_representation_item :=  representation_item('')|| 
            geometric_representation_item(); 
END_CONSTANT; 
 
 
(* ************************************************************ *) 
(* Types from approval_schema                      ISO 10303-41 *) 
(* ************************************************************ *) 
 
ENTITY approval;  (* m0 *) 
status :                    approval_status; 
level  :                    label; 
END_ENTITY; 
 
ENTITY approval_status;  (* m0 *) 
name :                      label; 
END_ENTITY; 
 
(* ************************************************************ *) 
(* Types from date_time_schema                     ISO 10303-41 *) 
(* ************************************************************ *) 
 
ENTITY date_and_time;  (* m0 *) 
date_component :            date; 
time_component :            local_time; 
END_ENTITY; 
 
ENTITY date   (* m0 *) 
SUPERTYPE OF (ONEOF (calendar_date, ordinal_date, 
week_of_year_and_day_date)); 
year_component :            year_number; 
END_ENTITY; 
 
ENTITY calendar_date  (* m0 *) 

SUBTYPE OF (date); 
day_component   :           day_in_month_number; 
month_component :           month_in_year_number; 
WHERE 
  WR1: valid_calendar_date (SELF); 
END_ENTITY; 
 
TYPE day_in_month_number = INTEGER; 
WHERE 
  WR1: {1 <= SELF <= 31}; 
END_TYPE;  
 
TYPE month_in_year_number = INTEGER; 
WHERE 
  WR1: { 1 <= SELF <= 12 }; 
END_TYPE;  
 
ENTITY ordinal_date  (* m0 *) 
SUBTYPE OF (date); 
day_component : day_in_year_number; 
WHERE 
  WR1: (NOT leap_year(SELF.year_component) AND { 1 <= day_component <= 365 
}) 
       OR 
       (leap_year(SELF.year_component) AND { 1 <= day_component <= 366 }); 
END_ENTITY;  
 
TYPE day_in_year_number = INTEGER; 
WHERE 
  WR1: {1 <= SELF <= 366}; 
END_TYPE;  
 
ENTITY week_of_year_and_day_date  (* m0 *) 
SUBTYPE OF (date); 
week_component :            week_in_year_number; 
day_component  :            OPTIONAL day_in_week_number; 
END_ENTITY;  
 
TYPE week_in_year_number = INTEGER; 
WHERE 
  WR1: { 1 <= SELF <= 53 }; 
END_TYPE;  
 
TYPE day_in_week_number = INTEGER; 
WHERE 
  WR1: { 1 <= SELF <= 7 }; 
END_TYPE; -- day_in_week_number 
 
ENTITY local_time;  (* m0 *) 
hour_component   :          hour_in_day; 
minute_component :          OPTIONAL minute_in_hour; 
second_component :          OPTIONAL second_in_minute; 
zone             :          coordinated_universal_time_offset; 
WHERE 
  WR1: valid_time (SELF); 
END_ENTITY; 
 
TYPE hour_in_day = INTEGER; 
WHERE 
  WR1: { 0 <= SELF < 24 }; 
END_TYPE;

TYPE minute_in_hour = INTEGER; 
WHERE 
  WR1: { 0 <= SELF <= 59 }; 
END_TYPE; 
 
TYPE second_in_minute = REAL; 
WHERE 
  WR1: { 0 <= SELF <= 60 }; 
END_TYPE; 
 
ENTITY coordinated_universal_time_offset;  (* m0 *) 
hour_offset   :             INTEGER; 
minute_offset :             OPTIONAL INTEGER; 
sense         :             ahead_or_behind; 
WHERE 
  WR1: { 0 <= hour_offset <= 12 }; 
  WR2: { 0 <= minute_offset <= 59 }; 
  WR3: NOT ((hour_offset <> 0) AND (sense = exact)); 
END_ENTITY; 
 
TYPE ahead_or_behind = ENUMERATION OF(ahead, exact, behind); 
END_TYPE; 
 
TYPE year_number = INTEGER; 
END_TYPE; 
 
FUNCTION valid_calendar_date (date : calendar_date) : LOGICAL; 
  CASE date.month_component OF 
    1  : RETURN({ 1 <= date.day_component <= 31 }); 
    2  : BEGIN 
           IF (leap_year(date.year_component)) THEN 
             RETURN({ 1 <= date.day_component <= 29 }); 
           ELSE 
             RETURN({ 1 <= date.day_component <= 28 }); 
           END_IF; 
         END; 
    3  : RETURN({ 1 <= date.day_component <= 31 }); 
    4  : RETURN({ 1 <= date.day_component <= 30 }); 
    5  : RETURN({ 1 <= date.day_component <= 31 }); 
    6  : RETURN({ 1 <= date.day_component <= 30 }); 
    7  : RETURN({ 1 <= date.day_component <= 31 }); 
    8  : RETURN({ 1 <= date.day_component <= 31 }); 
    9  : RETURN({ 1 <= date.day_component <= 30 }); 
    10 : RETURN({ 1 <= date.day_component <= 31 }); 
    11 : RETURN({ 1 <= date.day_component <= 30 }); 
    12 : RETURN({ 1 <= date.day_component <= 31 }); 
  END_CASE; 
       RETURN (FALSE); 
END_FUNCTION; 
 
FUNCTION leap_year (year : year_number) : BOOLEAN; 
  IF ((((year MOD 4) = 0) AND ((year MOD 100) <> 0)) OR 
       ((year MOD 400) = 0)) THEN 
    RETURN(TRUE); 
  ELSE 
    RETURN(FALSE); 
  END_IF; 
END_FUNCTION; 
 
FUNCTION valid_time (time: local_time) : BOOLEAN;
IF EXISTS (time.second_component) THEN 
    RETURN (EXISTS (time.minute_component)); 
  ELSE 
    RETURN (TRUE); 
  END_IF; 
END_FUNCTION; 
 
(* ************************************************************ *) 
(* Types from person_organization_schema           ISO 10303-41 *) 
(* ************************************************************ *) 
 
ENTITY person;   (* m0 *) 
id            :             identifier; 
last_name     :             OPTIONAL label; 
first_name    :             OPTIONAL label; 
middle_names  :             OPTIONAL LIST [1:?] OF label; 
prefix_titles :             OPTIONAL LIST [1:?] OF label; 
suffix_titles :             OPTIONAL LIST [1:?] OF label; 
WHERE 
  WR1: EXISTS(last_name) OR EXISTS(first_name); 
END_ENTITY; 
 
ENTITY address;  (* m0 *) 
internal_location       :   OPTIONAL label; 
street_number           :   OPTIONAL label; 
street                  :   OPTIONAL label; 
postal_box              :   OPTIONAL label; 
town                    :   OPTIONAL label; 
region                  :   OPTIONAL label; 
postal_code             :   OPTIONAL label; 
country                 :   OPTIONAL label; 
facsimile_number        :   OPTIONAL label; 
telephone_number        :   OPTIONAL label; 
electronic_mail_address :   OPTIONAL label; 
telex_number            :   OPTIONAL label; 
WHERE 
  WR1: EXISTS(internal_location)       OR 
       EXISTS(street_number)           OR 
       EXISTS(street)                  OR 
       EXISTS(postal_box)              OR 
       EXISTS(town)                    OR 
       EXISTS(region)                  OR 
       EXISTS(postal_code)             OR 
       EXISTS(country)                 OR 
       EXISTS(facsimile_number)        OR 
       EXISTS(telephone_number)        OR 
       EXISTS(electronic_mail_address) OR 
       EXISTS(telex_number); 
END_ENTITY; 
 
(* ************************************************************ *) 
(* Types from support_resource_schema              ISO 10303-41 *) 
(* ************************************************************ *) 
 
TYPE identifier = STRING; 
END_TYPE; 
 
TYPE label = STRING; 
END_TYPE; 
 
TYPE text = STRING;
END_TYPE; 
 
FUNCTION bag_to_set  
(the_bag : BAG OF GENERIC : intype) : SET OF GENERIC : intype; 
LOCAL 
    the_set: SET OF GENERIC : intype := []; 
END_LOCAL; 
IF SIZEOF (the_bag) > 0 THEN 
   REPEAT i := 1 to HIINDEX (the_bag); 
     the_set := the_set + the_bag [i]; 
   END_REPEAT; 
END_IF; 
RETURN (the_set); 
END_FUNCTION; 
 
 
(* ************************************************************ *) 
(* Types from measure_schema                       ISO 10303-41 *) 
(* ************************************************************ *) 
 
TYPE length_measure = REAL; 
END_TYPE; 
 
TYPE parameter_value = REAL; 
END_TYPE; 
 
TYPE plane_angle_measure = REAL; 
END_TYPE; 
 
TYPE positive_length_measure = length_measure; 
WHERE 
WR1: SELF > 0; 
END_TYPE; 
 
TYPE positive_ratio_measure = ratio_measure; 
WHERE 
WR1: SELF > 0; 
END_TYPE; 
 
TYPE ratio_measure = REAL; 
END_TYPE; 
 
TYPE time_measure = REAL; 
END_TYPE; 
 
 
(* ************************************************************** *) 
(* Types from product_property_representation_schema ISO 10303-41 *) 
(* ************************************************************** *) 
 
ENTITY shape_representation (* t1 *) 
SUBTYPE OF (representation); 
END_ENTITY; 
 
 
(* ************************************************************ *) 
(* Types from geometry_schema                      ISO 10303-42 *) 
(* ************************************************************ *) 
 
TYPE trimming_select = SELECT  
    (cartesian_point,
    parameter_value); 
END_TYPE; 
 
TYPE trimming_preference = ENUMERATION OF  
   (cartesian, parameter, unspecified); 
END_TYPE; 
 
TYPE transition_code = ENUMERATION OF  
        (discontinuous, 
        continuous, 
        cont_same_gradient, 
        cont_same_gradient_same_curvature); 
END_TYPE; 
 
ENTITY trimmed_curve    (* c0 *) 
        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: ('MACHINING_SCHEMA.PARAMETER_VALUE' IN TYPEOF(trim_1[1])) OR  
             ('MACHINING_SCHEMA.PARAMETER_VALUE' IN TYPEOF(trim_1[2])); 
        WR2: ('MACHINING_SCHEMA.PARAMETER_VALUE' IN TYPEOF(trim_2[1])) OR  
             ('MACHINING_SCHEMA.PARAMETER_VALUE' IN TYPEOF(trim_2[2])); 
        WR3: ('MACHINING_SCHEMA.PARAMETER' IN TYPEOF(SELF.master_representation));
END_ENTITY; 
 
ENTITY composite_curve  (* c0 *) 
        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;         (* c0 *) 
        transition    : transition_code;  
        same_sense    : BOOLEAN;  
        parent_curve  : curve;  
 INVERSE  
         using_curves  : BAG [1:?] OF composite_curve FOR segments;  
 WHERE  
        WR1 : ('MACHINING_SCHEMA.BOUNDED_CURVE' IN 
          TYPEOF(parent_curve));  
END_ENTITY; 
 
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 dimension_count = INTEGER; 
WHERE 
WR1: SELF > 0; 
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 vector_or_direction = SELECT (vector, direction); 
END_TYPE; 
 
ENTITY axis1_placement (* s1 *) 
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_3d (* m0 *) 
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 bezier_curve (* c1 *) 
SUBTYPE OF (b_spline_curve); 
END_ENTITY; 
 
ENTITY bezier_surface (* s1 *) 
SUBTYPE OF (b_spline_surface); 
END_ENTITY; 
 
ENTITY bounded_curve (* c0 *) 
SUPERTYPE OF (ONEOF(polyline, b_spline_curve, trimmed_curve, 
                    bounded_pcurve, composite_curve)) 
SUBTYPE OF (curve); 
END_ENTITY; 
 
ENTITY bounded_pcurve (* s0 *) 
SUBTYPE OF (pcurve, bounded_curve);

WHERE 
WR1: ('MACHINING_SCHEMA.BOUNDED_CURVE' IN 
      TYPEOF(SELF\pcurve.reference_to_curve.items[1])); 
END_ENTITY; 
 
ENTITY bounded_surface (* s0 *) 
SUPERTYPE OF (b_spline_surface) 
SUBTYPE OF (surface); 
END_ENTITY; 
 
ENTITY b_spline_curve (* c0 *) 
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: ('MACHINING_SCHEMA.UNIFORM_CURVE' IN TYPEOF(self)) OR 
     ('MACHINING_SCHEMA.QUASI_UNIFORM_CURVE' IN TYPEOF(self)) OR 
     ('MACHINING_SCHEMA.BEZIER_CURVE' IN TYPEOF(self)) OR 
     ('MACHINING_SCHEMA.B_SPLINE_CURVE_WITH_KNOTS' IN TYPEOF(self)); 
END_ENTITY; 
 
ENTITY b_spline_curve_with_knots (* c0 *) 
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 (* s0 *) 
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: ('MACHINING_SCHEMA.UNIFORM_SURFACE' IN TYPEOF(SELF)) OR 
     ('MACHINING_SCHEMA.QUASI_UNIFORM_SURFACE' IN TYPEOF(SELF)) OR 
     ('MACHINING_SCHEMA.BEZIER_SURFACE' IN TYPEOF(SELF)) OR 
     ('MACHINING_SCHEMA.B_SPLINE_SURFACE_WITH_KNOTS' IN TYPEOF(SELF)); 
END_ENTITY; 
 
ENTITY b_spline_surface_with_knots (* s0 *) 
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 cartesian_point (* m0 c0 s0 *) 
SUBTYPE OF (point); 
coordinates  : LIST [1:3] OF length_measure; 
END_ENTITY; 
 
ENTITY circle  (* c1 *) 
SUBTYPE OF (conic); 
radius   : positive_length_measure; 
END_ENTITY; 
 
ENTITY conic  (* c1 *) 
SUPERTYPE OF (ONEOF(circle, ellipse, hyperbola, parabola)) 
SUBTYPE OF (curve); 
position: axis2_placement_3d; 
END_ENTITY; 
 
ENTITY curve  (* c0 *) 
SUPERTYPE OF (ONEOF(line, conic, pcurve, bounded_curve)) 
SUBTYPE OF (geometric_representation_item); 
END_ENTITY; 
 
ENTITY direction  (* m0 *) 
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 elementary_surface (* m0 s0 *) 
SUPERTYPE OF (ONEOF(plane, spherical_surface)) 
SUBTYPE OF (surface); 
position : axis2_placement_3d; 
END_ENTITY; 
 
ENTITY ellipse  (* c1 *) 
SUBTYPE OF (conic); 
semi_axis_1 : positive_length_measure; 
semi_axis_2 : positive_length_measure; 
END_ENTITY; 
 
ENTITY geometric_representation_context (* m0 *) 
SUBTYPE OF (representation_context); 
coordinate_space_dimension : dimension_count; 
END_ENTITY; 
 
ENTITY geometric_representation_item (* m0 *) 
SUPERTYPE OF (ONEOF(point, direction, placement, curve, surface, edge_curve, 
face_surface, vertex_point, solid_model, poly_loop)) 
SUBTYPE OF (representation_item); 
DERIVE 
    dim : dimension_count := dimension_of(SELF); 
WHERE 
WR1: SIZEOF (QUERY (using_rep <* using_representations (SELF) | 
     NOT ('MACHINING_SCHEMA.GEOMETRIC_REPRESENTATION_CONTEXT' IN 
     TYPEOF (using_rep.context_of_items)))) = 0; 
END_ENTITY; 
 
ENTITY hyperbola  (* c1 *) 
SUBTYPE OF (conic); 
semi_axis      : positive_length_measure; 
semi_imag_axis : positive_length_measure; 
END_ENTITY; 
 
ENTITY line  (* c1 *) 
SUBTYPE OF (curve); 
pnt : cartesian_point; 
dir : vector; 
WHERE 
WR1: dir.dim  = pnt.dim; 
END_ENTITY; 
 
ENTITY oriented_surface (* c1 *) 
SUBTYPE OF (surface); 
orientation : BOOLEAN; 
END_ENTITY; 
 
ENTITY parabola  (* c1 *) 
SUBTYPE OF (conic); 
focal_dist : length_measure; 
WHERE 
WR1: focal_dist <> 0.0; 
END_ENTITY; 
 
ENTITY pcurve  (* s0 *) 
SUBTYPE OF (curve); 
basis_surface      : surface; 
reference_to_curve : definitional_representation; 
WHERE 
WR1: SIZEOF(reference_to_curve\representation.items) = 1; 
WR2: 'MACHINING_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  (* m0 *) 
SUPERTYPE OF (axis2_placement_3d) 
SUBTYPE OF (geometric_representation_item); 
location : cartesian_point; 
END_ENTITY; 
 
ENTITY plane  (* m0 s0 *) 
SUBTYPE OF (elementary_surface); 
END_ENTITY; 
 
ENTITY point (* m0 c0 s0 *) 
SUPERTYPE OF (cartesian_point) 
SUBTYPE OF (geometric_representation_item); 
END_ENTITY; 
 
ENTITY polyline  (* c0 *) 
SUBTYPE OF (bounded_curve); 
points : LIST [2:?] OF cartesian_point; 
END_ENTITY; 
 
ENTITY quasi_uniform_curve (* c1 *) 
SUBTYPE OF (b_spline_curve); 
END_ENTITY; 
 
ENTITY quasi_uniform_surface (* s1 *) 
SUBTYPE OF (b_spline_surface); 
END_ENTITY; 
 
ENTITY rational_b_spline_curve (* c0 *) 
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 rational_b_spline_surface (* s0 *) 
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 spherical_surface (* s1 *) 
SUBTYPE OF (elementary_surface); 
radius   : positive_length_measure; 
END_ENTITY; 
 
ENTITY surface (* m0 s0 *) 
SUPERTYPE OF (ONEOF(swept_surface, elementary_surface, bounded_surface, 
oriented_surface))  
SUBTYPE OF (geometric_representation_item); 
END_ENTITY; 
 
ENTITY surface_of_linear_extrusion (* s1 *) 
SUBTYPE OF (swept_surface); 
extrusion_axis      : vector; 
END_ENTITY; 
 
ENTITY surface_of_revolution (* s1 *) 
SUBTYPE OF (swept_surface); 
axis_position       : axis1_placement; 
DERIVE 
axis_line : line := dummy_gri || curve() || line (axis_position.location, 
                    dummy_gri || vector(axis_position.z, 1.0)); 
END_ENTITY; 
 
ENTITY swept_surface (* s1 *) 
SUPERTYPE OF (ONEOF(surface_of_linear_extrusion, surface_of_revolution)) 
SUBTYPE OF (surface); 
swept_curve : curve; 
END_ENTITY; 
 
ENTITY uniform_curve (* c1 *) 
SUBTYPE OF (b_spline_curve); 
END_ENTITY; 
 
ENTITY uniform_surface (* s1 *) 
SUBTYPE OF (b_spline_surface); 
END_ENTITY; 
 
ENTITY vector  (* c1 s1 *) 
SUBTYPE OF (geometric_representation_item); 
orientation : direction; 
magnitude   : length_measure; 
WHERE 
WR1 : magnitude >= 0.0; 
END_ENTITY; 
 
RULE compatible_dimension FOR (cartesian_point, direction, 
representation_context,  geometric_representation_context); 
WHERE 
  -- ensure that the count of coordinates of each cartesian_point 
  -- matches the coordinate_space_dimension of each geometric_context in 
  -- which it is geometrically founded 
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; 
  -- ensure that the count of direction_ratios of each direction 
  -- matches the coordinate_space_dimension of each geometric_context in 
  -- which it is geometrically founded 
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 build_axes(axis, 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_param_b_spline(degree, up_knots, 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 cross_product (arg1, 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 dimension_of(item : geometric_representation_item): dimension_count; 
LOCAL 
x : SET OF representation; 
y : representation_context; 
END_LOCAL; 
-- 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; 
RETURN (y\geometric_representation_context.coordinate_space_dimension); 
END_FUNCTION; 
 
FUNCTION dot_product(arg1, 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, 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]) 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 list_to_array(lis : LIST [0:?] OF GENERIC : T; low,u : INTEGER) : 
ARRAY 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, u1, low2, u2 : INTEGER): ARRAY OF ARRAY 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 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 'MACHINING_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 'MACHINING_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 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 'MACHINING_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 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, 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 'MACHINING_SCHEMA.VECTOR' IN TYPEOF(arg1) THEN 
      mag1 := arg1.magnitude; 
      vec1 := arg1.orientation; 
    ELSE 
      mag1 := 1.0; 
      vec1 := arg1; 
    END_IF; 
    IF 'MACHINING_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; 
 
 (* ************************************************************ *) 
(* Types from topology_schema                      ISO 10303-42 *) 
(* ************************************************************ *) 
 
TYPE list_of_reversible_topology_item = LIST [0:?] of 
reversible_topology_item; 
END_TYPE; 
 
TYPE set_of_reversible_topology_item = SET [0:?] of reversible_topology_item; 
END_TYPE; 
 
TYPE reversible_topology = SELECT (reversible_topology_item, 
   list_of_reversible_topology_item, set_of_reversible_topology_item); 
END_TYPE; 
 
TYPE reversible_topology_item = SELECT (edge, path, face,  
    face_bound, closed_shell, open_shell); 
END_TYPE; 
 
TYPE shell = SELECT (open_shell, closed_shell); 
END_TYPE; 
 
ENTITY closed_shell (* t0 *) 
SUBTYPE OF (connected_face_set, oriented_closed_shell); 
END_ENTITY; 
 
ENTITY connected_face_set (* t0 *) 
SUPERTYPE OF (ONEOF(open_shell, closed_shell)) 
SUBTYPE OF (topological_representation_item); 
cfs_faces : SET [1:?] OF face; 
END_ENTITY; 
 
ENTITY edge  (* t0 *) 
SUPERTYPE OF(ONEOF(edge_curve, oriented_edge)) 
SUBTYPE OF (topological_representation_item); 
edge_start : vertex; 
edge_end   : vertex; 
END_ENTITY; 
 
ENTITY edge_curve (* t0 *) 
SUBTYPE OF(edge, geometric_representation_item); 
edge_geometry : curve; 
same_sense    : BOOLEAN; 
END_ENTITY; 
 
ENTITY edge_loop  (* t0 *) 
SUBTYPE OF (loop, path); 
DERIVE 
ne : INTEGER := SIZEOF(SELF\path.edge_list); 
WHERE 
WR1: (SELF\path.edge_list[1].edge_start) :=: 
     (SELF\path.edge_list[ne].edge_end); 
END_ENTITY; 
 
ENTITY face  (* t0 *) 
SUPERTYPE OF(ONEOF (face_surface, oriented_face) )
SUBTYPE OF (topological_representation_item); 
bounds : SET[1:?] OF face_bound;
WR1: NOT (mixed_loop_type_set(list_to_set(list_face_loops(SELF)))); 
WR2: SIZEOF(QUERY(temp <* bounds | 'MACHINING_SCHEMA.FACE_OUTER_BOUND' IN 
                                           TYPEOF(temp))) <= 1; 
END_ENTITY; 
 

END_SCHEMA;

