1 module chipmunk.cpBB; 2 3 import chipmunk.chipmunk_types; 4 import chipmunk.cpVect; 5 6 extern (C): 7 8 struct cpBB 9 { 10 cpFloat l; 11 cpFloat b; 12 cpFloat r; 13 cpFloat t; 14 } 15 16 // these functions are inlined in the chipmunk headers: 17 18 static cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t) 19 { 20 cpBB bb = {l, b, r, t}; 21 return bb; 22 } 23 24 /// Constructs a cpBB centered on a point with the given extents (half sizes). 25 static cpBB 26 cpBBNewForExtents(const cpVect c, const cpFloat hw, const cpFloat hh) 27 { 28 return cpBBNew(c.x - hw, c.y - hh, c.x + hw, c.y + hh); 29 } 30 31 /// Constructs a cpBB for a circle with the given position and radius. 32 static cpBB cpBBNewForCircle(const cpVect p, const cpFloat r) 33 { 34 return cpBBNewForExtents(p, r, r); 35 } 36 37 /// Returns true if @c a and @c b intersect. 38 static cpBool cpBBIntersects(const cpBB a, const cpBB b) 39 { 40 return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t); 41 } 42 43 /// Returns true if @c other lies completely within @c bb. 44 static cpBool cpBBContainsBB(const cpBB bb, const cpBB other) 45 { 46 return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t); 47 } 48 49 /// Returns true if @c bb contains @c v. 50 static cpBool cpBBContainsVect(const cpBB bb, const cpVect v) 51 { 52 return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y); 53 } 54 55 /// Returns a bounding box that holds both bounding boxes. 56 static cpBB cpBBMerge(const cpBB a, const cpBB b){ 57 return cpBBNew( 58 cpfmin(a.l, b.l), 59 cpfmin(a.b, b.b), 60 cpfmax(a.r, b.r), 61 cpfmax(a.t, b.t) 62 ); 63 } 64 65 /// Returns a bounding box that holds both @c bb and @c v. 66 static cpBB cpBBExpand(const cpBB bb, const cpVect v){ 67 return cpBBNew( 68 cpfmin(bb.l, v.x), 69 cpfmin(bb.b, v.y), 70 cpfmax(bb.r, v.x), 71 cpfmax(bb.t, v.y) 72 ); 73 } 74 75 /// Returns the center of a bounding box. 76 static cpVect 77 cpBBCenter(cpBB bb) 78 { 79 return cpvlerp(cpv(bb.l, bb.b), cpv(bb.r, bb.t), 0.5f); 80 } 81 82 /// Returns the area of the bounding box. 83 static cpFloat cpBBArea(cpBB bb) 84 { 85 return (bb.r - bb.l)*(bb.t - bb.b); 86 } 87 88 /// Merges @c a and @c b and returns the area of the merged bounding box. 89 static cpFloat cpBBMergedArea(cpBB a, cpBB b) 90 { 91 return (cpfmax(a.r, b.r) - cpfmin(a.l, b.l))*(cpfmax(a.t, b.t) - cpfmin(a.b, b.b)); 92 } 93 94 /// Returns the fraction along the segment query the cpBB is hit. Returns INFINITY if it doesn't hit. 95 static cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b) 96 { 97 cpVect delta = cpvsub(b, a); 98 cpFloat tmin = -INFINITY, tmax = INFINITY; 99 100 if(delta.x != 0.0f){ 101 cpFloat t1 = (bb.l - a.x)/delta.x; 102 cpFloat t2 = (bb.r - a.x)/delta.x; 103 tmin = cpfmax(tmin, cpfmin(t1, t2)); 104 tmax = cpfmin(tmax, cpfmax(t1, t2)); 105 } 106 107 if(delta.y != 0.0f){ 108 cpFloat t1 = (bb.b - a.y)/delta.y; 109 cpFloat t2 = (bb.t - a.y)/delta.y; 110 tmin = cpfmax(tmin, cpfmin(t1, t2)); 111 tmax = cpfmin(tmax, cpfmax(t1, t2)); 112 } 113 114 if(tmin <= tmax && 0.0f <= tmax && tmin <= 1.0f){ 115 return cpfmax(tmin, 0.0f); 116 } 117 118 return INFINITY; 119 } 120 121 /// Return true if the bounding box intersects the line segment with ends @c a and @c b. 122 static cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b) 123 { 124 return (cpBBSegmentQuery(bb, a, b) != INFINITY); 125 } 126 127 /// Clamp a vector to a bounding box. 128 static cpVect 129 cpBBClampVect(const cpBB bb, const cpVect v) 130 { 131 return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t)); 132 } 133 134 /// Wrap a vector to a bounding box. 135 static cpVect 136 cpBBWrapVect(const cpBB bb, const cpVect v) 137 { 138 cpFloat dx = cpfabs(bb.r - bb.l); 139 cpFloat modx = cpfmod(v.x - bb.l, dx); 140 cpFloat x = (modx > 0.0f) ? modx : modx + dx; 141 142 cpFloat dy = cpfabs(bb.t - bb.b); 143 cpFloat mody = cpfmod(v.y - bb.b, dy); 144 cpFloat y = (mody > 0.0f) ? mody : mody + dy; 145 146 return cpv(x + bb.l, y + bb.b); 147 } 148 149 /// Returns a bounding box offseted by @c v. 150 static cpBB 151 cpBBOffset(const cpBB bb, const cpVect v) 152 { 153 return cpBBNew( 154 bb.l + v.x, 155 bb.b + v.y, 156 bb.r + v.x, 157 bb.t + v.y 158 ); 159 } 160