## how to get closest edge normal?

Official forum for the Chipmunk2D Physics Library.

### how to get closest edge normal?

i know there is a way to get the closest point on the surface of a shape to a specific point inside it using cpPointQueryInfo

but is there an easy way to get the closest edge normal to a point inside a cpshape?
Joseph39

Posts: 10
Joined: Mon Dec 07, 2015 1:50 am

### Re: how to get closest edge normal?

i managed to find a couple of good solutions for my problem after a good night sleep!!
what i needed to find is the closest edge normal to a point inside a cpshape?

so in turn the real question is how to find the closest edge to a point? and from there getting the normal is the easy part

since we can get the nearest point to the surface from cpPointQueryInfo using cpShapePointQuery()

and since the nearest point to the surface lies by default on the closest edge then all what we have to do is get the segment that the point is lying on by iterating thru each pair of vertices (face) and check if the nearest point is on the current pair of vertices (face) being iterated. and if it is then we have our closest edge and all what is left to do is get the normal!

and to check if our nearest point to the surface is lieing on a segment i used this method:

Code: Select all
`// check if point p is on segment abstatic bool onSegment(const Point& a, const Point& b, const Point& p){   if (p.x <= std::max(a.x, b.x) && p.x >= std::min(a.x, b.x) &&      p.y <= std::max(a.y, b.y) && p.y >= std::min(a.y, b.y))      return true;   return false;}`

in total this is how it should look like
Code: Select all
`// get transformed verticesint count = cpPolyShapeGetCount(shape);cpVect* verts = new cpVect[count];for(int i=0;i<count;++i)    verts[i] = cpBodyLocalToWorld(body, cpPolyShapeGetVert(shape, i));// p is our point which is inside the the shapecpVect p = cpv(x, y);cpPointQueryInfo info;cpShapePointQuery(cpshape, p, &info);// this point is on the closest surfacecpVect closestPoint = info.point;// iterate thru each pair of vertices (face)cpVect closestEdgeNormal;for (int i = 0; i < count; i++){   int next = i + 1 < count ? i + 1 : 0;   cpVect a = verts[i];   cpVect b = verts[next];      if (onSegment(a, b, closestPoint))   {      // get perpendicular vector then normalize      closestEdgeNormal = cpvnormalize(cpvperp(cpvsub(a, b)));            //no point in continuing once we found our normal      break;   }}delete[] verts;`

another approach which doesn't use a nearest point on surface would be to find the shortest distance to a particular edge using the dot product like this:

Code: Select all
`cpVect closestEdgeNormal;float shortestDistance = FLT_MAX;for (int i = 0; i < count; i++){   // project the vertex position relative to the position inside onto the edge's normal to find the distance   int next = i + 1 < count ? i + 1 : 0;   cpVect a = verts[i];   cpVect b = verts[next];      cpVect currentNormal = cpvnormalize(cpvperp(cpvsub(a, b)));      float distance = cpvdot(currentNormal, cpvsub(a, p))   if (distance < shortestDistance)   {      // store the shortest distance      shortestDistance = distance;            closestEdgeNormal = currentNormal;   }}// only after the loop ends (all faces looped) then we can get our closest edge normal.`
Joseph39

Posts: 10
Joined: Mon Dec 07, 2015 1:50 am

### Who is online

Users browsing this forum: No registered users and 2 guests