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 ab`

static 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 vertices`

int 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 shape

cpVect p = cpv(x, y);

cpPointQueryInfo info;

cpShapePointQuery(cpshape, p, &info);

// this point is on the closest surface

cpVect 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.