Clipping a Mesh Against a Plane

Similar documents
Constructing a Cycle Basis for a Planar Graph

1 Introduction 2. 2 A Simple Algorithm 2. 3 A Fast Algorithm 2

Perspective Mappings. Contents

Triangulation by Ear Clipping

Minimum-Area Rectangle Containing a Set of Points

Intersection of a Triangle and a Cone

Tessellation of a Unit Sphere Starting with an Inscribed Convex Triangular Mesh

Clipping & Culling. Lecture 11 Spring Trivial Rejection Outcode Clipping Plane-at-a-time Clipping Backface Culling

Intersection of an Oriented Box and a Cone

Level Set Extraction from Gridded 2D and 3D Data

Extraction of Level Sets from 2D Images

Practical Linear Algebra: A Geometry Toolbox

Clipping and Intersection

Minimum-Volume Box Containing a Set of Points

Computer Graphics Prof. Sukhendu Das Dept. of Computer Science and Engineering Indian Institute of Technology, Madras Lecture - 24 Solid Modelling

Lecture 25 of 41. Spatial Sorting: Binary Space Partitioning Quadtrees & Octrees

Triangle Rasterization

On-Line Computer Graphics Notes CLIPPING

Distance Between Point and Triangle in 3D

Chapter 4 Concepts from Geometry

CSCI 4620/8626. Computer Graphics Clipping Algorithms (Chapter 8-5 )

Matching and Planarity

Intersection of Moving Sphere and Triangle

15. Clipping. Projection Transformation. Projection Matrix. Perspective Division

Lecture notes: Object modeling

As a consequence of the operation, there are new incidences between edges and triangles that did not exist in K; see Figure II.9.

Convex Hulls in Three Dimensions. Polyhedra

Pebble Sets in Convex Polygons

EXTREME POINTS AND AFFINE EQUIVALENCE

Constrained Delaunay Triangulations (CDT)

2D rendering takes a photo of the 2D scene with a virtual camera that selects an axis aligned rectangle from the scene. The photograph is placed into

Geometric Computations for Simulation

GEOMETRIC TOOLS FOR COMPUTER GRAPHICS

The goal is the definition of points with numbers and primitives with equations or functions. The definition of points with numbers requires a

Preferred directions for resolving the non-uniqueness of Delaunay triangulations

Lofting 3D Shapes. Abstract

Flavor of Computational Geometry. Convex Hull in 2D. Shireen Y. Elhabian Aly A. Farag University of Louisville

Solutions to problem set 1

Geometric Algorithms in Three Dimensions Tutorial. FSP Seminar, Strobl,

Computational Geometry

: Mesh Processing. Chapter 8

Page 1. Area-Subdivision Algorithms z-buffer Algorithm List Priority Algorithms BSP (Binary Space Partitioning Tree) Scan-line Algorithms

Two-Dimensional Viewing. Chapter 6

Saab. Kyle McDonald. Polygon Meshes

Part IV. 2D Clipping

Polygon Triangulation

MATH 890 HOMEWORK 2 DAVID MEREDITH

Polygon Partitioning. Lecture03

γ 2 γ 3 γ 1 R 2 (b) a bounded Yin set (a) an unbounded Yin set

CMSC 754 Computational Geometry 1

RASTERIZING POLYGONS IN IMAGE SPACE

Lecture 17: Solid Modeling.... a cubit on the one side, and a cubit on the other side Exodus 26:13

CSE 167: Lecture #5: Rasterization. Jürgen P. Schulze, Ph.D. University of California, San Diego Fall Quarter 2012

Topological Issues in Hexahedral Meshing

Polygon Filling. Can write frame buffer one word at time rather than one bit. 2/3/2000 CS 4/57101 Lecture 6 1

Scalar Field Visualization. Some slices used by Prof. Mike Bailey

Computational Geometry

Sung-Eui Yoon ( 윤성의 )

Lecture 2 September 3

66 III Complexes. R p (r) }.

Lecture 3. Corner Polyhedron, Intersection Cuts, Maximal Lattice-Free Convex Sets. Tepper School of Business Carnegie Mellon University, Pittsburgh

Renderer Implementation: Basics and Clipping. Overview. Preliminaries. David Carr Virtual Environments, Fundamentals Spring 2005

Clipping. CSC 7443: Scientific Information Visualization

INFOGR Computer Graphics. J. Bikker - April-July Lecture 11: Visibility. Welcome!

FROM VERTICES TO FRAGMENTS. Lecture 5 Comp3080 Computer Graphics HKBU

S U N G - E U I YO O N, K A I S T R E N D E R I N G F R E E LY A VA I L A B L E O N T H E I N T E R N E T

Three applications of Euler s formula. Chapter 10

Triangle meshes I. CS 4620 Lecture Steve Marschner. Cornell CS4620 Spring 2017

MARCHING CUBES AND VARIANTS

9. Three Dimensional Object Representations

