/* face.c: routines for manipulating BREP_FACEs */ #include "brep.h" #include "private.h" #include "pools.h" #ifndef NOPOOLS static POOL *facePool = (POOL *)NULL; #define NEWFACE() (BREP_FACE *)NewPoolCell(sizeof(BREP_FACE), 0, "brep faces", &facePool) #define DISPOSEFACE(ptr) Dispose((unsigned char *)(ptr), &facePool) #else /* NOPOOLS */ #define NEWFACE() (BREP_FACE *)Alloc(sizeof(BREP_FACE)) #define DISPOSEFACE(ptr) Free((char *)ptr, sizeof(BREP_FACE)) #endif /* NOPOOLS */ /* callback functions for manipulating BREP_FACEs */ static BREP_CALLBACK_FUNC brep_close_face_callback = (BREP_CALLBACK_FUNC)NULL, brep_destroy_face_callback = (BREP_CALLBACK_FUNC)NULL, brep_create_face_callback = (BREP_CALLBACK_FUNC)NULL; /* set the CreateFace callback routine */ BREP_CALLBACK_FUNC BrepSetCreateFaceCallback(BREP_CALLBACK_FUNC func) { BREP_CALLBACK_FUNC oldfunc = brep_create_face_callback; brep_create_face_callback = func; return oldfunc; } /* set the CloseFace callback routine */ BREP_CALLBACK_FUNC BrepSetCloseFaceCallback(BREP_CALLBACK_FUNC func) { BREP_CALLBACK_FUNC oldfunc = brep_close_face_callback; brep_close_face_callback = func; return oldfunc; } /* set the DestroyFace callback routine */ BREP_CALLBACK_FUNC BrepSetDestroyFaceCallback(BREP_CALLBACK_FUNC func) { BREP_CALLBACK_FUNC oldfunc = brep_destroy_face_callback; brep_destroy_face_callback = func; return oldfunc; } /* connects the face to the shell */ void BrepConnectFaceToShell(BREP_FACE *face, BREP_SHELL *shell) { face->shell = shell; if (!shell) return; if (!shell->faces) { /* this is the first face in the shell */ shell->faces = face; face->next = face->prev = face; } else { /* not the first face in the shell */ face->next = shell->faces; face->prev = shell->faces->prev; face->next->prev = face->prev->next = face; } } /* creates a new empty face within the shell */ BREP_FACE *BrepCreateFace(BREP_SHELL *shell, void *client_data) { BREP_FACE *face; face = NEWFACE(); face->outer_contour = (BREP_CONTOUR *)NULL; BrepConnectFaceToShell(face, shell); /* if a CreateFace callback has been specified, call it */ face->client_data = client_data; if (brep_create_face_callback) face->client_data = brep_create_face_callback(face); return face; } /* various actions to be performed when a face is specified completely */ void BrepCloseFace(BREP_FACE *face) { /* notify the user that the contours of the face have been completely * specified */ BrepFaceIterateContours(face, BrepCloseContour); /* if a CloseFace callback has been specified, call it */ if (brep_close_face_callback) face->client_data = brep_close_face_callback(face); } /* execute func for every contour in the face */ void BrepFaceIterateContours(BREP_FACE *face, void (*func)(BREP_CONTOUR *)) { BrepIterate((BREP_RING *)face->outer_contour, (void (*)(BREP_RING *))func); } void BrepFaceIterateContours1A(BREP_FACE *face, void (*func)(BREP_CONTOUR *, void *), void *parm) { BrepIterate1A((BREP_RING *)face->outer_contour, (void (*)(BREP_RING *, void *))func, parm); } void BrepFaceIterateContours2A(BREP_FACE *face, void (*func)(BREP_CONTOUR *, void *, void *), void *parm1, void *parm2) { BrepIterate2A((BREP_RING *)face->outer_contour, (void (*)(BREP_RING *, void *, void *))func, parm1, parm2); } /* disconnect the face from its containing shell */ void BrepDisconnectFaceFromShell(BREP_FACE *face) { BREP_SHELL *shell = face->shell; if (!shell) /* not connected to a shell */ return; if (shell->faces == face) { /* the face is the first face * in the shell */ if (face->next == face) /* it is the only face */ shell->faces = (BREP_FACE *)NULL; else /* make the next face the * first face of the shell */ shell->faces = face->next; } face->next->prev = face->prev; face->prev->next = face->next; face->shell = (BREP_SHELL *)NULL; } /* destroys the contours in a face */ static void BrepFaceDestroyContours(BREP_CONTOUR *first) { BREP_CONTOUR *contour, *prev; if (first) { for (contour = first->prev; contour != first; contour = prev) { prev = contour->prev; BrepDestroyContour(contour); } BrepDestroyContour(first); } } /* release all storage associated with a face and its contours, including * edges and vertices if not used in other faces as well */ void BrepDestroyFace(BREP_FACE *face) { /* inverse actions performed in BrepCreateFace() in reverse order */ /* disconnect the face from the containing shell */ BrepDisconnectFaceFromShell(face); /* notify the user that the client_data can be disposed of */ if (brep_destroy_face_callback) brep_destroy_face_callback(face); /* destroy its contours */ BrepFaceDestroyContours(face->outer_contour); /* dispose of the BREP_FACE structure itself */ DISPOSEFACE(face); }