/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "chipmunk/chipmunk_private.h" static inline cpSpatialIndexClass *Klass(); //MARK: Basic Structures typedef struct Bounds { cpFloat min, max; } Bounds; typedef struct TableCell { void *obj; Bounds bounds; } TableCell; struct cpSweep1D { cpSpatialIndex spatialIndex; int num; int max; TableCell *table; }; static inline cpBool BoundsOverlap(Bounds a, Bounds b) { return (a.min <= b.max && b.min <= a.max); } static inline Bounds BBToBounds(cpSweep1D *sweep, cpBB bb) { Bounds bounds = {bb.l, bb.r}; return bounds; } static inline TableCell MakeTableCell(cpSweep1D *sweep, void *obj) { TableCell cell = {obj, BBToBounds(sweep, sweep->spatialIndex.bbfunc(obj))}; return cell; } //MARK: Memory Management Functions cpSweep1D * cpSweep1DAlloc(void) { return (cpSweep1D *)cpcalloc(1, sizeof(cpSweep1D)); } static void ResizeTable(cpSweep1D *sweep, int size) { sweep->max = size; sweep->table = (TableCell *)cprealloc(sweep->table, size*sizeof(TableCell)); } cpSpatialIndex * cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) { cpSpatialIndexInit((cpSpatialIndex *)sweep, Klass(), bbfunc, staticIndex); sweep->num = 0; ResizeTable(sweep, 32); return (cpSpatialIndex *)sweep; } cpSpatialIndex * cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) { return cpSweep1DInit(cpSweep1DAlloc(), bbfunc, staticIndex); } static void cpSweep1DDestroy(cpSweep1D *sweep) { cpfree(sweep->table); sweep->table = NULL; } //MARK: Misc static int cpSweep1DCount(cpSweep1D *sweep) { return sweep->num; } static void cpSweep1DEach(cpSweep1D *sweep, cpSpatialIndexIteratorFunc func, void *data) { TableCell *table = sweep->table; for(int i=0, count=sweep->num; itable; for(int i=0, count=sweep->num; inum == sweep->max) ResizeTable(sweep, sweep->max*2); sweep->table[sweep->num] = MakeTableCell(sweep, obj); sweep->num++; } static void cpSweep1DRemove(cpSweep1D *sweep, void *obj, cpHashValue hashid) { TableCell *table = sweep->table; for(int i=0, count=sweep->num; inum; table[i] = table[num]; table[num].obj = NULL; return; } } } //MARK: Reindexing Functions static void cpSweep1DReindexObject(cpSweep1D *sweep, void *obj, cpHashValue hashid) { // Nothing to do here } static void cpSweep1DReindex(cpSweep1D *sweep) { // Nothing to do here // Could perform a sort, but queries are not accelerated anyway. } //MARK: Query Functions static void cpSweep1DQuery(cpSweep1D *sweep, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data) { // Implementing binary search here would allow you to find an upper limit // but not a lower limit. Probably not worth the hassle. Bounds bounds = BBToBounds(sweep, bb); TableCell *table = sweep->table; for(int i=0, count=sweep->num; itable; for(int i=0, count=sweep->num; ibounds.min < b->bounds.min ? -1 : (a->bounds.min > b->bounds.min ? 1 : 0)); } static void cpSweep1DReindexQuery(cpSweep1D *sweep, cpSpatialIndexQueryFunc func, void *data) { TableCell *table = sweep->table; int count = sweep->num; // Update bounds and sort for(int i=0; ispatialIndex.staticIndex, func, data); } static cpSpatialIndexClass klass = { (cpSpatialIndexDestroyImpl)cpSweep1DDestroy, (cpSpatialIndexCountImpl)cpSweep1DCount, (cpSpatialIndexEachImpl)cpSweep1DEach, (cpSpatialIndexContainsImpl)cpSweep1DContains, (cpSpatialIndexInsertImpl)cpSweep1DInsert, (cpSpatialIndexRemoveImpl)cpSweep1DRemove, (cpSpatialIndexReindexImpl)cpSweep1DReindex, (cpSpatialIndexReindexObjectImpl)cpSweep1DReindexObject, (cpSpatialIndexReindexQueryImpl)cpSweep1DReindexQuery, (cpSpatialIndexQueryImpl)cpSweep1DQuery, (cpSpatialIndexSegmentQueryImpl)cpSweep1DSegmentQuery, }; static inline cpSpatialIndexClass *Klass(){return &klass;}