Invariant Measures of Convex Sets. Eitan Grinspun, Columbia University Peter Schröder, Caltech

Intersection of Box and Ellipsoid

Chapter 6. Planar Orientations. 6.1 Numberings of Digraphs

Triangle meshes I. CS 4620 Lecture 2

Solid Modelling. Graphics Systems / Computer Graphics and Interfaces COLLEGE OF ENGINEERING UNIVERSITY OF PORTO

Week 7 Convex Hulls in 3D

4.5 VISIBLE SURFACE DETECTION METHODES

CLASSIFICATION OF SURFACES

Line segment intersection. Family of intersection problems

COMPUTING CONSTRAINED DELAUNAY

Computational Geometry [csci 3250]

3D Validation of CityGML

CS 532: 3D Computer Vision 14 th Set of Notes

Accelerating Geometric Queries. Computer Graphics CMU /15-662, Fall 2016

Pacific Journal of Mathematics

Image Morphing. The user is responsible for defining correspondences between features Very popular technique. since Michael Jackson s clips

Computer Graphics. The Two-Dimensional Viewing. Somsak Walairacht, Computer Engineering, KMITL

Elementary Planar Geometry

Lecture 3 (CGAL) Panos Giannopoulos, Dror Atariah AG TI WS 2012/13

Computer Science 474 Spring 2010 Viewing Transformation

Marching Squares Algorithm. Can you summarize the marching squares algorithm based on what we just discussed?

Treewidth and graph minors

Project 3: Point Location

Computational Geometry

Delaunay Triangulations

Computer Graphics. - Rasterization - Philipp Slusallek

VISIBILITY & CULLING. Don t draw what you can t see. Thomas Larsson, Afshin Ameri DVA338, Spring 2018, MDH

White Paper. Solid Wireframe. February 2007 WP _v01

Critique for CS 448B: Topics in Modeling The Voronoi-clip Collision Detection Algorithm

Basic Properties The Definition of Catalan Numbers

Transcription:

Clipping a Mesh Against a Plane David Eberly, Geometric Tools, Redmond WA 98052 https://www.geometrictools.com/ This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. Created: February 28, 2002 Last Modified: March 1, 2008 Contents 1 Introduction 2 2 Mesh Data Structures 4 3 Initializing the Clipper Mesh 6 4 Clipping by a Plane 6 4.1 Vertex Processing........................................... 7 4.2 Edge Processing........................................... 7 4.3 Face Processing............................................ 8 5 Conversion Back to an Application Mesh 9 6 Support for Closing a Clipped Mesh 12 6.1 Closing a Clipped Convex Polyhedron............................... 12 6.2 Closing a Clipped Closed Polyhedron................................ 13 1

1 Introduction Clipping is a standard operation in computer graphics that involves splitting an object by a plane and retaining that part of the object, if any, that is on one designated side of the plane. Typical applications include computing the portion of an object that is inside a viewing frustum for display purposes and constructing sets of intersection between two objects. The plane is represented by the equation N X c = 0 where N is a unit-length normal vector, c is a scalar, and X is any point on the plane. For any point Y, we say that Y is on the positive side of the plane when N Y c > 0, on the negative side of the plane when N Y c < 0, or on the plane when N Y c = 0. Similarly, Y is on the nonnegative side of the plane when N Y c 0 or on the nonpositive side of the plane when N Y c 0. The simplest example is clipping a line segment by a plane as shown in Figure 1. Figure 1. A line segment clipped by a plane. The line segment has end points P 0 and P 1 and is denoted by P 0, P 1. The convention in this document is that clipping retains the portion of the object on the nonnegative side of the plane. The portion on the negative side is discarded. In Figure 1, the point P 0 is on the positive side of the plane and the point P 1 is on the negative side. The point of intersection of the line segment and the plane occurs at Q. To be on the plane we need N Q c = 0. To be on the line segment, we need Q = (1 t)p 0 + tp 1 for some t [0, 1]. Substituting this into the plane equation and solving for t leads to t = N P 0 N (P 0 P 1 ) = N P 0 c (N P 0 c) (N P 1 c) = d 0 (1) d 0 d 1 where d i = N P i c for i = 0, 1. The point of intersection is therefore Q = P 0 + (d 0 /(d 0 d 1 ))(P 1 P 0 ). The line segment that is retained is P 0, Q. The line segment that is discarded is Q, P 1. Generally, the clipping results of a line segment P 0, P 1 are as follows. 1. d 0 0 and d 1 > 0, or, d 0 > 0 and d 1 0: The entire segment is retained. 2. d 0 0 and d 1 < 0, or, d 0 < 0 and d 1 0: The entire segment is clipped. 2

