/* vertex_octree.c: Octrees containing BREP_VERTEX structs for fast * vertex lookup. */ #include "vertex_octree.h" #include "brep.h" #include "private.h" /* a user specified routine to compare the client data of two vertices */ static BREP_COMPARE_FUNC brep_vertex_clientdata_compare = (BREP_COMPARE_FUNC)NULL, brep_vertex_location_compare = (BREP_COMPARE_FUNC)NULL; /* Set a routine to compare the BREP_VERTEX client data for two vertices. * BrepSetVertexCompareRoutine() returns the previously installed compare * routine so it can be restored when necessary. */ BREP_COMPARE_FUNC BrepSetVertexCompareRoutine(BREP_COMPARE_FUNC routine) { BREP_COMPARE_FUNC oldroutine = brep_vertex_clientdata_compare; brep_vertex_clientdata_compare = routine; return oldroutine; } /* Set a routine to compare the location of two BREP_VERTEXes. * BrepSetVertexCompareLocationRoutine() returns the previously installed compare * routine so it can be restored when necessary. */ BREP_COMPARE_FUNC BrepSetVertexCompareLocationRoutine(BREP_COMPARE_FUNC routine) { BREP_COMPARE_FUNC oldroutine = brep_vertex_location_compare; brep_vertex_location_compare = routine; return oldroutine; } /* compares two vertices. Calls a user installed routine to compare the * client data of two vertices. The routine to be used is specified with * BrepSetVertexCompareRoutine() in brep.h */ int BrepVertexCompare(BREP_VERTEX *v1, BREP_VERTEX *v2) { if (!brep_vertex_clientdata_compare) BrepFatal(v1->client_data, "BrepVertexCompare", "no user specified vertex compare routine!"); return brep_vertex_clientdata_compare(v1->client_data, v2->client_data); } /* Calls a user installed routine to compare the location * of two vertices. The routine to be used is specified with * BrepSetVertexCompareLocationRoutine() in brep.h */ int BrepVertexCompareLocation(BREP_VERTEX *v1, BREP_VERTEX *v2) { if (!brep_vertex_location_compare) BrepFatal(v1->client_data, "BrepVertexCompareLocation", "no user specified routine for comparing the location of two vertices"); return brep_vertex_location_compare(v1->client_data, v2->client_data); } /* Looks up a vertex in the vertex octree, return NULL if not found */ BREP_VERTEX *BrepFindVertex(void *vertex_data, BREP_VERTEX_OCTREE *vertices) { BREP_VERTEX vert; vert.client_data = vertex_data; return BrepVertexOctreeFind(vertices, &vert); } /* attaches an existing BREP_VERTEX to the vertex octree */ void BrepAttachVertex(BREP_VERTEX *vertex, BREP_VERTEX_OCTREE **vertices) { *vertices = BrepVertexOctreeAdd(*vertices, vertex); } /* remove a BREP_VERTEX from the vertex octree */ void BrepReleaseVertex(BREP_VERTEX *vertex, BREP_VERTEX_OCTREE **vertices) { BrepError(vertex->client_data, "BrepReleaseVertex", "not yet implemented"); } /* Creates a vertex and installs it in the vertex octree. */ BREP_VERTEX *BrepInstallVertex(void *vertex_data, BREP_VERTEX_OCTREE **vertices) { BREP_VERTEX *vert; vert = BrepCreateVertex(vertex_data); *vertices = BrepVertexOctreeAdd(*vertices, vert); return vert; } /* creates a new vertex octree: currently only returns a NULL pointer */ BREP_VERTEX_OCTREE *BrepCreateVertexOctree(void) { return BrepVertexOctreeCreate(); } /* Destroys a vertex octree, does not destroy the vertices referenced in * the octree. */ void BrepDestroyVertexOctree(BREP_VERTEX_OCTREE *vertices) { BrepVertexOctreeDestroy(vertices); } /* calls func for each BREP_VERTEX in the octree */ void BrepIterateVertices(BREP_VERTEX_OCTREE *vertices, void (*func)(BREP_VERTEX *)) { BrepVertexOctreeIterate(vertices, func); } /* destroys all the vertices and the vertex octree, same as * BrepIterateVertices(vertices, BrepDestroyVertex) followed by * BrepDestroyvertexOctree(). */ void BrepDestroyVertices(BREP_VERTEX_OCTREE *vertices) { BrepIterateVertices(vertices, BrepDestroyVertex); BrepDestroyVertexOctree(vertices); } /* Looks up the first vertex in the vertex octree at the location as specified in the * given vertex data. There may be multiple vertices at the same location (e.g. having * a different normal and/or a different name). These vertices should normally be * stored as a suboctree of the octree containing all vertices. A pointer to the * top of this suboctree is returned if there are vertices at the given location. * NULL is returned if there are no vertices at the given location. */ BREP_VERTEX_OCTREE *BrepFindVertexAtLocation(void *vertex_data, BREP_VERTEX_OCTREE *vertices) { BREP_VERTEX vert; vert.client_data = vertex_data; return (BREP_VERTEX_OCTREE *)OctreeFindSubtree((OCTREE *)vertices, (void *)&vert, (int (*)(void *, void *))BrepVertexCompareLocation); } /* Iterators over all vertices in the given vertex octree that are at the same * location as specified in the vertex data. */ void BrepIterateVerticesAtLocation(void *vertex_data, BREP_VERTEX_OCTREE *vertices, void (*routine)(BREP_VERTEX *vertex)) { BREP_VERTEX_OCTREE *vertoct; vertoct = BrepFindVertexAtLocation(vertex_data, vertices); OctreeIterate((OCTREE *)vertoct, (void (*)(void *))routine); } /* 1 extra parameter */ void BrepIterateVerticesAtLocation1A(void *vertex_data, BREP_VERTEX_OCTREE *vertices, void (*routine)(BREP_VERTEX *vertex, void *parm), void *parm) { BREP_VERTEX_OCTREE *vertoct; vertoct = BrepFindVertexAtLocation(vertex_data, vertices); OctreeIterate1A((OCTREE *)vertoct, (void (*)(void *, void *))routine, parm); } /* 2 extra parameters */ void BrepIterateVerticesAtLocation2A(void *vertex_data, BREP_VERTEX_OCTREE *vertices, void (*routine)(BREP_VERTEX *vertex, void *parm1, void *parm2), void *parm1, void *parm2) { BREP_VERTEX_OCTREE *vertoct; vertoct = BrepFindVertexAtLocation(vertex_data, vertices); OctreeIterate2A((OCTREE *)vertoct, (void (*)(void *, void *, void *))routine, parm1, parm2); } static void BrepIterateWingsWithVertices(BREP_VERTEX *v2, BREP_VERTEX_OCTREE *v1octree, void (*func)(BREP_WING *)) { OctreeIterate2A((OCTREE *)v1octree, (void (*)(void *, void *, void *))BrepIterateWingsWithVertex, (void *)v2, (void *)func); } /* Iterator over all edge-wings between vertices at the locations specified by * v1data and v2data. */ void BrepIterateWingsBetweenLocations(void *v1data, void *v2data, BREP_VERTEX_OCTREE *vertices, void (*func)(BREP_WING *)) { BREP_VERTEX_OCTREE *v1octree, *v2octree; v1octree = BrepFindVertexAtLocation(v1data, vertices); if (!v1octree) return; v2octree = BrepFindVertexAtLocation(v2data, vertices); if (!v2octree) return; OctreeIterate2A((OCTREE *)v2octree, (void (*)(void *, void *, void *))BrepIterateWingsWithVertices, (void *)v1octree, (void *)func); }