/* * Copyright (c) 2008-2010 Hypertriton, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Basic operations on general sets of points in R^2 and R^3. */ #include #include /* Preallocate for a given number of points. */ int M_PointSetAlloc2(M_PointSet2 *S, Uint nAlloc) { M_Vector2 *pNew; if (nAlloc <= S->nMax) { return (0); } if ((pNew = TryRealloc(S->p, nAlloc*sizeof(M_Vector2))) == NULL) { return (-1); } S->p = pNew; S->nMax = nAlloc; return (0); } int M_PointSetAlloc3(M_PointSet3 *S, Uint nAlloc) { M_Vector3 *pNew; if (nAlloc <= S->nMax) { return (0); } if ((pNew = TryRealloc(S->p, nAlloc*sizeof(M_Vector3))) == NULL) { return (-1); } S->p = pNew; S->nMax = nAlloc; return (0); } int M_PointSetAlloc2i(M_PointSet2i *S, Uint nAlloc) { int *vNew; if (nAlloc <= S->nMax) return (0); if ((vNew = TryRealloc(S->x, nAlloc*sizeof(int))) == NULL) { return (-1); } S->x = vNew; if ((vNew = TryRealloc(S->y, nAlloc*sizeof(int))) == NULL) { return (-1); } S->y = vNew; S->nMax = nAlloc; return (0); } int M_PointSetAlloc3i(M_PointSet3i *S, Uint nAlloc) { int *vNew; if (nAlloc <= S->nMax) return (0); if ((vNew = TryRealloc(S->x, nAlloc*sizeof(int))) == NULL) { return (-1); } S->x = vNew; if ((vNew = TryRealloc(S->y, nAlloc*sizeof(int))) == NULL) { return (-1); } S->y = vNew; if ((vNew = TryRealloc(S->z, nAlloc*sizeof(int))) == NULL) { return (-1); } S->z = vNew; S->nMax = nAlloc; return (0); } /* Copy the contents a point set. */ int M_PointSetCopy2(M_PointSet2 *D, const M_PointSet2 *S) { if (M_PointSetAlloc2(D, S->n) == -1) { return (-1); } memcpy(D->p, S->p, S->n*sizeof(M_Vector2)); return (0); } int M_PointSetCopy3(M_PointSet3 *D, const M_PointSet3 *S) { if (M_PointSetAlloc3(D, S->n) == -1) { return (-1); } memcpy(D->p, S->p, S->n*sizeof(M_Vector3)); return (0); } int M_PointSetCopy2i(M_PointSet2i *D, const M_PointSet2i *S) { if (M_PointSetAlloc2i(D, S->n) == -1) { return (-1); } memcpy(D->x, S->x, S->n*sizeof(int)); memcpy(D->y, S->y, S->n*sizeof(int)); return (0); } int M_PointSetCopy3i(M_PointSet3i *D, const M_PointSet3i *S) { if (M_PointSetAlloc3i(D, S->n) == -1) { return (-1); } memcpy(D->x, S->x, S->n*sizeof(int)); memcpy(D->y, S->y, S->n*sizeof(int)); memcpy(D->z, S->z, S->n*sizeof(int)); return (0); } /* * Point comparison routines for sort. */ static M_Real ComparePoints2_XY(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector2 *v1 = p1, *v2 = p2; return (Fabs(v2->x - v1->x) <= M_MACHEP) ? (v2->y - v1->y) : (v1->x - v2->x); } static M_Real ComparePoints2_YX(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector2 *v1 = p1, *v2 = p2; return (Fabs(v2->y - v1->y) <= M_MACHEP) ? (v2->x - v1->x) : (v1->y - v2->y); } static M_Real ComparePoints3_XYZ(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector3 *v1 = p1, *v2 = p2; return (Fabs(v2->x - v1->x) <= M_MACHEP) ? (Fabs(v2->y - v1->y) <= M_MACHEP) ? (v2->z - v1->z) : (v1->y - v2->y) : (v1->x - v2->x); } static M_Real ComparePoints3_XZY(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector3 *v1 = p1, *v2 = p2; return (Fabs(v2->x - v1->x) <= M_MACHEP) ? (Fabs(v2->z - v1->z) <= M_MACHEP) ? (v2->y - v1->y) : (v1->z - v2->z) : (v1->x - v2->x); } static M_Real ComparePoints3_YXZ(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector3 *v1 = p1, *v2 = p2; return (Fabs(v2->y - v1->y) <= M_MACHEP) ? (Fabs(v2->x - v1->x) <= M_MACHEP) ? (v2->z - v1->z) : (v1->x - v2->x) : (v1->y - v2->y); } static M_Real ComparePoints3_YZX(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector3 *v1 = p1, *v2 = p2; return (Fabs(v2->y - v1->y) <= M_MACHEP) ? (Fabs(v2->z - v1->z) <= M_MACHEP) ? (v2->x - v1->x) : (v1->z - v2->z) : (v1->y - v2->y); } static M_Real ComparePoints3_ZXY(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector3 *v1 = p1, *v2 = p2; return (Fabs(v2->z - v1->z) <= M_MACHEP) ? (Fabs(v2->x - v1->z) <= M_MACHEP) ? (v2->y - v1->y) : (v1->x - v2->x) : (v1->z - v2->z); } static M_Real ComparePoints3_ZYX(const void *_Nonnull p1, const void *_Nonnull p2) { const M_Vector3 *v1 = p1, *v2 = p2; return (Fabs(v2->z - v1->z) <= M_MACHEP) ? (Fabs(v2->y - v1->y) <= M_MACHEP) ? (v2->x - v1->x) : (v1->y - v2->y) : (v1->z - v2->z); } /* Sort points in R2 by their X or Y coordinates. */ void M_PointSetSort2(M_PointSet2 *P, enum m_point_set_sort_mode2 mode) { switch (mode) { case M_POINT_SET_SORT_XY: M_QSort(P->p, P->n, sizeof(M_Vector2), ComparePoints2_XY); break; case M_POINT_SET_SORT_YX: M_QSort(P->p, P->n, sizeof(M_Vector2), ComparePoints2_YX); break; } } /* Sort points in R3 by their X, Y or Z coordinates. */ void M_PointSetSort3(M_PointSet3 *P, enum m_point_set_sort_mode3 mode) { switch (mode) { case M_POINT_SET_SORT_XYZ: M_QSort(P->p, P->n, sizeof(M_Vector3), ComparePoints3_XYZ); break; case M_POINT_SET_SORT_XZY: M_QSort(P->p, P->n, sizeof(M_Vector3), ComparePoints3_XZY); break; case M_POINT_SET_SORT_YXZ: M_QSort(P->p, P->n, sizeof(M_Vector3), ComparePoints3_YXZ); break; case M_POINT_SET_SORT_YZX: M_QSort(P->p, P->n, sizeof(M_Vector3), ComparePoints3_YZX); break; case M_POINT_SET_SORT_ZXY: M_QSort(P->p, P->n, sizeof(M_Vector3), ComparePoints3_ZXY); break; case M_POINT_SET_SORT_ZYX: M_QSort(P->p, P->n, sizeof(M_Vector3), ComparePoints3_ZYX); break; } }