static int circle2segment(const cpCircleShape *circleShape, const cpSegmentShape *segmentShape, cpContact *con) { cpVect seg_a = segmentShape->ta; cpVect seg_b = segmentShape->tb; cpVect center = circleShape->tc; cpVect seg_delta = cpvsub(seg_b, seg_a); cpFloat closest_t = cpfclamp01(cpvdot(seg_delta, cpvsub(center, seg_a))/cpvlengthsq(seg_delta)); cpVect closest = cpvadd(seg_a, cpvmult(seg_delta, closest_t)); if(circle2circleQuery(center, closest, circleShape->r, segmentShape->r, con)){ cpVect n = con[0].n; // Reject endcap collisions if tangents are provided. if( (closest_t == 0.0f && cpvdot(n, segmentShape->a_tangent) < 0.0) || (closest_t == 1.0f && cpvdot(n, segmentShape->b_tangent) < 0.0) ) return 0; return 1; } else { return 0; } }
static void cpSegmentShapePointQuery(cpSegmentShape *seg, cpVect p, cpPointQueryExtendedInfo *info){ if(!cpBBContainsVect(seg->shape.bb, p)) return; cpVect a = seg->ta; cpVect b = seg->tb; cpVect seg_delta = cpvsub(b, a); cpFloat closest_t = cpfclamp01(cpvdot(seg_delta, cpvsub(p, a))/cpvlengthsq(seg_delta)); cpVect closest = cpvadd(a, cpvmult(seg_delta, closest_t)); cpVect delta = cpvsub(p, closest); cpFloat distsq = cpvlengthsq(delta); cpFloat r = seg->r; if(distsq < r*r){ info->shape = (cpShape *)seg; cpFloat dist = cpfsqrt(distsq); info->d = r - dist; info->n = cpvmult(delta, 1.0/dist); } }