/* shell.c: routines for manipulating BREP_SHELLs */ #include "brep.h" #include "private.h" #include "pools.h" #ifndef NOPOOLS static POOL *shellPool = (POOL *)NULL; #define NEWSHELL() (BREP_SHELL *)NewPoolCell(sizeof(BREP_SHELL), 0, "brep shells", &shellPool) #define DISPOSESHELL(ptr) Dispose((unsigned char *)(ptr), &shellPool) #else /* NOPOOLS */ #define NEWSHELL() (BREP_SHELL *)Alloc(sizeof(BREP_SHELL)) #define DISPOSESHELL(ptr) Free((char *)ptr, sizeof(BREP_SHELL)) #endif /* NOPOOLS */ /* callback functions for manipulating BREP_SHELLs */ static BREP_CALLBACK_FUNC brep_close_shell_callback = (BREP_CALLBACK_FUNC)NULL, brep_destroy_shell_callback = (BREP_CALLBACK_FUNC)NULL, brep_create_shell_callback = (BREP_CALLBACK_FUNC)NULL; /* set the CreateShell callback routine */ BREP_CALLBACK_FUNC BrepSetCreateShellCallback(BREP_CALLBACK_FUNC func) { BREP_CALLBACK_FUNC oldfunc = brep_create_shell_callback; brep_create_shell_callback = func; return oldfunc; } /* set the CloseShell callback routine */ BREP_CALLBACK_FUNC BrepSetCloseShellCallback(BREP_CALLBACK_FUNC func) { BREP_CALLBACK_FUNC oldfunc = brep_close_shell_callback; brep_close_shell_callback = func; return oldfunc; } /* set the DestroyShell callback routine */ BREP_CALLBACK_FUNC BrepSetDestroyShellCallback(BREP_CALLBACK_FUNC func) { BREP_CALLBACK_FUNC oldfunc = brep_destroy_shell_callback; brep_destroy_shell_callback = func; return oldfunc; } /* connects the shell to the solid */ void BrepConnectShellToSolid(BREP_SHELL *shell, BREP_SOLID *solid) { shell->solid = solid; if (!solid) return; if (!solid->shells) { /* this is the first shell in the solid */ solid->shells = shell; shell->next = shell->prev = shell; } else { /* not the first shell in the solid */ shell->next = solid->shells; shell->prev = solid->shells->prev; shell->next->prev = shell->prev->next = shell; } } /* creates a new empty shell within the solid */ BREP_SHELL *BrepCreateShell(BREP_SOLID *solid, void *client_data) { BREP_SHELL *shell; shell = NEWSHELL(); shell->faces = (BREP_FACE *)NULL; shell->client_data = client_data; BrepConnectShellToSolid(shell, solid); /* if a CreateShell callback has been specified, call it */ shell->client_data = client_data; if (brep_create_shell_callback) shell->client_data = brep_create_shell_callback(shell); return shell; } /* perform various actions to be performed when a shell has been * completely specified */ void BrepCloseShell(BREP_SHELL *shell) { /* notify the user that the faces of the shell have been completely * specified */ BrepShellIterateFaces(shell, BrepCloseFace); /* if a CloseShell callback has been specified, call it */ if (brep_close_shell_callback) shell->client_data = brep_close_shell_callback(shell); } /* execute func for every face in the shell */ void BrepShellIterateFaces(BREP_SHELL *shell, void (*func)(BREP_FACE *)) { BrepIterate((BREP_RING *)shell->faces, (void (*)(BREP_RING *))func); } void BrepShellIterateFaces1A(BREP_SHELL *shell, void (*func)(BREP_FACE *, void *), void *parm) { BrepIterate1A((BREP_RING *)shell->faces, (void (*)(BREP_RING *, void *))func, parm); } void BrepShellIterateFaces2A(BREP_SHELL *shell, void (*func)(BREP_FACE *, void *, void *), void *parm1, void *parm2) { BrepIterate2A((BREP_RING *)shell->faces, (void (*)(BREP_RING *, void *, void *))func, parm1, parm2); } /* disconnect the shell from the solid */ void BrepDisconnectShellFromSolid(BREP_SHELL *shell) { BREP_SOLID *solid = shell->solid; if (!solid) /* not connected to a solid */ return; if (solid->shells == shell) { /* the shell is the first shell * in the solid */ if (shell->next == shell) /* it is the only shell */ solid->shells = (BREP_SHELL *)NULL; else /* make the next shell the * first shell of the solid */ solid->shells = shell->next; } shell->next->prev = shell->prev; shell->prev->next = shell->next; shell->solid = (BREP_SOLID *)NULL; } /* destroys the faces in a shell */ static void BrepShellDestroyFaces(BREP_FACE *first) { BREP_FACE *face, *prev; if (first) { for (face = first->prev; face != first; face = prev) { prev = face->prev; BrepDestroyFace(face); } BrepDestroyFace(first); } } /* release all memory associated to a shell and its contained faces */ void BrepDestroyShell(BREP_SHELL *shell) { /* inverse actions performed in BrepCreateShell() in reverse order */ /* disconnect the shell from the containing solid */ BrepDisconnectShellFromSolid(shell); /* notify the user that the client_data can be disposed of */ if (brep_destroy_shell_callback) brep_destroy_shell_callback(shell); /* destroy its faces */ BrepShellDestroyFaces(shell->faces); /* dispose of the BREP_SHELL structure itself */ DISPOSESHELL(shell); }