/*  libgrbs - geometric rubber band sketch model
    Copyright (C) 2021  Tibor 'Igor2' Palinkas
    (Supported by NLnet NGI0 PET Fund in 2021)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 31 Milk Street, # 960789 Boston, MA 02196 USA

    Contact:
      Project page: http://repo.hu/projects/libgrbs
      lead developer: http://repo.hu/projects/pcb-rnd/contact.html
*/

void grbs_point_reg(grbs_t *grbs, grbs_point_t *p)
{
	double r = p->copper + p->clearance;
	p->bbox.x1 = p->x - r; p->bbox.y1 = p->y - r;
	p->bbox.x2 = p->x + r; p->bbox.y2 = p->y + r;
	grbs_rtree_insert(&grbs->point_tree, p, &p->bbox);
}

void grbs_point_unreg(grbs_t *grbs, grbs_point_t *p)
{
	grbs_rtree_delete(&grbs->point_tree, p, &p->bbox);
}

/* returns the point an incident line of tn would collide with its endcap
   at tpt (or NULL on no collision) */
static grbs_point_t *grbs_endcap_point_collision(grbs_t *grbs, grbs_2net_t *tn, grbs_point_t *tpt)
{
	grbs_rtree_box_t bbox;
	double bloat = tn->copper + tn->clearance;
	grbs_point_t *pt;
	grbs_rtree_it_t it;

	bbox.x1 = tpt->x - bloat; bbox.y1 = tpt->y - bloat;
	bbox.x2 = tpt->x + bloat; bbox.y2 = tpt->y + bloat;

	for(pt = grbs_rtree_first(&it, &grbs->point_tree, &bbox); pt != NULL; pt = grbs_rtree_next(&it)) {
		double dx = pt->x - tpt->x, dy = pt->y - tpt->y;
		double d2 = dx*dx + dy*dy, maxd = tpt->copper + pt->copper + GRBS_MAX(tpt->clearance, pt->clearance);

		if (d2 > maxd*maxd)
			return pt;
	}

	return NULL;
}

/* returns the arc an incident line of tn would collide with its endcap
   at tpt (or NULL on no collision); arcs going around tpt are ignored */
static grbs_arc_t *grbs_endcap_arc_collision(grbs_t *grbs, grbs_2net_t *tn, grbs_point_t *tpt)
{
	grbs_rtree_box_t bbox;
	double bloat = tn->copper + tn->clearance;
	grbs_arc_t *arc;
	grbs_rtree_it_t it;
	g2d_carc_t outer;
	g2d_vect_t v;

	bbox.x1 = tpt->x - bloat; bbox.y1 = tpt->y - bloat;
	bbox.x2 = tpt->x + bloat; bbox.y2 = tpt->y + bloat;
	v.x = tpt->x; v.y = tpt->y;

	for(arc = grbs_rtree_first(&it, &grbs->arc_tree, &bbox); arc != NULL; arc = grbs_rtree_next(&it)) {
		double r;
		grbs_2net_t *atn;
		g2d_sarc_t sarc;

		if (arc->parent_pt == tpt) continue;
		if (arc->in_use == 0) continue;

		atn = grbs_arc_parent_2net(arc);
		if (atn == tn) continue;

		r = tpt->copper + GRBS_MAX(tpt->clearance, atn->clearance);

		sarc.c.c.x = arc->parent_pt->x;
		sarc.c.c.y = arc->parent_pt->y;
		sarc.c.r = arc->r + atn->copper;
		sarc.c.start = arc->sa; sarc.c.delta = arc->da;
		sarc.s.width = atn->copper;

		g2d_sarc_sides(&sarc, &outer, NULL);
		if (g2d_iscp_carc_circle(&outer, v, r, 0, 0))
			return arc;
	}

	return NULL;
}