3. d 0 > 0 and d 1 < 0, or, d 0 < 0 and d 1 > 0: The segment intersects the plane at a point Q that is interior to the segment. That is, the value of t in equation (1) satisfies 0 < t < 1. If d 0 > 0, the retained segment is P 0, Q. If d 1 > 0, the retained segment is Q, P 1. 4. d 0 = 0 and d 1 = 0. The segment lies entirely in the plane. Whether it is retained or discarded is dependent on the application. In the clipping algorithm of this document, such segments are discarded during the intermediate stage of the algorithm, but are re-added in the final stage. The next example shows how to clip a triangle by a plane. Let P 0, P 1, and P 2 be the triangle vertices. The clipping results are completely determined by the signs of d i = N P i c for 0 i 2. Figure 2 shows two typical configurations. Figure 2. Triangles clipped by a plane. In the left figure, the portion remaining after clipping is itself a triangle. In the right figure, the portion remaining is a convex quadrilateral. Some applications that manipulate only triangles as primitives will choose to split the quadrilateral into two triangles for any further processing. For example, if the triangle is being clipped relative to a view frustum defined by six planes, and the clipping operation for a single plane is designed to handle only triangles, then the quadrilateral must be decomposed into two triangles for clipping against the remaining planes. In this document I show how to build a clipper that does not constrain itself to triangles, rather it manages the convex polygons that occur as a result of clipping. If the application that uses the clipper allows only triangles, the resulting convex polygons from the clipping may be triangulated to satisfy those constraints. A key observation from Figure 2 is that you may compute the d i first, then compare pairs of the d i corresponding to edges of the triangle so that those edges may be clipped accordingly. This allows the edge processing to be a separate phase from the vertex processing. Less obvious is that the face processing, a face being a convex polygon, can be a separate phase from the edge processing. Thus, a clipper may be constructed that processes vertices first, edges second, and faces third. 3

2 Mesh Data Structures The introduction motivated clipping of a line segment and of a triangle. The operations apply more generally to a mesh of convex polygons. The classical meshes use triangle faces, but the ideas presented here apply to faces that are convex polygons. The data structures used to represent the mesh form a vertex-edge-face table. The minimum information required in a mesh to support clipping is that each vertex knows its spatial location, each edge knows the two vertices that form its end points and knows all the faces that share the edge, and each face knows all the edges that bound it. Figure 3 shows the minimum data structures for the application mesh. Figure 3. The minimum information needed by an application mesh to support clipping. AVertex: AEdge: AFace: AMesh: Point point; array(int) vertex; set(int) edge; array(avertex) V; set(int) face; array(aedge) E; array(aface) F; The AVertex data structure can be slightly more general by allowing a level of indirection. The application can store an array of points and require the vertex to store an index into that array rather than storing the point itself. The array of integers in the AEdge data structure has length 2 since each edge has exactly two end points. The elements of this array are indices into the array of edges in the Mesh data structure. The set of faces in AEdge must be nonempty. The elements of this set are indices into the array of faces in the AMesh data structure. In many applications, a mesh is required to be manifold in the sense that an edge is shared by 1 or 2 faces. If the meshes are constrained to be manifold, then the set member of AEdge may be replaced by a length-2 array of integers. When an edge is shared by only one face, the first element of the array contains a nonnegative index into the face array of the mesh. The other element of the array stores an invalid index; by convention this can be 1. Finally, the set of edges in AFace must contain at least three elements since the smallest convex polygon for a face is a triangle. The elements of this set are indices into the array of edges in the AMesh data structure. The clipping algorithm described here requires some additional information. It is convenient to allow the clipper to have data structures similar to those of the application but that allow storage for the additional items. Figure 4 shows the data structures. 4

Figure 4. The information needed by the clipper. CVertex: CEdge: CFace: CMesh: Point point; array(int) vertex; set(int) edge; array(cvertex) V; float distance; set(int) face; boolean visible; array(cedge) E; int occurs; boolean visible; array(cface) F; boolean visible; The distance member of CVertex is used to store the signed distance from the vertex to a plane. If the point is P and the plane has unit-length normal N and constant c, then the signed distance from the point to the plane is d = N P c. The actual distance is d. Although I assumed earlier that the plane normal is a unit-length vector, that vector need not be unit length in the calculations. If it is not unit length, then d is no longer the signed distance. However, this is unimportant since all that is important for the clipping is the sign of d as mentioned earlier when enumerating all the possibilities for clipping a line segment. The occurs member of CVertex provides support for computing the convex polygon resulting from the clipping. In Figure 2, the points of intersection with line segments and the plane are denoted Q 0 and Q 1. These points will be constructed by the clipper. The clipper will know immediately which subsegments are retained by considering the signed distances of the segment s original end points. The clipper also knows to retain edges on the positive side of the plane and to discard edges on the negative side. The intersection points of edges with the plane are added to the CVertex array of the CMesh. The vertex indices of the CEdge for a clipped edge are updated accordingly, and in place, so any CFace sharing the edge need not be updated when an intersection occurs. The CFace objects are notified about discarded edges. Each such edge is removed from the set of edges stored by the face. Because the edges are effectively processed in an arbitrary order, the clipper does not know during the edge processing phase that the segment Q 0, Q 1 belongs to the clipped face. The face processing phase has the responsibility for recognizing this. Using the right image in Figure 2 to illustrate, the original face is the convex polygon P 0, P 1, P 2. I stress the fact that this is a closed polyline. After the edge processing, the face has been clipped to produce the open polyline Q 1, P 2, P 0, Q 0. The end points of this polyline must be located and an edge connecting them must be added to the CMesh and the appropriate index added to the edge set of the CFace object. The set of edges in the face is unordered, a fact that can make the search difficult. However, it is enough just to traverse the unordered set and let each vertex end point know how many times it has been visited. The points P 0 and P 2 are each seen 2 times; the points Q 0 and Q 1 are each seen 1 time. The occurs member is initially zero and is incremented each time the vertex is visited, thus leading to a final value of 1 or 2. The visible member of CVertex is used to indicate which side of the plane the vertex occurs. The value is true if the point is on the nonnegative side of the plane, false if the point is on the negative side. This information is not necessary when clipping against a single plane. However, if the mesh is to be clipped against a set of planes, the visibility flag allows you to avoid processing vertices that were discarded by earlier planes. The visible member of CEdge is also used to indicate which side of the plane the edge occurs. The value is true if one end point is on the positive side of the plane, the other end point on the nonnegative side. The value is false, otherwise, including the case when the edge is entirely on the plane. A discarded planar edge will be restored during the face processing phase when the polyline of the face is closed to form a convex polygon. The edge visibility member is necessary even when clipping only against one plane. 5

