break_wires_at_point(): oblique lines can be cut at any point, the break point will be aligned to the snap value and broken wires are slightly changed to land on this new point.

This commit is contained in:
stefan schippers 2023-09-22 03:45:09 +02:00
parent f0c83e72b4
commit 5181ca77e6
2 changed files with 47 additions and 4 deletions

View File

@ -398,19 +398,61 @@ static int touches_inst_pin(double x, double y, int inst)
return touches;
}
/* return 2 if x0, y0 is on the segment
* return 1 if x0, y0 is less than cadsnap (10) from the segment
* In this case x0, y0 are reset to the closest point on the segment */
static int closest_point_calculation(double x1, double y1, double x2, double y2, double *x0, double *y0)
{
double projection, sq_distance, x3, y3;
double cs = tclgetdoublevar("cadsnap"), sq_cs;
int ret = 0;
sq_cs = cs * cs; /* get squared value to compare with squared distance */
if(x1 == x2 && y1 == y2) {
x3 = x1;
y3 = y1;
} else {
projection = (x2 - x1) * (*x0 - x1) + (y2 - y1) * (*y0 - y1);
projection /= (x2 - x1) * ( x2 - x1) + (y2 - y1) * (y2 - y1);
x3 = x1 + projection * (x2 - x1);
y3 = y1 + projection * (y2 - y1);
}
sq_distance = (*x0 - x3) * (*x0 - x3) + (*y0 - y3) * (*y0 - y3);
if(x3 >= x1 && x3 <= x2) { /* point is within x1,y1 - x2,y2 */
if(sq_distance == 0) ret = 2;
else if(sq_distance < sq_cs) ret = 1;
}
dbg(0, "x3 = %g y3=%g dist=%g ret=%d\n", x3, y3, sqrt(sq_distance), ret);
if(touch(x1, y1, x2, y2, x3, y3)) dbg(0, "touches\n");
if(ret == 1) {
*x0 = my_round(x3 / cs) * cs;
*y0 = my_round(y3 / cs) * cs;
}
return ret;
}
void break_wires_at_point(double x0, double y0)
{
int i, sqx, sqy;
int r, i, sqx, sqy;
Wireentry *wptr;
int changed=0;
double x1, y1, x2, y2;
dbg(1, "break_wires_at_pins(): processing pin %g %g\n", x0, y0);
get_square(x0, y0, &sqx, &sqy);
for(wptr=xctx->wire_spatial_table[sqx][sqy]; wptr; wptr=wptr->next) {
i = wptr->n;
if( touch(xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2, x0,y0) ) {
if( (x0!=xctx->wire[i].x1 && x0!=xctx->wire[i].x2) ||
(y0!=xctx->wire[i].y1 && y0!=xctx->wire[i].y2) ) {
x1 = xctx->wire[i].x1;
y1 = xctx->wire[i].y1;
x2 = xctx->wire[i].x2;
y2 = xctx->wire[i].y2;
r = closest_point_calculation(x1, y1, x2, y2, &x0, &y0);
if( r == 1 || touch(x1, y1, x2, y2, x0,y0) ) {
if( (x0 != x1 && x0 != x2) ||
(y0 != y1 && y0 != y2) ) {
dbg(1, "break_wires_at_point(): processing wire %d: %g %g %g %g\n",
i, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2);
if(!changed) { xctx->push_undo(); changed=1;}

View File

@ -349,6 +349,7 @@ extern char win_temp_dir[PATH_MAX];
#define CLIP(x,a,b) (((x) < (a)) ? (a) : ((x) > (b)) ? (b) : (x))
#define MINOR(a,b) ( (a) <= (b) ? (a) : (b) )
#define MAJOR(a,b) ( (a) >= (b) ? (a) : (b) )
/* "show_label" type symbols are used for any type of symbol that
* must be automatically highlighted by attached nets