I need a function that returns the distance between a point and the edge of
a smd pad. If the point is inside the pad, I'd want it to return 0.
Anyone tried doing that? I want the roundness of the smd to be a part of the
function too.
I need a function that returns the distance between a point and the edge of
a smd pad. If the point is inside the pad, I'd want it to return 0.
Anyone tried doing that? I want the roundness of the smd to be a part of the
function too.
Morten Leikvoll wrote on Wed, 16 December 2009 03:52
I need a function that returns the distance between a point and the
edge of
a smd pad. If the point is inside the pad, I'd want it to return 0.
Anyone tried doing that? I want the roundness of the smd to be a part
of the
function too.
That's going to be a little tricky since you have to mimic the Eagle SMD
roundness algorithm. The UL_SMD structure only gives you the rectangular
size and roundness as a separate parameter. There are various ways the
roundess parameter could be used to blend between a rectangle and a elipse,
and I don't remember seeing documentation on how exactly Eagle does it.
On the other hand, maybe it doesn't need to be that accurate and you can
probably get a good idea of their method with a little experimentation.
Once you know how to compute the pad shape, the brute force way to do what
you ask would be to turn it into a polygon and perform a normal in/out
function. At least you know the polygon will be convex.
However, it still sounds like you're stuck in a rut having made the wrong
choice several layers up and now requiring ever more elaborate schemes to
work around the problem, when the right answer is to not be in this
situation in the first place. Step back and explain the original problem
you are trying to solve.
--
Browser access to CadSoft Support Forums at http://www.eaglecentral.ca
"Olin Lathrop" <eagle@embedinc.com> wrote in message
news:hgap4t$8a5$1@cheetah.cadsoft.de...
That's going to be a little tricky since you have to mimic the Eagle SMD
roundness algorithm. The UL_SMD structure only gives you the rectangular
size and roundness as a separate parameter. There are various ways the
roundess parameter could be used to blend between a rectangle and a
elipse,
and I don't remember seeing documentation on how exactly Eagle does it.
On the other hand, maybe it doesn't need to be that accurate and you can
probably get a good idea of their method with a little experimentation.
Once you know how to compute the pad shape, the brute force way to do what
you ask would be to turn it into a polygon and perform a normal in/out
function. At least you know the polygon will be convex.
However, it still sounds like you're stuck in a rut having made the wrong
choice several layers up and now requiring ever more elaborate schemes to
work around the problem, when the right answer is to not be in this
situation in the first place. Step back and explain the original problem
you are trying to solve.
I know I can do it (gimme a day or two), that is not the problem. I just
didnt want to if anyone else has done it and wanted to share it before I
spend my valuable time.
"Morten Leikvoll" <mleikvol@yahoo.nospam> wrote in message
news:hga74q$qco$1@cheetah.cadsoft.de...
I need a function that returns the distance between a point and the edge of
a smd pad. If the point is inside the pad, I'd want it to return 0.
Anyone tried doing that? I want the roundness of the smd to be a part of
the function too.
If any interest, here is one way of doing it (with printf's for debugging
commented out).
It basicaly turns a SMD into an octacon and 4 corner circles, checks the
distance to each side + circles, then picks the smallest.
Of course I can not guarantee that it will work for all types of smds, but
it should work for the basic ones. It will not detect wether you are inside
the smd or not, just the smallest distance to the smd edge.
-
int Point2PointDistance(real x1, real y1, real x2, real y2)
{
return floor(sqrt( ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2))));
}
int Point2WireDistance(int x, int y, int x1, int y1,int x2,int y2)
{
int Ux = x - x1;
int Uy = y - y1;
int Vx = x2 - x1;
int Vy = y2 - y1;
real dot = 1.0 * Ux * Vx + 1.0 * Uy * Vy;
real len_sq = 1.0 * Vx * Vx + 1.0 * Vy * Vy;
if(len_sq==0) return 0; //line len is 0
real param = dot / len_sq;
if(param<0) param=0;
if(param>1) param=1;
real xx = round(paramVx + 1.0x1);
real yy = round(paramVy + 1.0y1);
return Point2PointDistance(x,y,xx,yy);
}
int smddist(int x,int y,UL_CONTACT C)
{
int dist,t,t1;
int x1,y1,x2,y2;
int xs,ys,ang;
xs=round(C.smd.dx/2);
ys=round(C.smd.dy/2);
ang=C.smd.angle;
int edg=(xs<ys)?xs:ys;//smallest edge
edg=edg-round(1.0edgC.smd.roundness/100);//radius of corner circles
//printf("Checking point (%f %f) distance to smd at (%f
%f)\n",u2mm(x),u2mm(y),u2mm(C.x),u2mm(C.y));
x1=C.x+round(cos(PIang/180)(xs-edg)-sin(PIang/180)ys); //find dist to
upper wire
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)ys);
x2=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)ys);
y2=C.yround(sin(PIang/180)(-xsedg)+cos(PIang/180)ys);
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
dist=t1;
//printf("\tDist to upper wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
x1=C.x+round(cos(PIang/180)(xs-edg)-sin(PIang/180)(-ys)); //find dist
to lower wire
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)(-ys));
x2=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)(-ys));
y2=C.yround(sin(PIang/180)(-xsedg)+cos(PIang/180)(-ys));
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
if(t1<dist) dist=t1;
//printf("\tDist to lower wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
x1=C.x+round(cos(PIang/180)(-xs)-sin(PIang/180)(ys-edg)); //find dist
to left wire
y1=C.yround(sin(PIang/180)(-xs)cos(PIang/180)(ys-edg));
x2=C.xround(cos(PIang/180)(-xs)-sin(PIang/180)(-ysedg));
y2=C.yround(sin(PIang/180)(-xs)cos(PIang/180)(-ys+edg));
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
if(t1<dist) dist=t1;
//printf("\tDist to left wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
x1=C.x+round(cos(PIang/180)(xs)-sin(PIang/180)(ys-edg)); //find dist to
right wire
y1=C.yround(sin(PIang/180)(xs)cos(PIang/180)(ys-edg));
x2=C.xround(cos(PIang/180)(xs)-sin(PIang/180)(-ysedg));
y2=C.yround(sin(PIang/180)(xs)cos(PIang/180)(-ys+edg));
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
if(t1<dist) dist=t1;
//printf("\tDist to right wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
if(edg)
{
x1=C.x+round(cos(PIang/180)(xs-edg)-sin(PIang/180)(ys-edg)); //circle
in upper right corner
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)(ys-edg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in upper
right corner
//printf("\tDist to upper right corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
x1=C.xround(cos(PIang/180)(xs-edg)-sin(PIang/180)(-ysedg)); //circle
in lower right corner
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)(-ys+edg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in lower
right corner
//printf("\tDist to lower right corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
x1=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)(-ys+edg));
//circle in lower left corner
y1=C.yround(sin(PIang/180)(-xsedg)cos(PIang/180)(-ysedg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in lower
left corner
//printf("\tDist to lower left corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
x1=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)(ys-edg)); //circle
in upper left corner
y1=C.yround(sin(PIang/180)(-xsedg)+cos(PIang/180)(ys-edg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in upper
left corner
//printf("\tDist to upper left corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
}
//printf("\tDistance=%f\n",u2mm(dist));
return dist;
}
I should post this bug warning. The position of the corner circles may be
wrong. They should probably be positioned at xs±edg/2,ys±edg/2 instead of
xs±edg,ys±edg.
"Morten Leikvoll" <mleikvol@yahoo.nospam> wrote in message
news:hh9qlp$6ok$1@cheetah.cadsoft.de...
"Morten Leikvoll" <mleikvol@yahoo.nospam> wrote in message
news:hga74q$qco$1@cheetah.cadsoft.de...
I need a function that returns the distance between a point and the edge
of a smd pad. If the point is inside the pad, I'd want it to return 0.
Anyone tried doing that? I want the roundness of the smd to be a part of
the function too.
If any interest, here is one way of doing it (with printf's for debugging
commented out).
It basicaly turns a SMD into an octacon and 4 corner circles, checks the
distance to each side + circles, then picks the smallest.
Of course I can not guarantee that it will work for all types of smds, but
it should work for the basic ones. It will not detect wether you are
inside the smd or not, just the smallest distance to the smd edge.
--------------
int Point2PointDistance(real x1, real y1, real x2, real y2)
{
return floor(sqrt( ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2))));
}
int Point2WireDistance(int x, int y, int x1, int y1,int x2,int y2)
{
int Ux = x - x1;
int Uy = y - y1;
int Vx = x2 - x1;
int Vy = y2 - y1;
real dot = 1.0 * Ux * Vx + 1.0 * Uy * Vy;
real len_sq = 1.0 * Vx * Vx + 1.0 * Vy * Vy;
if(len_sq==0) return 0; //line len is 0
real param = dot / len_sq;
if(param<0) param=0;
if(param>1) param=1;
real xx = round(paramVx + 1.0x1);
real yy = round(paramVy + 1.0y1);
return Point2PointDistance(x,y,xx,yy);
}
int smddist(int x,int y,UL_CONTACT C)
{
int dist,t,t1;
int x1,y1,x2,y2;
int xs,ys,ang;
xs=round(C.smd.dx/2);
ys=round(C.smd.dy/2);
ang=C.smd.angle;
int edg=(xs<ys)?xs:ys;//smallest edge
edg=edg-round(1.0edgC.smd.roundness/100);//radius of corner circles
//printf("Checking point (%f %f) distance to smd at (%f
%f)\n",u2mm(x),u2mm(y),u2mm(C.x),u2mm(C.y));
x1=C.x+round(cos(PIang/180)(xs-edg)-sin(PIang/180)ys); //find dist to
upper wire
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)ys);
x2=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)ys);
y2=C.yround(sin(PIang/180)(-xsedg)+cos(PIang/180)ys);
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
dist=t1;
//printf("\tDist to upper wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
x1=C.x+round(cos(PIang/180)(xs-edg)-sin(PIang/180)(-ys)); //find dist
to lower wire
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)(-ys));
x2=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)(-ys));
y2=C.yround(sin(PIang/180)(-xsedg)+cos(PIang/180)(-ys));
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
if(t1<dist) dist=t1;
//printf("\tDist to lower wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
x1=C.x+round(cos(PIang/180)(-xs)-sin(PIang/180)(ys-edg)); //find dist
to left wire
y1=C.yround(sin(PIang/180)(-xs)cos(PIang/180)(ys-edg));
x2=C.xround(cos(PIang/180)(-xs)-sin(PIang/180)(-ysedg));
y2=C.yround(sin(PIang/180)(-xs)cos(PIang/180)(-ys+edg));
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
if(t1<dist) dist=t1;
//printf("\tDist to left wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
x1=C.x+round(cos(PIang/180)(xs)-sin(PIang/180)(ys-edg)); //find dist
to right wire
y1=C.yround(sin(PIang/180)(xs)cos(PIang/180)(ys-edg));
x2=C.xround(cos(PIang/180)(xs)-sin(PIang/180)(-ysedg));
y2=C.yround(sin(PIang/180)(xs)cos(PIang/180)(-ys+edg));
t1=Point2WireDistance(x,y,x1,y1,x2,y2);
if(t1<dist) dist=t1;
//printf("\tDist to right wire (%f %f) (%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(x2),u2mm(y2),u2mm(t1));
if(edg)
{
x1=C.x+round(cos(PIang/180)(xs-edg)-sin(PIang/180)(ys-edg)); //circle
in upper right corner
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)(ys-edg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in upper
right corner
//printf("\tDist to upper right corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
x1=C.xround(cos(PIang/180)(xs-edg)-sin(PIang/180)(-ysedg));
//circle in lower right corner
y1=C.yround(sin(PIang/180)(xs-edg)cos(PIang/180)(-ys+edg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in lower
right corner
//printf("\tDist to lower right corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
x1=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)(-ys+edg));
//circle in lower left corner
y1=C.yround(sin(PIang/180)(-xsedg)cos(PIang/180)(-ysedg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in lower
left corner
//printf("\tDist to lower left corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
x1=C.xround(cos(PIang/180)(-xsedg)-sin(PIang/180)(ys-edg));
//circle in upper left corner
y1=C.yround(sin(PIang/180)(-xsedg)+cos(PIang/180)(ys-edg));
t=Point2PointDistance(x,y,x1,y1)-edg; // check dist to circle in upper
left corner
//printf("\tDist to upper left corner circle(%f
%f):%f\n",u2mm(x1),u2mm(y1),u2mm(t));
if(t<dist) dist=t;
}
//printf("\tDistance=%f\n",u2mm(dist));
return dist;
}
"Morten Leikvoll" <mleikvol@yahoo.nospam> wrote in message
news:hh9u0b$hnr$1@cheetah.cadsoft.de...
I should post this bug warning. The position of the corner circles may be
wrong. They should probably be positioned at xs±edg/2,ys±edg/2 instead of
xs±edg,ys±edg.
This was false alarm. I just had my hand written sketch drawn wrong.. The
original function was correct.