(* THIS IS DOCUMENT ISO TC184/SC4/WG12 N4852, CONTAINING REVISED EXPRESS FOR *)
(* ISO 10303-108, 'PARAMETERIZATION AND CONSTRAINTS FOR EXPLICIT GEOMETRIC   *)
(* PRODUCT MODELS' TO TAKE INTO ACCOUNT TC1 FOR THAT DOCUMENT -- 2007-04-20  *)                                          

SCHEMA sketch_schema;

REFERENCE FROM product_property_representation_schema -- ISO 10303-41
  (shape_representation);

REFERENCE FROM geometry_schema;                       -- ISO 10303-42

REFERENCE FROM topology_schema                        -- ISO 10303-42
  (face_surface);

REFERENCE FROM geometric_model_schema                 -- ISO 10303-42
  (solid_model,
   surface_model);

REFERENCE FROM representation_schema                  -- ISO 10303-43
  (item_in_context,
   mapped_item,
   representation,
   representation_item_relationship,
   representation_map,
   using_items,
   using_representations);

REFERENCE FROM variational_representation_schema      -- ISO 10303-108
  (auxiliary_geometric_representation_item,
   variational_representation,
   variational_representation_item);

TYPE surface_or_solid_model = SELECT
  (surface_model,
   solid_model);
END_TYPE;

TYPE planar_curve_select = SELECT
  (line,
   conic,
   trimmed_curve,
   pcurve,
   surface_curve);
WHERE
  WR1: SELF\geometric_representation_item.dim = 3;
  WR2: check_curve_planarity(SELF);
END_TYPE;

TYPE sketch_element_select = EXTENSIBLE SELECT
  (point,
   curve);
WHERE
  WR1: 'GEOMETRY_SCHEMA.GEOMETRIC_REPRESENTATION_ITEM' IN TYPEOF(SELF);
END_TYPE;

TYPE sketch_basis_select = SELECT
  (planar_curve_select,
   curve_bounded_surface,
   face_surface);
END_TYPE;

TYPE sketch_type_select = SELECT
  (neutral_sketch_representation,
   positioned_sketch,
   subsketch);
END_TYPE;

TYPE curves_or_area = ENUMERATION OF
  (curves, area);
END_TYPE;

ENTITY implicit_point_on_plane
  ABSTRACT SUPERTYPE OF (ONEOF
    (implicit_planar_intersection_point,
     implicit_planar_projection_point))
  SUBTYPE OF (point, auxiliary_geometric_representation_item);
  using_sketch   : positioned_sketch;
  computed_representation 
                 : cartesian_point;
DERIVE
  plane_of_point : 
    plane := get_plane_of_implicit_geometry(using_sketch);
WHERE
  WR1: (plane_of_point\elementary_surface.position.location = 
    computed_representation) XOR
    (dot_product(plane_of_point\elementary_surface.position.p[3],
    get_relative_direction_2points
    (plane_of_point\elementary_surface.position.location, 
    computed_representation)) = 0);
  WR2: SIZEOF(TYPEOF(computed_representation) * 
    ['SKETCH_SCHEMA.IMPLICIT_POINT_ON_PLANE',
     'GEOMETRY_SCHEMA.POINT_REPLICA']) = 0;
END_ENTITY;

ENTITY implicit_planar_intersection_point
  SUBTYPE OF (implicit_point_on_plane);
  external_curve : curve;
END_ENTITY;

ENTITY implicit_planar_projection_point
  SUBTYPE OF (implicit_point_on_plane);
  external_point       : point;
  projection_direction : direction;
END_ENTITY;

ENTITY implicit_planar_curve
  ABSTRACT SUPERTYPE OF (ONEOF
    (implicit_intersection_curve,
     implicit_projected_curve,
     implicit_model_intersection_curve,
     implicit_silhouette_curve))
  SUBTYPE OF (curve, auxiliary_geometric_representation_item);
  using_sketch                  : positioned_sketch;
  computed_representation       : curve;
DERIVE
  curve_plane : plane 
    := get_plane_of_implicit_geometry(using_sketch);
WHERE
  WR1: SIZEOF(TYPEOF(computed_representation) * 
    ['SKETCH_SCHEMA.IMPLICIT_PLANAR_CURVE',
     'GEOMETRY_SCHEMA.CURVE_REPLICA']) = 0;
END_ENTITY;

ENTITY implicit_intersection_curve
  SUBTYPE of (implicit_planar_curve);
  external_surface : surface;
END_ENTITY;

ENTITY implicit_projected_curve
  SUBTYPE of (implicit_planar_curve);
  external_curve       : curve;
  projection_direction : direction;
END_ENTITY;

ENTITY implicit_model_intersection_curve
  SUBTYPE of (implicit_planar_curve);
  intersected_model : surface_or_solid_model;
END_ENTITY;

ENTITY implicit_silhouette_curve
  SUBTYPE of (implicit_planar_curve);
  silhouetted_model : surface_or_solid_model;
  view_direction    : direction;
END_ENTITY;

ENTITY neutral_sketch_representation
  SUBTYPE OF (shape_representation);
  neutral_sketch_semantics  : curves_or_area; 
  SELF\representation.items : SET[1:?] OF sketch_element_select;
WHERE
  WR1: SIZEOF(QUERY(q <* SELF\representation.items | q.dim <> 2)) = 0;
END_ENTITY;

ENTITY positioned_sketch
  SUBTYPE OF (geometric_representation_item);
  sketch_basis           : sketch_basis_select;
  auxiliary_elements     : 
    SET[0:?] OF auxiliary_geometric_representation_item;
WHERE
  WR1: NOT (('GEOMETRY_SCHEMA.CURVE_BOUNDED_SURFACE' IN 
    TYPEOF(sketch_basis)) AND NOT ('GEOMETRY_SCHEMA.PLANE' IN
    TYPEOF(sketch_basis.basis_surface)));
  WR2: NOT (('TOPOLOGY_SCHEMA.FACE_SURFACE' IN TYPEOF(sketch_basis)) AND
    NOT ('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(sketch_basis.face_geometry)));
  WR3: SIZEOF(QUERY(q <* auxiliary_elements | (SIZEOF(TYPEOF(q) * 
    ['GEOMETRY_SCHEMA.POINT','GEOMETRY_SCHEMA.CURVE']) = 0))) = 0;
  WR4: SIZEOF(QUERY(q <* auxiliary_elements | 
    q\geometric_representation_item.dim <> 3)) = 0;
END_ENTITY;

ENTITY repositioned_neutral_sketch
  SUBTYPE OF (mapped_item, geometric_representation_item);
DERIVE
  map : representation_map := SELF\mapped_item.mapping_source;
WHERE
  WR1 : 'SKETCH_SCHEMA.NEUTRAL_SKETCH_REPRESENTATION'
    IN TYPEOF(map.mapped_representation);
  WR2 : 'GEOMETRY_SCHEMA.AXIS2_PLACEMENT_2D' IN 
    TYPEOF(map.mapping_origin);
  WR3 : 'GEOMETRY_SCHEMA.AXIS2_PLACEMENT_3D' IN 
    TYPEOF(SELF\mapped_item.mapping_target);
END_ENTITY;

ENTITY implicit_explicit_positioned_sketch_relationship
  SUBTYPE OF (representation_item_relationship);
  SELF\representation_item_relationship.relating_representation_item 
    : repositioned_neutral_sketch; 
  SELF\representation_item_relationship.related_representation_item  
    : positioned_sketch;
WHERE
  WR1: SIZEOF(QUERY(q <* using_representations(
    SELF\representation_item_relationship.related_representation_item) |
    item_in_context(
    SELF\representation_item_relationship.relating_representation_item,
    q.context_of_items))) > 0; 
END_ENTITY;

ENTITY subsketch
  SUBTYPE OF (geometric_representation_item);
  subsketch_elements : SET[1:?] OF sketch_element_select; 
  owning_sketch      : sketch_type_select;
WHERE
  WR1: (('SKETCH_SCHEMA.NEUTRAL_SKETCH_REPRESENTATION' 
    IN TYPEOF(owning_sketch)) AND (SIZEOF(QUERY(q <* 
    subsketch_elements | NOT (owning_sketch IN 
    using_representations(q)))) = 0))
    XOR
    ((SIZEOF(TYPEOF(owning_sketch) *
     ['SKETCH_SCHEMA.POSITIONED_SKETCH','SKETCH_SCHEMA.SUBSKETCH']) = 1)
    AND 
    (SIZEOF(QUERY(q <* subsketch_elements |
     NOT (owning_sketch IN using_items(q,[])))) = 0));
END_ENTITY;

ENTITY rigid_subsketch
  SUBTYPE OF (subsketch); 
END_ENTITY;

FUNCTION get_relative_direction_2points 
           (cp1, cp2 : cartesian_point) : direction;

  LOCAL
    d1, d2, d3, magnitude : REAL;
    result                : direction := ?;  
  END_LOCAL;

  -- check that input points are three-dimensional

  IF ((cp1.dim <> 3) OR (cp2.dim <> 3)) THEN 
    RETURN(result);
  ELSE

    -- construct components of vector and compute its magnitude

    BEGIN
      d1 := cp2.coordinates[1] - cp1.coordinates[1];
      d2 := cp2.coordinates[2] - cp1.coordinates[2];
      d3 := cp2.coordinates[3] - cp1.coordinates[3];
      magnitude := sqrt(d1*d1 + d2*d2 + d3*d3);
      IF (magnitude = 0) THEN 
        return(result); -- direction is indeterminate in this case
      END_IF;
      result := dummy_gri || direction([d1, d2, d3]);
    END;
  END_IF;
  RETURN(result);

END_FUNCTION;

FUNCTION check_curve_planarity (checked_curve: curve) : BOOLEAN;

  LOCAL
    crv    : curve   := checked_curve;
    i,j    : INTEGER;
    result : LOGICAL := UNKNOWN;
  END_LOCAL;

  -- Determine whether the curve lies on a plane, according to its type

  IF (SIZEOF(['GEOMETRY_SCHEMA.CONIC','GEOMETRY_SCHEMA.LINE'] *
    TYPEOF(crv)) > 0) 
  THEN result := TRUE;
  ELSE
    IF (('GEOMETRY_SCHEMA.TRIMMED_CURVE' IN TYPEOF(crv)) 
      AND check_curve_planarity(crv.basis_curve))
    THEN result := TRUE;
    ELSE
      IF (('GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(crv)) 
        AND ('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(crv.basis_surface)))
      THEN result := TRUE;
      ELSE
        IF ('GEOMETRY_SCHEMA.SURFACE_CURVE' IN TYPEOF(crv)) 
        THEN
        BEGIN
          REPEAT j := 1 TO HIINDEX(crv.basis_surface);
            IF ('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(crv.basis_surface[j])) 
            THEN result := TRUE;
            END_IF;
          END_REPEAT;
        END;
        END_IF;
      END_IF;
    END_IF;
  END_IF;

  RETURN(result);

END_FUNCTION;

FUNCTION get_plane_of_implicit_geometry
         (ps : positioned_sketch) : plane;

  LOCAL
    sb     : sketch_basis_select := ps.sketch_basis;
    result : plane := ?;
  END_LOCAL;

  -- determine plane of implicit geometry from the underlying entity data
  -- type of its owning instance of positioned_sketch_representation.  If
  -- the sketch basis is of type planar_curve_select then the planarity 
  -- of the curve is guaranteed by a WHERE rule on the SELECT type of that 
  -- name.

  IF ('TOPOLOGY_SCHEMA.FACE_SURFACE' IN TYPEOF(sb)) THEN 
    result := sb.face_geometry;
  ELSE
    IF ('GEOMETRY_SCHEMA.CURVE_BOUNDED_SURFACE' IN TYPEOF(sb)) THEN
      result := sb.basis_surface;
    ELSE 
      IF ('SKETCH_SCHEMA.PLANAR_CURVE_SELECT' IN TYPEOF(sb)) THEN
      BEGIN
 
        IF ('GEOMETRY_SCHEMA.CONIC' IN TYPEOF(sb)) 
          THEN result := dummy_gri || surface() || 
            elementary_surface(sb.position) || plane();
        END_IF;

        IF ('GEOMETRY_SCHEMA.TRIMMED_CURVE' IN TYPEOF(sb)) 
          THEN 
          BEGIN
            result := get_plane_of_implicit_geometry(
            dummy_gri || positioned_sketch(sb.basis_curve,[]));
          END;
        END_IF;

        IF ('GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(sb))
          THEN result := sb.basis_surface;
        END_IF;

        IF ('GEOMETRY_SCHEMA.SURFACE_CURVE' IN TYPEOF(sb)) THEN
        BEGIN
          IF ((SIZEOF(sb.basis_surface) = 1) -- case of one basis surface 
            AND ('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(sb.basis_surface[1])))
          THEN result := sb.basis_surface[1];
          ELSE -- case of two basis surfaces
            IF (('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(sb.basis_surface[1]))
              AND ('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(sb.basis_surface[2])))
            THEN result := ?;
              -- both basis surfaces are planes, their intersection curve 
              -- is a line, and no unique plane is defined
            ELSE -- only one of the two basis surfaces is a plane
              IF ('GEOMETRY_SCHEMA.PLANE' IN TYPEOF(sb.basis_surface[1]))
              THEN result := sb.basis_surface[1];
              ELSE result := sb.basis_surface[2];
              END_IF;
            END_IF;
          END_IF;
        END;
        END_IF;
      END;
      END_IF;
    END_IF;
  END_IF;

  RETURN(result);

END_FUNCTION;

END_SCHEMA; -- sketch_schema