The visible member of CFace is used to indicate which side of the plane the face occurs. The value is true if at least one edge of the face is visible, false otherwise. 3 Initializing the Clipper Mesh The clipper mesh data structures must be initialized from the application mesh. The pseudocode for this is shown below. CMesh ( AMesh appmesh ) V. S e t S i z e ( appmesh. V. l e n g t h ) ; f o r ( i = 0 ; i < V. l e n g t h ; i ) V [ i ]. p o i n t = appmesh. V [ i ]. p o i n t ; E. S e t S i z e ( appmesh. E. l e n g t h ) ; f o r ( i = 0 ; i < E. l e n g t h ; i ++) E [ i ]. v e r t e x [ 0 ] = appmesh. E [ i ]. v e r t e x [ 0 ] ; E [ i ]. v e r t e x [ 1 ] = appmesh. E [ i ]. v e r t e x [ 1 ] ; f o r ( each j i n appmesh. E [ i ]. f a c e ) E [ i ]. f a c e. I n s e r t ( j ) ; F. S e t S i z e ( appmesh. F. l e n g t h ) ; f o r ( i ; i < F. l e n g t h ; i ++) f o r ( each j i n appmesh. F [ i ]. edge ) F [ i ]. edge. I n s e r t ( j ) ; The vertices, edges, and faces of the clipper mesh are initialized as shown. CVertex ( ) d i s t a n c e = 0 ; v i s i b l e = t r u e ; CEdge ( ) v i s i b l e = t r u e ; CFace ( ) v i s i b l e = t r u e ; The partial constructions are all that is required to start the processes. Other members are appropriately set when needed. 4 Clipping by a Plane The basic structure of the clipping is as shown. i n t CMesh. C l i p ( Plane c l i p p l a n e ) p r o c e s s v e r t i c e s ; // compute d i s t a n c e s to plane, s e t v i s i b i l i t y f l a g s 6

i f ( a l l v e r t i c e s a r e on n o n n e g a t i v e s i d e o f p l a n e ) r e t u r n +1; // no c l i p p i n g o c c u r s i f ( a l l v e r t i c e s a r e on n o n p o s i t i v e s i d e o f p l a n e ) r e t u r n 1; // e v e r y t h i n g i s c l i p p e d // mesh s t r a d d l e s t h e p l a n e ; some on p o s i t i v e s i d e, some on n e g a t i v e s i d e p r o c e s s e d g e s ; p r o c e s s f a c e s ; r e t u r n 0 ; Each of the processing phases is discussed below. 4.1 Vertex Processing The vertex processing is given by the following simple code. The epsilon value is a small positive number and is used to avoid large amounts of edge clipping when vertices are nearly on the plane. // compute s i g n e d d i s t a n c e s from v e r t i c e s to p l a n e i n t p o s i t i v e = 0, n e g a t i v e = 0 ; f o r ( i n t i = 0 ; i < V. l e n g t h ; i ++) i f ( V [ i ]. v i s i b l e ) V [ i ]. d i s t a n c e = Dot ( c l i p p l a n e. N, V [ i ]. p o i n t ) c l i p p l a n e. c ; i f ( V [ i ]. d i s t a n c e >= e p s i l o n ) p o s i t i v e ++; e l s e i f ( V [ i ]. d i s t a n c e <= e p s i l o n ) n e g a t i v e ++; V [ i ]. v i s i b l e = f a l s e ; e l s e // p o i n t on t h e p l a n e w i t h i n f l o a t i n g p o i n t t o l e r a n c e V [ i ]. d i s t a n c e = 0 ; i f ( n e g a t i v e == 0 ) // a l l v e r t i c e s on n o n n e g a t i v e s i d e, no c l i p p i n g r e t u r n +1; i f ( p o s i t i v e == 0 ) // a l l v e r t i c e s on n o n p o s i t i v e s i d e, e v e r y t h i n g c l i p p e d r e t u r n 1; 4.2 Edge Processing The edge processing is also relatively simple and just compares the signed distances of the vertex end points to zero and takes the appropriate action with the edge. f o r ( i n t i = 0 ; i < E. l e n g t h ; i ++) 7

