grbs_addr_t *grbs_path_next(grbs_t *grbs, grbs_2net_t *tn, grbs_addr_t *from, grbs_point_t *to_pt, grbs_arc_dir_t dir);
grbs_addr_t *path_path_next_to_addr(grbs_t *grbs, grbs_2net_t *tn, grbs_addr_t *from, grbs_addr_t *to);
grbs_arc_t *grbs_path_realize(grbs_t *grbs, grbs_2net_t *tn, grbs_addr_t *addr, int reverse);

/* Pretend to realize an addr, but do not make any change to grbs; return 0
   on success, -1 on error (typically collision). This catches collisions
   that would happen on realize when arc radii are bumped and typically the
   outmost arc collides */
int grbs_path_dry_realize(grbs_t *grbs, grbs_2net_t *tn, grbs_addr_t *addr, int reverse);

int grbs_path_validate(grbs_t *grbs, grbs_2net_t *tn, grbs_addr_t *prev_addr, grbs_addr_t *addr, grbs_addr_t *next_addr);

/* Create a fixed line between 2 points without any check */
grbs_line_t *grbs_line_realize(grbs_t *grbs, grbs_2net_t *tn, grbs_point_t *p1, grbs_point_t *p2);

/* rip-up: remove an address or a whole 2net (and free address(es)) */
void grbs_path_remove_addr(grbs_t *grbs, grbs_addr_t *addr);
void grbs_path_remove_arc(grbs_t *grbs, grbs_arc_t *arc);
void grbs_path_remove_2net_addrs(grbs_t *grbs, grbs_2net_t *tn); /* doesn't free tn */
void grbs_path_remove_2net(grbs_t *grbs, grbs_2net_t *tn); /* frees tn */
void grbs_path_remove_line(grbs_t *grbs, grbs_line_t *line);


/* Free all addresses and reset all temporary arcs */
void grbs_path_cleanup_addr(grbs_t *grbs, grbs_addr_t *addr);
void grbs_path_cleanup_by_tn(grbs_t *grbs, grbs_2net_t *tn); /* faster */
void grbs_path_cleanup_all(grbs_t *grbs); /* slower */


/*** Utility ***/
double grbs_self_isect_convex_r2(grbs_t *grbs, grbs_arc_t *arc);
void grbs_inc_ang_update(grbs_t *grbs, grbs_arc_t *a);
grbs_arc_t *grbs_new_sentinel(grbs_t *grbs, grbs_point_t *pt, double sa, double da, int *seg_out);
void grbs_clean_unused_sentinel(grbs_t *grbs, grbs_point_t *pt);
void grbs_del_arc(grbs_t *grbs, grbs_arc_t *arc);

