static void cpPolyShapeNearestPointQuery(cpPolyShape *poly, cpVect p, cpNearestPointQueryInfo *info) { int count = poly->numVerts; cpSplittingPlane *planes = poly->tPlanes; cpVect *verts = poly->tVerts; cpVect v0 = verts[count - 1]; cpFloat minDist = INFINITY; cpVect closestPoint = cpvzero; cpBool outside = cpFalse; for(int i=0; i<count; i++) { if(cpSplittingPlaneCompare(planes[i], p) > 0.0f) outside = cpTrue; cpVect v1 = verts[i]; cpVect closest = cpClosetPointOnSegment(p, v0, v1); cpFloat dist = cpvdist(p, closest); if(dist < minDist) { minDist = dist; closestPoint = closest; } v0 = v1; } info->shape = (cpShape *)poly; info->p = closestPoint; // TODO div/0 info->d = (outside ? minDist : -minDist); }
static void cpSegmentShapeNearestPointQuery(cpSegmentShape *seg, cpVect p, cpNearestPointQueryInfo *info) { cpVect closest = cpClosetPointOnSegment(p, seg->ta, seg->tb); cpVect delta = cpvsub(p, closest); cpFloat d = cpvlength(delta); cpFloat r = seg->r; info->shape = (cpShape *)seg; info->p = (d ? cpvadd(closest, cpvmult(delta, r/d)) : closest); info->d = d - r; }
static void cpSegmentShapePointQuery(cpSegmentShape *seg, cpVect p, cpPointQueryInfo *info) { cpVect closest = cpClosetPointOnSegment(p, seg->ta, seg->tb); cpVect delta = cpvsub(p, closest); cpFloat d = cpvlength(delta); cpFloat r = seg->r; cpVect g = cpvmult(delta, 1.0f/d); info->shape = (cpShape *)seg; info->point = (d ? cpvadd(closest, cpvmult(g, r)) : closest); info->distance = d - r; // Use the segment's normal if the distance is very small. info->gradient = (d > MAGIC_EPSILON ? g : seg->n); }
static void cpPolyShapeNearestPointQuery(cpPolyShape *poly, cpVect p, cpNearestPointQueryInfo *info){ int count = poly->numVerts; cpSplittingPlane *planes = poly->tPlanes; cpVect *verts = poly->tVerts; cpFloat r = poly->r; cpVect v0 = verts[count - 1]; cpFloat minDist = INFINITY; cpVect closestPoint = cpvzero; cpVect closestNormal = cpvzero; cpBool outside = cpFalse; for(int i=0; i<count; i++){ if(cpSplittingPlaneCompare(planes[i], p) > 0.0f) outside = cpTrue; cpVect v1 = verts[i]; cpVect closest = cpClosetPointOnSegment(p, v0, v1); cpFloat dist = cpvdist(p, closest); if(dist < minDist){ minDist = dist; closestPoint = closest; closestNormal = planes[i].n; } v0 = v1; } cpFloat dist = (outside ? minDist : -minDist); cpVect g = cpvmult(cpvsub(p, closestPoint), 1.0f/dist); info->shape = (cpShape *)poly; info->p = cpvadd(closestPoint, cpvmult(g, r)); info->d = dist - r; // Use the normal of the closest segment if the distance is small. info->g = (minDist > MAGIC_EPSILON ? g : closestNormal); }
static void cpPolyShapePointQuery(cpPolyShape *poly, cpVect p, cpPointQueryInfo *info){ int count = poly->count; struct cpSplittingPlane *planes = poly->planes; cpFloat r = poly->r; cpVect v0 = planes[count - 1].v0; cpFloat minDist = INFINITY; cpVect closestPoint = cpvzero; cpVect closestNormal = cpvzero; cpBool outside = cpFalse; for(int i=0; i<count; i++){ cpVect v1 = planes[i].v0; outside = outside || (cpvdot(planes[i].n, cpvsub(p,v1)) > 0.0f); cpVect closest = cpClosetPointOnSegment(p, v0, v1); cpFloat dist = cpvdist(p, closest); if(dist < minDist){ minDist = dist; closestPoint = closest; closestNormal = planes[i].n; } v0 = v1; } cpFloat dist = (outside ? minDist : -minDist); cpVect g = cpvmult(cpvsub(p, closestPoint), 1.0f/dist); info->shape = (cpShape *)poly; info->point = cpvadd(closestPoint, cpvmult(g, r)); info->distance = dist - r; // Use the normal of the closest segment if the distance is small. info->gradient = (minDist > MAGIC_EPSILON ? g : closestNormal); }