i f ( E [ i ]. v i s i b l e ) f l o a t d0 = V [ E [ i ]. v e r t e x [ 0 ] ], d1 = V [ E [ i ]. v e r t e x [ 1 ] ] ; i f ( d0 <= 0 && d1 <= 0 ) // edge i s c u l l e d, remove edge from f a c e s s h a r i n g i t f o r ( each j i n E [ i ]. f a c e ) F [ j ]. edge. Remove ( i ) ; i f ( F [ j ]. edge. empty ( ) ) F [ j ]. v i s i b l e = f a l s e ; E [ i ]. v i s i b l e = f a l s e ; continue ; i f ( d0 >= 0 && d1 >= 0 ) // edge i s on n o n n e g a t i v e s i d e, f a c e s r e t a i n t h e edge continue ; // The edge i s s p l i t by t h e p l a n e. Compute t h e p o i n t o f i n t e r s e c t i o n. // I f t h e o l d edge i s <V0, V1> and I i s t h e i n t e r s e c t i o n p o i n t, t h e new // edge i s <V0, I> when d0 > 0 or <I, V1> when d1 > 0. f l o a t t = d0 /( d0 d1 ) ; P o i n t i n t e r s e c t = (1 t ) V [ E [ i ]. v e r t e x [ 0 ] ] + t V [ E [ i ]. v e r t e x [ 1 ] ] ; i n d e x = V. l e n g t h ; V. Append ( i n t e r s e c t ) ; i f ( d0 > 0 ) E [ i ]. v e r t e x [ 1 ] = i n d e x ; e l s e E [ i ]. v e r t e x [ 0 ] = i n d e x ; 4.3 Face Processing The face processing is the most complicated of the phases to implement. // p r o c e s s t h e f a c e s f o r ( i n t i = 0 ; i < F. l e n g t h ; i ++) i f ( F [ i ]. v i s i b l e ) // The edge i s c u l l e d. I f t h e edge i s e x a c t l y on t h e c l i p // plane, i t i s p o s s i b l e t h a t a v i s i b l e t r i a n g l e s h a r e s i t. // The edge w i l l be re added d u r i n g t h e f a c e l o o p. f o r ( each j i n F [ i ]. edge ) V [ E [ j ]. v e r t e x [ 0 ] ]. o c c u r s = 0 ; V [ E [ j ]. v e r t e x [ 1 ] ]. o c c u r s = 0 ; i n t s t a r t, f i n a l ; i f ( G e t O p e n P o l y l i n e ( F [ i ], s t a r t, f i n a l ) ) // p o l y l i n e i s open, c l o s e i t CEdge closeedge ; i n t e i n d e x = E. l e n g t h ; E. Append ( c l o s e E d g e ) ; c l o s e E d g e. v e r t e x [ 0 ] = s t a r t ; 8

c l o s e E d g e. v e r t e x [ 1 ] = f i n a l ; c l o s e E d g e. f a c e. I n s e r t ( i ) ; F [ i ]. edge. I n s e r t ( e i n d e x ) ; The detection of an open polyline and the subsequent determination of the vertex indices of the end points is given below. b o o l e a n CMesh. G e t O p e n P o l y l i n e ( CFace F, i n t& s t a r t, i n t& f i n a l ) // Count t h e number o f o c c u r r e n c e s o f each v e r t e x i n t h e p o l y l i n e. The // r e s u l t i n g o c c u r s v a l u e s must be 1 o r 2. f o r ( each j i n F. edge ) V [ E [ j ]. v e r t e x [ 0 ] ]. o c c u r s ++; V [ E [ j ]. v e r t e x [ 1 ] ]. o c c u r s ++; // d e t e r m i n e i f t h e p o l y l i n e i s open s t a r t = 1; f i n a l = 1; f o r ( each j i n F. edge ) i n t i 0 = E [ j ]. v e r t e x [ 0 ], i 1 = E [ j ]. v e r t e x [ 1 ] ; i f ( V [ i 0 ]. o c c u r s == 1 ) i f ( s t a r t == 1 ) s t a r t = i 0 ; e l s e i f ( f i n a l == 1 ) f i n a l = i 0 ; i f ( V [ i 1 ]. o c c u r s == 1 ) i f ( s t a r t == 1 ) s t a r t = i 1 ; e l s e i f ( f i n a l == 1 ) f i n a l = i 1 ; r e t u r n s t a r t!= 1; 5 Conversion Back to an Application Mesh At first glance, the conversion from a clipper mesh back to an application mesh might appear straightforward. In fact you might think that it is similar to the initialization of the clipper mesh. This is not the case. First, the clipper has stored all the vertices, edges, and faces throughout the process of clipping against a set of planes. Many of these components are no longer visible because they have been clipped away. We do not want these components stored in the application mesh. Second, in many cases the application mesh might also store additional topological information about the relationships between the vertices, edges, and faces. The most common constraint on the application mesh is one of ordering of the face vertices and, by implication, the face edges. The clipper mesh does not maintain these additional relationships because they are not necessary for the clipping algorithm. In this section I present an algorithm that handles the visibility issues by creating an array of visible vertices and an array of visible faces whose vertices are consistently ordered (all faces clockwise or all faces counterclockwise). The assumption is that a AMesh object has a construction mechanism to build all the mesh components given the array of points and the array of consistently ordered faces. In support of this, the AFace and CFace data structures are each given a new member to store the plane of the face. The normal vectors of the planes for the original application mesh are what are used to represent the ordering of the face vertices. The new member type is Plane and the member name is plane. The CMesh initialization code must be slightly modified so that its faces copy the application mesh face planes. 9

