Schema: topology_schema

Source : ISO 10303-42



SCHEMA topology_schema;

REFERENCE FROM basic_attribute_schema   -- ISO 10303-41
  (aggregate_id_attribute,
   get_aggregate_id_value,
   get_id_value,
   id_attribute,
   id_attribute_select);

REFERENCE FROM geometry_schema;    -- ISO 10303-42

REFERENCE FROM representation_schema   -- ISO 10303-43
  (representation,
   representation_item);

REFERENCE FROM support_resource_schema   -- ISO 10303-41
  (bag_to_set,
   identifier);


CONSTANT
  dummy_tri : topological_representation_item := representation_item('')|| topological_representation_item();
END_CONSTANT;

TYPE list_of_reversible_topology_item = LIST[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 set_of_reversible_topology_item = SET[0:?] OF reversible_topology_item;
END_TYPE;

TYPE shell = SELECT
   (vertex_shell,
    wire_shell,
    open_shell,
    closed_shell);
END_TYPE;

TYPE tri_id_attribute_select = SELECT BASED_ON id_attribute_select WITH
   (topological_representation_item);
END_TYPE;

ENTITY closed_shell
  SUBTYPE OF (connected_face_set);
END_ENTITY;

ENTITY connected_edge_set
  SUBTYPE OF (topological_representation_item);
  ces_edges : SET[1:?] OF edge;
END_ENTITY;

ENTITY connected_edge_sub_set
  SUBTYPE OF (connected_edge_set);
  parent_edge_set : connected_edge_set;
WHERE
  WR1: SELF :<>: parent_edge_set;
END_ENTITY;

ENTITY connected_face_set
  SUPERTYPE OF (ONEOF (closed_shell,
                       open_shell))
  SUBTYPE OF (topological_representation_item);
  cfs_faces : SET[1:?] OF face;
END_ENTITY;

ENTITY connected_face_sub_set
  SUBTYPE OF (connected_face_set);
  parent_face_set : connected_face_set;
WHERE
  WR1: SELF :<>: parent_face_set;
END_ENTITY;

ENTITY connected_volume_set
  SUBTYPE OF (topological_representation_item);
  cvs_volumes : SET[1:?] OF volume_with_faces;
END_ENTITY;

ENTITY connected_volume_sub_set
  SUBTYPE OF (connected_volume_set);
  parent_volume_set : connected_volume_set;
WHERE
  WR1: SELF :<>: parent_volume_set;
END_ENTITY;

ENTITY edge
  SUPERTYPE OF (ONEOF (edge_curve,
                       oriented_edge,
                       subedge))
  SUBTYPE OF (topological_representation_item);
  edge_start : vertex;
  edge_end : vertex;
END_ENTITY;

ENTITY edge_curve
  SUBTYPE OF (edge, geometric_representation_item);
  edge_geometry : curve;
  same_sense : BOOLEAN;
END_ENTITY;

ENTITY edge_loop
  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
  SUPERTYPE OF (ONEOF (face_surface,
                       subface,
                       oriented_face))
  SUBTYPE OF (topological_representation_item);
  bounds : SET[1:?] OF face_bound;
WHERE
  WR1: NOT (mixed_loop_type_set(list_to_set(list_face_loops(SELF))));
  WR2: SIZEOF(QUERY(temp <* bounds | 'TOPOLOGY_SCHEMA.FACE_OUTER_BOUND' IN TYPEOF(temp))) <= 1;
END_ENTITY;

ENTITY face_bound
  SUBTYPE OF (topological_representation_item);
  bound : loop;
  orientation : BOOLEAN;
END_ENTITY;

ENTITY face_outer_bound
  SUBTYPE OF (face_bound);
END_ENTITY;

ENTITY face_surface
  SUBTYPE OF (face, geometric_representation_item);
  face_geometry : surface;
  same_sense : BOOLEAN;
WHERE
  WR1: NOT ('GEOMETRY_SCHEMA.ORIENTED_SURFACE' IN TYPEOF(face_geometry));
END_ENTITY;

ENTITY loop
  SUPERTYPE OF (ONEOF (vertex_loop,
                       edge_loop,
                       poly_loop))
  SUBTYPE OF (topological_representation_item);
END_ENTITY;

ENTITY open_path
  SUBTYPE OF (path);
DERIVE
  ne : INTEGER := SIZEOF(SELF\path.edge_list);
WHERE
  WR1: (SELF\path.edge_list[1].edge_element.edge_start) :<>: (SELF\path.edge_list[ne].edge_element.edge_end);
END_ENTITY;

ENTITY open_shell
  SUBTYPE OF (connected_face_set);
END_ENTITY;

ENTITY oriented_closed_shell
  SUBTYPE OF (closed_shell);
  closed_shell_element : closed_shell;
  orientation : BOOLEAN;
DERIVE
  SELF\connected_face_set.cfs_faces : SET[1:?] OF face := conditional_reverse(SELF.orientation, SELF.closed_shell_element.cfs_faces);
WHERE
  WR1: NOT ('TOPOLOGY_SCHEMA.ORIENTED_CLOSED_SHELL' IN TYPEOF (SELF.closed_shell_element));
END_ENTITY;

ENTITY oriented_edge
  SUBTYPE OF (edge);
  edge_element : edge;
  orientation : BOOLEAN;
DERIVE
  SELF\edge.edge_start : vertex := boolean_choose (SELF.orientation, SELF.edge_element.edge_start, SELF.edge_element.edge_end);
  SELF\edge.edge_end : vertex := boolean_choose (SELF.orientation, SELF.edge_element.edge_end, SELF.edge_element.edge_start);
WHERE
  WR1: NOT ('TOPOLOGY_SCHEMA.ORIENTED_EDGE' IN TYPEOF (SELF.edge_element));
END_ENTITY;

ENTITY oriented_face
  SUBTYPE OF (face);
  face_element : face;
  orientation : BOOLEAN;
DERIVE
  SELF\face.bounds : SET[1:?] OF face_bound := conditional_reverse(SELF.orientation,SELF.face_element.bounds);
WHERE
  WR1: NOT ('TOPOLOGY_SCHEMA.ORIENTED_FACE' IN TYPEOF (SELF.face_element));
END_ENTITY;

ENTITY oriented_open_shell
  SUBTYPE OF (open_shell);
  open_shell_element : open_shell;
  orientation : BOOLEAN;
DERIVE
  SELF\connected_face_set.cfs_faces : SET[1:?] OF face := conditional_reverse(SELF.orientation, SELF.open_shell_element.cfs_faces);
WHERE
  WR1: NOT ('TOPOLOGY_SCHEMA.ORIENTED_OPEN_SHELL' IN TYPEOF (SELF.open_shell_element));
END_ENTITY;

ENTITY oriented_path
  SUBTYPE OF (path);
  path_element : path;
  orientation : BOOLEAN;
DERIVE
  SELF\path.edge_list : LIST[1:?] OF UNIQUE oriented_edge := conditional_reverse(SELF.orientation, SELF.path_element.edge_list);
WHERE
  WR1: NOT ('TOPOLOGY_SCHEMA.ORIENTED_PATH' IN TYPEOF (SELF.path_element));
END_ENTITY;

ENTITY path
  SUPERTYPE OF (ONEOF (open_path,
                       edge_loop,
                       oriented_path))
  SUBTYPE OF (topological_representation_item);
  edge_list : LIST[1:?] OF UNIQUE oriented_edge;
WHERE
  WR1: path_head_to_tail(SELF);
END_ENTITY;

ENTITY poly_loop
  SUBTYPE OF (loop, geometric_representation_item);
  polygon : LIST[3:?] OF UNIQUE cartesian_point;
END_ENTITY;

ENTITY seam_edge
  SUBTYPE OF (oriented_edge);
  pcurve_reference : pcurve;
WHERE
  WR1: ( 'TOPOLOGY_SCHEMA.EDGE_CURVE' IN TYPEOF (edge_element) ) AND ('TOPOLOGY_SCHEMA.SEAM_CURVE' IN TYPEOF (edge_element\edge_curve.edge_geometry));
  WR2: pcurve_reference IN edge_element\edge_curve.edge_geometry\ surface_curve.associated_geometry;
END_ENTITY;

ENTITY subedge
  SUBTYPE OF (edge);
  parent_edge : edge;
WHERE
  WR1: SELF :<>: parent_edge;
END_ENTITY;

ENTITY subface
  SUBTYPE OF (face);
  parent_face : face;
WHERE
  WR1: NOT (mixed_loop_type_set(list_to_set(list_face_loops(SELF)) + list_to_set(list_face_loops(parent_face))));
  WR2: SELF :<>: parent_face;
END_ENTITY;

ENTITY subpath
  SUBTYPE OF (path);
  parent_path : path;
WHERE
  WR1: SELF :<>: parent_path;
  WR2: NOT (('TOPOLOGY_SCHEMA.EDGE_LOOP' IN TYPEOF(SELF)) AND ('TOPOLOGY_SCHEMA.OPEN_PATH' IN TYPEOF(parent_path)));
END_ENTITY;

ENTITY topological_representation_item
  SUPERTYPE OF (ONEOF (vertex,
                       edge,
                       face_bound,
                       face,
                       vertex_shell,
                       wire_shell,
                       connected_edge_set,
                       connected_face_set,
                       connected_volume_set,
                       volume_with_faces, (
                       loop
               ANDOR path)))
  SUBTYPE OF (representation_item);
DERIVE
  permanent_id : identifier := get_id_value(SELF);
  permanent_aggregate_id : identifier := get_aggregate_id_value(SELF);
WHERE
  WR1: SIZEOF(USEDIN(SELF,'BASIC_ATTRIBUTE_SCHEMA.ID_ATTRIBUTE.IDENTIFIED_ITEM')) <= 1;
  WR2: SIZEOF(USEDIN(SELF,'BASIC_ATTRIBUTE_SCHEMA.AGGREGATE_ID_ATTRIBUTE.IDENTIFIED_ITEM')) <= 1;
END_ENTITY;

ENTITY vertex
  SUBTYPE OF (topological_representation_item);
END_ENTITY;

ENTITY vertex_loop
  SUBTYPE OF (loop);
  loop_vertex : vertex;
END_ENTITY;

ENTITY vertex_point
  SUBTYPE OF (vertex, geometric_representation_item);
  vertex_geometry : point;
END_ENTITY;

ENTITY vertex_shell
  SUBTYPE OF (topological_representation_item);
  vertex_shell_extent : vertex_loop;
END_ENTITY;

ENTITY volume_with_faces
  ABSTRACT SUPERTYPE OF (ONEOF (volume_with_shell,
                                volume_with_parametric_boundary))
  SUBTYPE OF (geometric_representation_item, topological_representation_item);
  volume_geometry : volume;
END_ENTITY;

ENTITY volume_with_parametric_boundary
  SUBTYPE OF (volume_with_faces);
  outer_bound : LIST[6:6] OF face;
END_ENTITY;

ENTITY volume_with_shell
  SUBTYPE OF (volume_with_faces);
  outer_bound : closed_shell;
END_ENTITY;

ENTITY wire_shell
  SUBTYPE OF (topological_representation_item);
  wire_shell_extent : SET[1:?] OF loop;
WHERE
  WR1: NOT mixed_loop_type_set(wire_shell_extent);
END_ENTITY;

FUNCTION boolean_choose
 (b : BOOLEAN; choice1 : GENERIC : item; choice2 : GENERIC : item) : GENERIC : item;
IF b THEN
       RETURN (choice1);
     ELSE
       RETURN (choice2);
     END_IF;
END_FUNCTION;

FUNCTION closed_shell_reversed
 (a_shell : closed_shell) : oriented_closed_shell;
LOCAL
    the_reverse : oriented_closed_shell;
  END_LOCAL;
   IF ('TOPOLOGY_SCHEMA.ORIENTED_CLOSED_SHELL' IN TYPEOF (a_shell) ) THEN
      the_reverse := dummy_tri ||
                    connected_face_set (
                       a_shell\connected_face_set.cfs_faces) ||
                    closed_shell () || oriented_closed_shell(
                     a_shell\oriented_closed_shell.closed_shell_element,
                       NOT(a_shell\oriented_closed_shell.orientation));
   ELSE
      the_reverse := dummy_tri ||
               connected_face_set (
                 a_shell\connected_face_set.cfs_faces) ||
               closed_shell () || oriented_closed_shell (a_shell, FALSE);
   END_IF;
   RETURN (the_reverse);
END_FUNCTION;

FUNCTION conditional_reverse
 (p : BOOLEAN; an_item : reversible_topology) : reversible_topology;
IF p THEN
     RETURN (an_item);
   ELSE
     RETURN (topology_reversed (an_item));
   END_IF;
END_FUNCTION;

FUNCTION edge_curve_pcurves
 (an_edge : edge_curve; the_surface_curves : SET[0:?] OF surface_curve) : SET[0:?] OF pcurve;
LOCAL
  a_curve      : curve;
  result       : SET OF pcurve;
  the_geometry : LIST[1:2] OF pcurve_or_surface;
END_LOCAL;
  a_curve := an_edge.edge_geometry;
  result := [];
  IF 'GEOMETRY_SCHEMA.PCURVE' IN TYPEOF(a_curve) THEN
    result := result + a_curve;
  ELSE
    IF 'GEOMETRY_SCHEMA.SURFACE_CURVE' IN TYPEOF(a_curve) THEN
      the_geometry := a_curve\surface_curve.associated_geometry;
      REPEAT k := 1 TO SIZEOF(the_geometry);
         IF 'GEOMETRY_SCHEMA.PCURVE' IN TYPEOF (the_geometry[k])
         THEN
            result := result + the_geometry[k];
         END_IF;
      END_REPEAT;
    ELSE
      REPEAT j := 1 TO SIZEOF(the_surface_curves);
        the_geometry := the_surface_curves[j].associated_geometry;
        IF the_surface_curves[j].curve_3d :=: a_curve
        THEN
          REPEAT k := 1 TO SIZEOF(the_geometry);
            IF 'GEOMETRY_SCHEMA.PCURVE' IN TYPEOF (the_geometry[k])
            THEN
              result := result + the_geometry[k];
            END_IF;
          END_REPEAT;
        END_IF;
      END_REPEAT;
    END_IF;
  END_IF;

  RETURN (result);
END_FUNCTION;

FUNCTION edge_reversed
 (an_edge : edge) : oriented_edge;
LOCAL
     the_reverse : oriented_edge;
   END_LOCAL;

   IF ('TOPOLOGY_SCHEMA.ORIENTED_EDGE' IN TYPEOF (an_edge) ) THEN
     the_reverse  := dummy_tri ||
             edge(an_edge.edge_end, an_edge.edge_start) ||
             oriented_edge(an_edge\oriented_edge.edge_element,
                        NOT (an_edge\oriented_edge.orientation)) ;
   ELSE
     the_reverse := dummy_tri ||
             edge(an_edge.edge_end, an_edge.edge_start) ||
             oriented_edge(an_edge, FALSE);
   END_IF;
   RETURN (the_reverse);
END_FUNCTION;

FUNCTION face_bound_reversed
 (a_face_bound : face_bound) : face_bound;
LOCAL
     the_reverse : face_bound ;
   END_LOCAL;
   IF ('TOPOLOGY_SCHEMA.FACE_OUTER_BOUND' IN TYPEOF (a_face_bound) ) THEN
     the_reverse := dummy_tri ||
                      face_bound(a_face_bound\face_bound.bound,
                           NOT (a_face_bound\face_bound.orientation))
                            || face_outer_bound() ;
   ELSE
     the_reverse := dummy_tri ||
         face_bound(a_face_bound.bound, NOT(a_face_bound.orientation));
   END_IF;
  RETURN (the_reverse);
END_FUNCTION;

FUNCTION face_reversed
 (a_face : face) : oriented_face;
LOCAL
     the_reverse : oriented_face ;
   END_LOCAL;
   IF ('TOPOLOGY_SCHEMA.ORIENTED_FACE' IN TYPEOF (a_face) ) THEN
     the_reverse := dummy_tri ||
       face(set_of_topology_reversed(a_face.bounds)) ||
          oriented_face(a_face\oriented_face.face_element,
                           NOT (a_face\oriented_face.orientation)) ;
   ELSE
     the_reverse := dummy_tri ||
       face(set_of_topology_reversed(a_face.bounds)) ||
                               oriented_face(a_face, FALSE) ;
   END_IF;
      RETURN (the_reverse);
END_FUNCTION;

FUNCTION get_tri_in_representations
 (members : SET[0:?] OF representation) : SET[0:?] OF topological_representation_item;
LOCAL
 tri_set : SET OF topological_representation_item := [];
END_LOCAL;

IF SIZEOF(members) = 0 THEN
RETURN(?);
END_IF;

REPEAT i := LOINDEX(members) TO HIINDEX(members);
  REPEAT J := LOINDEX(members[i]\representation.items) TO HIINDEX(members[i]\representation.items);
   IF 'TOPOLOGY_SCHEMA.TOPOLOGICAL_REPRESENTATION_ITEM' IN TYPEOF(members[i]\representation.items[j]) THEN
    tri_set := tri_set + members[i]\representation.items[j];
   END_IF;
  END_REPEAT;
END_REPEAT;

RETURN(tri_set);
END_FUNCTION;

FUNCTION list_face_loops
 (f : face) : LIST[0:?] OF loop;
LOCAL
     loops : LIST[0:?] OF loop := [];
   END_LOCAL;
   
   REPEAT i := 1 TO SIZEOF(f.bounds);
     loops := loops +(f.bounds[i].bound);
   END_REPEAT;
      
   RETURN(loops);
END_FUNCTION;

FUNCTION list_loop_edges
 (l : loop) : LIST[0:?] OF edge;
LOCAL
     edges : LIST[0:?] OF edge := [];
   END_LOCAL;
      
   IF 'TOPOLOGY_SCHEMA.EDGE_LOOP' IN TYPEOF(l) THEN
     REPEAT i := 1 TO SIZEOF(l\path.edge_list);
       edges := edges + (l\path.edge_list[i].edge_element);
     END_REPEAT;
   END_IF;

   RETURN(edges);
END_FUNCTION;

FUNCTION list_of_topology_reversed
 (a_list : list_of_reversible_topology_item) : list_of_reversible_topology_item;
LOCAL
     the_reverse : list_of_reversible_topology_item;
   END_LOCAL;
    
   the_reverse := [];
   REPEAT i := 1 TO SIZEOF (a_list);
     the_reverse := topology_reversed (a_list [i]) + the_reverse;
   END_REPEAT;
  
   RETURN (the_reverse);
END_FUNCTION;

FUNCTION list_shell_edges
 (s : shell) : LIST[0:?] OF edge;
LOCAL
     edges : LIST[0:?] OF edge := [];
   END_LOCAL;
      
   REPEAT i := 1 TO SIZEOF(list_shell_loops(s));
     edges := edges + list_loop_edges(list_shell_loops(s)[i]);
   END_REPEAT;
   
   RETURN(edges);
END_FUNCTION;

FUNCTION list_shell_faces
 (s : shell) : LIST[0:?] OF face;
LOCAL
     faces : LIST[0:?] OF face := [];
   END_LOCAL;
   
   IF ('TOPOLOGY_SCHEMA.CLOSED_SHELL' IN TYPEOF(s)) OR 
      ('TOPOLOGY_SCHEMA.OPEN_SHELL' IN TYPEOF(s)) THEN
     REPEAT i := 1 TO SIZEOF(s\connected_face_set.cfs_faces);
       faces := faces + s\connected_face_set.cfs_faces[i];
     END_REPEAT;
   END_IF;
      
   RETURN(faces);
END_FUNCTION;

FUNCTION list_shell_loops
 (s : shell) : LIST[0:?] OF loop;
LOCAL
     loops : LIST[0:?] OF loop := [];
   END_LOCAL;
      
   IF 'TOPOLOGY_SCHEMA.VERTEX_SHELL' IN TYPEOF(s) THEN
     loops := loops + s.vertex_shell_extent;
   END_IF;
      
   IF 'TOPOLOGY_SCHEMA.WIRE_SHELL' IN TYPEOF(s) THEN
     REPEAT i := 1 TO SIZEOF(s.wire_shell_extent);
       loops := loops + s.wire_shell_extent[i];
     END_REPEAT;
   END_IF;
      
   IF ('TOPOLOGY_SCHEMA.OPEN_SHELL' IN TYPEOF(s)) OR 
      ('TOPOLOGY_SCHEMA.CLOSED_SHELL' IN TYPEOF(s)) THEN
     REPEAT i := 1 TO SIZEOF(s.cfs_faces);
       loops := loops + list_face_loops(s.cfs_faces[i]);
     END_REPEAT;
   END_IF;
      
   RETURN(loops);
END_FUNCTION;

FUNCTION list_to_set
 (l : LIST[0:?] OF GENERIC : T) : SET[0:?] OF GENERIC : T;
LOCAL
     s : SET OF GENERIC:T := [];
   END_LOCAL;
      
   REPEAT i := 1 TO SIZEOF(l);
     s := s + l[i];
   END_REPEAT;
   
   RETURN(s);
END_FUNCTION;

FUNCTION mixed_loop_type_set
 (l : SET[0:?] OF loop) : LOGICAL;
LOCAL
      poly_loop_type: LOGICAL;
    END_LOCAL;
    IF(SIZEOF(l) <= 1) THEN
      RETURN(FALSE);
    END_IF;
    poly_loop_type := ('TOPOLOGY_SCHEMA.POLY_LOOP' IN TYPEOF(l[1]));
    REPEAT i := 2 TO SIZEOF(l);
      IF(('TOPOLOGY_SCHEMA.POLY_LOOP' IN TYPEOF(l[i])) <> poly_loop_type)
          THEN
          RETURN(TRUE);
       END_IF;
    END_REPEAT;
    RETURN(FALSE);
END_FUNCTION;

FUNCTION open_shell_reversed
 (a_shell : open_shell) : oriented_open_shell;
LOCAL
     the_reverse : oriented_open_shell;
   END_LOCAL;
   IF ('TOPOLOGY_SCHEMA.ORIENTED_OPEN_SHELL' IN TYPEOF (a_shell) ) THEN
     the_reverse := dummy_tri ||
                  connected_face_set (
                      a_shell\connected_face_set.cfs_faces) ||
                  open_shell () || oriented_open_shell(
                    a_shell\oriented_open_shell.open_shell_element,
                      (NOT (a_shell\oriented_open_shell.orientation)));
   ELSE
     the_reverse := dummy_tri ||
                 connected_face_set (
                     a_shell\connected_face_set.cfs_faces) ||
                 open_shell () ||  oriented_open_shell (a_shell, FALSE);
   END_IF;
   RETURN (the_reverse);
END_FUNCTION;

FUNCTION path_head_to_tail
 (a_path : path) : LOGICAL;
LOCAL
     n : INTEGER;
     p : LOGICAL := TRUE;
   END_LOCAL;
     
     n := SIZEOF (a_path.edge_list);
     REPEAT i := 2 TO n;
       p := p AND (a_path.edge_list[i-1].edge_end :=:
                   a_path.edge_list[i].edge_start);
     END_REPEAT;
     
     RETURN (p);
END_FUNCTION;

FUNCTION path_reversed
 (a_path : path) : oriented_path;
LOCAL
    the_reverse : oriented_path ;
  END_LOCAL;
  IF ('TOPOLOGY_SCHEMA.ORIENTED_PATH' IN TYPEOF (a_path) ) THEN
    the_reverse := dummy_tri ||
       path(list_of_topology_reversed (a_path.edge_list)) ||
          oriented_path(a_path\oriented_path.path_element,
                          NOT(a_path\oriented_path.orientation)) ;
  ELSE
    the_reverse := dummy_tri ||
                   path(list_of_topology_reversed (a_path.edge_list)) ||
                       oriented_path(a_path, FALSE);
  END_IF;

  RETURN (the_reverse);
END_FUNCTION;

FUNCTION set_of_topology_reversed
 (a_set : set_of_reversible_topology_item) : set_of_reversible_topology_item;
LOCAL
     the_reverse : set_of_reversible_topology_item;
   END_LOCAL;
   
   the_reverse := [];
   REPEAT i := 1 TO SIZEOF (a_set);
     the_reverse := the_reverse + topology_reversed (a_set [i]);
   END_REPEAT;
   
   RETURN (the_reverse);
END_FUNCTION;

FUNCTION shell_reversed
 (a_shell : shell) : shell;
IF ('TOPOLOGY_SCHEMA.OPEN_SHELL' IN TYPEOF (a_shell) ) THEN
     RETURN (open_shell_reversed (a_shell));
   ELSE
     IF ('TOPOLOGY_SCHEMA.CLOSED_SHELL' IN TYPEOF (a_shell) ) THEN
       RETURN (closed_shell_reversed (a_shell));
     ELSE
       RETURN (?);
     END_IF;
   END_IF;
END_FUNCTION;

FUNCTION topology_reversed
 (an_item : reversible_topology) : reversible_topology;
IF ('TOPOLOGY_SCHEMA.EDGE' IN TYPEOF (an_item)) THEN
     RETURN (edge_reversed (an_item));
   END_IF;

   IF ('TOPOLOGY_SCHEMA.PATH' IN TYPEOF (an_item)) THEN
     RETURN (path_reversed (an_item));
   END_IF;

   IF ('TOPOLOGY_SCHEMA.FACE_BOUND' IN TYPEOF (an_item)) THEN
     RETURN (face_bound_reversed (an_item));
   END_IF;
  
   IF ('TOPOLOGY_SCHEMA.FACE' IN TYPEOF (an_item)) THEN
     RETURN (face_reversed (an_item));
   END_IF;

   IF ('TOPOLOGY_SCHEMA.SHELL' IN TYPEOF (an_item)) THEN
     RETURN (shell_reversed (an_item));
   END_IF;

   IF ('SET' IN TYPEOF (an_item)) THEN
     RETURN (set_of_topology_reversed (an_item));
   END_IF;

   IF ('LIST' IN TYPEOF (an_item)) THEN
     RETURN (list_of_topology_reversed (an_item));
   END_IF;

   RETURN (?);
END_FUNCTION;

FUNCTION valid_tri_ids
 (objs : SET[0:?] OF topological_representation_item) : BOOLEAN;
LOCAL
   values              : BAG OF identifier := [];
END_LOCAL;

  REPEAT i := LOINDEX(objs) TO HIINDEX(objs);
--each tri shall have at least one id.
   IF NOT(EXISTS(objs[i]\topological_representation_item.permanent_id) OR
          EXISTS(objs[i]\topological_representation_item.permanent_aggregate_id)) THEN
    RETURN(FALSE);
   END_IF;
   values := values + objs[i]\topological_representation_item.permanent_id 
                       + objs[i]\topological_representation_item.permanent_aggregate_id;
  END_REPEAT;

--ids are unique across both types
 IF SIZEOF(bag_to_set(values)) <> SIZEOF(values) THEN 
   RETURN(FALSE);
 END_IF;

 RETURN (TRUE);
END_FUNCTION;

FUNCTION vertex_point_pcurves
 (a_vertex : vertex_point; the_degenerates : SET[0:?] OF evaluated_degenerate_pcurve) : SET[0:?] OF degenerate_pcurve;
LOCAL
  a_point : point;
  result  : SET OF degenerate_pcurve;
END_LOCAL;
  a_point := a_vertex.vertex_geometry;
  result := [];
  IF 'GEOMETRY_SCHEMA.DEGENERATE_PCURVE' IN TYPEOF(a_point) THEN
    result := result + a_point;
  ELSE
      REPEAT j := 1 TO SIZEOF(the_degenerates);
         IF (the_degenerates[j].equivalent_point :=: a_point)  THEN
            result := result + the_degenerates[j];
         END_IF;
      END_REPEAT;
  END_IF;

  RETURN (result);
END_FUNCTION;

END_SCHEMA;  -- topology_schema