CMesh ( ) // p r e v i o u s code t h e same as b e f o r e... F. S e t S i z e ( appmesh. F. l e n g t h ) ; f o r ( i ; i < F. l e n g t h ; i ++) F [ i ]. p l a n e = appmesh. F [ i ]. p l a n e ; f o r ( each j i n appmesh. F [ i ]. edge ) F [ i ]. edge. I n s e r t ( j ) ; The conversion code is as follows. AMesh CMesh. Convert ( ) // c r e a t e a l o o k u p t a b l e f o r t h e v i s i b l e v e r t i c e s a r r a y ( P o i n t ) p o i n t (V. l e n g t h ) ; a r r a y ( i n t ) vmap (V. l e n g t h ) ; vmap. SetAllElementsTo ( 1); // copy t h e v i s i b l e v e r t i c e s i n t o t h e t a b l e f o r ( i = 0 ; i < V. l e n g t h ; i ++) i f ( V [ i ]. v i s i b l e ) vmap [ i ] = p o i n t. l e n g t h ; p o i n t. Append (V [ i ]. p o i n t ) ; // Order t h e v e r t i c e s f o r a l l t h e f a c e s. The o u t p u t a r r a y has a // s e q u e n c e o f s u b a r r a y s, each s u b a r r a y h a v i n g f i r s t e l e m e n t s t o r i n g // t h e number o f v e r t i c e s i n t h e f a c e, t h e r e m a i n i n g e l e m e n t s s t o r i n g // t h e v e r t e x i n d i c e s f o r t h a t f a c e i n t h e c o r r e c t o r d e r. The i n d i c e s // a r e r e l a t i v e to t h e V [ ] a r r a y. a r r a y ( i n t ) f a c e s = GetOrderedFaces ( ) ; // map t h e v e r t e x i n d i c e s to t h o s e o f t h e new t a b l e f o r ( i = 0 ; i < f a c e s. l e n g t h ; / / ) i n t n u m I n d i c e s = f a c e s [ i ] ; i ++; f o r ( j = 0 ; j < n u m I n d i c e s ; j ++) f a c e s [ i ] = vmap [ f a c e s [ i ] ] ; i ++; r e t u r n AMesh ( p o i n t, f a c e s ) ; The face ordering is accomplished by the following code. a r r a y ( i n t ) CMesh. GetOrderedFaces ( ) a r r a y ( i n t ) f a c e s ; f o r ( i = 0 ; i < F. l e n g t h ; i ++) i f ( F [ i ]. v i s i b l e ) // Get t h e o r d e r e d v e r t i c e s o f t h e f a c e. The f i r s t and l a s t // e l e m e n t o f t h e a r r a y a r e t h e same s i n c e t h e p o l y l i n e i s // c l o s e d. a r r a y ( i n t ) v e r t i c e s = G e t O r d e r e d V e r t i c e s ( F [ i ] ) ; f a c e s. Append ( v e r t i c e s. l e n g t h 1); // The c o n v e n t i o n i s t h a t t h e v e r t i c e s s h o u l d be c o u n t e r c l o c k w i s e 10

// o r d e r e d when viewed from t h e n e g a t i v e s i d e o f t h e p l a n e o f t h e // f a c e. I f you need t h e o p p o s i t e c o n v e n t i o n, s w i t c h t h e // i n e q u a l i t y i n t h e i f e l s e s t a t e m e n t. i f ( Dot ( F [ i ]. p l a n e. N, GetNormal ( v e r t i c e s ) ) > 0 ) // c l o c k w i s e, need to swap f o r ( j = v e r t i c e s. l e n g t h 2; j >= 0 ; j ) f a c e s. Append ( v e r t i c e s [ j ] ) ; e l s e // c o u n t e r c l o c k w i s e f o r ( j = 0 ; j <= v e r t i c e s. l e n g t h 2; j ++) f a c e s. Append ( v e r t i c e s [ j ] ) ; r e t u r n f a c e s ; The vertex ordering requires some type of sorting. The algorithm here uses a bubble-like sort, a reasonable choice if the faces have a small number of edges. If the number of edges is quite large in an application, you should consider adding a faster sort (probably switching between bubble sort and the faster sort based on number of edges). v o i d CMesh. G e t O r d e r e d V e r t i c e s ( CFace F ) // copy edge i n d i c e s i n t o c o n t i g u o u s memory f o r s o r t i n g a r r a y ( i n t ) e d g e s ( F. edge. s i z e ) ; i = 0 ; f o r ( each j i n F. edge ) e d g e s [ i ++] = j ; // b u b b l e s o r t to a r r a n g e e d g e s i n c o n t i g u o u s o r d e r f o r ( i 0 = 0, i 1 = 1, c h o i c e = 1 ; i 1 < e d g e s. l e n g t h 1; i 0 = i1, i 1 ++) i n t c u r r e n t = E [ e d g e s [ i 0 ] ]. v e r t e x [ c h o i c e ] ; f o r ( j = i 1 ; j < e d g e s. l e n g t h ; j ++) Edge& rketemp = E [ e d g e s [ j ] ] ; i f ( E [ e d ges [ j ] ]. v e r t e x [ 0 ] == c u r r e n t ) Swap ( e d g e s [ i 1 ], e d g e s [ j ] ) ; c h o i c e = 1 ; break ; i f ( E [ e d ges [ j ] ]. v e r t e x [ 1 ] == c u r r e n t ) Swap ( e d g e s [ i 1 ], e d g e s [ j ] ) ; c h o i c e = 0 ; break ; a r r a y ( i n t ) v e r t i c e s ( e d g e s. l e n g t h +1); // add t h e f i r s t two v e r t i c e s v e r t i c e s. Append (E [ e d g e s [ 0 ] ]. v e r t e x [ 0 ] ) ; v e r t i c e s. Append (E [ e d g e s [ 0 ] ]. v e r t e x [ 1 ] ) ; // add t h e r e m a i n i n g v e r t i c e s f o r ( i = 1 ; i < edge. l e n g t h ; i ++) Edge& rke = m akedge [ aieordered [ i ] ] ; i f ( E [ e d g e s [ i ] ]. v e r t e x [ 0 ] == v e r t i c e s [ i ] ) v e r t i c e s [ i +1] = E [ e d g e s [ i ] ]. v e r t e x [ 1 ] ; e l s e v e r t i c e s [ i +1] = E [ e d g e s [ i ] ]. v e r t e x [ 0 ] ; 11

r e t u r n v e r t i c e s ; Finally, a numerically robust method for computing the normal from an ordered set of vertices is given below. The function relies on the fact that the first and last indices of the input array are the same. P o i n t CMesh. GetNormal ( a r r a y ( i n t ) v e r t i c e s ) P o i n t normal ( 0, 0, 0 ) ; f o r ( i = 0 ; i <= v e r t i c e s. l e n g t h 2; i ++) normal += C r o s s (V [ v e r t i c e s [ i ] ], V [ v e r t i c e s [ i + 1 ] ] ) ; normal. N o r m a l i z e ( ) ; // make t h e normal u n i t l e n g t h r e t u r n normal ; 6 Support for Closing a Clipped Mesh For purposes of display, once the mesh is clipped and converted back to the form the application requires, no other work must be done other than sending the faces through the rendering system. For purposes of intersection of closed meshes and planes (or other closed meshes), it is necessary to close the clipped mesh by adding faces whose boundaries are the polygons of intersection with the clipping plane. The face processing pseudocode listed earlier needs to be modified to support this. 6.1 Closing a Clipped Convex Polyhedron When a convex polyhedron is split by a plane, the intersection of the polyhedron and the plane is a convex polygon. The portion of the original convex polyhedron on the nonnegative side of the plane has a hole in it, but the convex polygon of intersection bounds a face that is used to plug the hole. Only a minor modification is required to the face processing code. // The mesh s t r a d d l e s t h e p l a n e. A new convex p o l y g o n a l f a c e w i l l be // g e n e r a t e d. Add i t now and i n s e r t e d g e s when t h e y a r e v i s i t e d. CFace c l o s e F a c e ; c l o s e F a c e. p l a n e = c l i p p l a n e ; i n t f i n d e x = F. l e n g t h ; F. Append ( c l o s e F a c e ) ; f o r ( i n t i = 0 ; i < F. l e n g t h ; i ++) i f ( F [ i ]. v i s i b l e ) // p r e v i o u s code t h e same as b e f o r e... i n t s t a r t, f i n a l ; i f ( G e t O p e n P o l y l i n e ( F [ i ], s t a r t, f i n a l ) ) // p o l y l i n e i s open, c l o s e i t CEdge closeedge ; i n t e i n d e x = E. l e n g t h ; E. Append ( c l o s e E d g e ) ; c l o s e E d g e. v e r t e x [ 0 ] = s t a r t ; c l o s e E d g e. v e r t e x [ 1 ] = f i n a l ; c l o s e E d g e. f a c e. I n s e r t ( i ) ; F [ i ]. edge. I n s e r t ( e i n d e x ) ; 12

// t h e new l i n e s o f code c l o s e E d g e. f a c e. I n s e r t ( f i n d e x ) ; c l o s e F a c e. edge. I n s e r t ( e i n d e x ) ; Assuming the modifications have been added to the face processing code, the pseudocode for clipping a convex polyhedron (an AMesh object) against a plane is ConvexPolyhedron ConvexPolyhedron. C l i p ( Plane plane ) CMesh c l i p p e r ( s e l f ) ; i n t s i d e = k C l i p p e r. C l i p ( r k P l a n e ) ; i f ( s i d e == +1 ) // p o l y h e d r o n on n o n n e g a t i v e s i d e o f plane, n o t h i n g c l i p p e d r e t u r n s e l f ; i f ( s i d e == 1 ) // p o l y h e d r o n on n o n p o s i t i v e s i d e o f plane, c l i p a l l r e t u r n n u l l ; // p o l y h e d r o n s p l i t by plane, c o n v e r t c l i p mesh to p o l y h e d r o n r e t u r n c l i p p e r. Convert ( ) ; The pseudocode for intersection of two convex polyhedra is ConvexPolyhedron ConvexPolyhedron. I n t e r s e c t i o n ( ConvexPolyhedron p o l y ) CMesh c l i p p e r ( s e l f ) ; f o r ( i = 0 ; i < p o l y. F. l e n g t h ; i ++) i f ( k C l i p p e r. C l i p ( p o l y. F [ i ]. p l a n e ) == 1 ) // p o l y h e d r a do not i n t e r s e c t r e t u r n n u l l ; // p o l y h e d r a do i n t e r s e c t, c o n v e r t c l i p mesh to p o l y h e d r o n r e t u r n c l i p p e r. Convert ( ) ; 6.2 Closing a Clipped Closed Polyhedron If the polyhedron is a closed mesh, but not convex, the intersection of the polyhedron and plane results in a disjoint collection of polygons and/or line segments. The original face processing code also requires modification for this case. // The mesh s t r a d d l e s t h e p l a n e. J u s t s t o r e any e d g e s t h a t a r e used to c l o s e // t h e non p l a n a r convex p o l y g o n f a c e s and p r o c e s s them a f t e r t h i s l o o p. a r r a y ( CEdge ) e d g e s ; f o r ( i = 0 ; i < F. l e n g t h ; i ++) i f ( F [ i ]. v i s i b l e ) 13

// p r e v i o u s code t h e same as b e f o r e... i n t s t a r t, f i n a l ; i f ( G e t O p e n P o l y l i n e ( F [ i ], s t a r t, f i n a l ) ) // p o l y l i n e i s open, c l o s e i t CEdge closeedge ; i n t e i n d e x = E. l e n g t h ; E. Append ( c l o s e E d g e ) ; c l o s e E d g e. v e r t e x [ 0 ] = s t a r t ; c l o s e E d g e. v e r t e x [ 1 ] = f i n a l ; c l o s e E d g e. f a c e. I n s e r t ( i ) ; F [ i ]. edge. I n s e r t ( e i n d e x ) ; // t h e new l i n e o f code e d g e s. Append ( e i n d e x ) ; // e x t r a c t t h e r e l e v a n t p o l y g o n f a c e s from t h e edge s e t a r r a y ( CFace ) f a c e s = E x t r a c t F a c e s ( e d g e s ) ; i n t f i n d e x = F. l e n g t h ; f o r ( i = 0 ; i < f a c e s. l e n g t h ; i ++, f i n d e x ++) // c o n n e c t t h e f a c e to each edge o f t h e e x t r a c t e d f a c e f o r ( each j i n f a c e s [ i ]. edge ) E [ j ]. f a c e. I n s e r t ( f i n d e x ) ; // add t h e f a c e to t h e c l i p mesh F. Append ( f a c e s [ i ] ) ; The function ExtractFaces processed the edges on the clip plane to find all the connected components. Isolated line segments are ignored since they represent the polyhedron just touching the clip plane along that edge without crossing through the plane. Care must be taken to handle polygons such as a figure-eight where at least one vertex is shared by more than two edges. Such structures need to be further decomposed into simple polygons. An implementation of ExtractFaces will have the flavor of both functions GetOpenPolyline and GetOrderedVertices. Essentially you build an abstract undirected graph for the edges and find all connected components of that graph. 14