/*-----------------------------------------------------------------------*/ VINDEX next_vertex(GRAPH *g, VINDEX vertex) { GR_ASSERT(is_vertex(g, vertex), "next_vertex is_vertex(g,vertex)\n"); while (1) { if (is_vertex(g, ++vertex)) return vertex; else if (vertex >= GRAPH_vmax(g)) return INVALID_VINDEX; } }
/*----------------------------------------------------------------------*/ EINDEX add_edge(GRAPH *g, VINDEX from, VINDEX to, void *user) { EINDEX new_edge, e2; MEM_POOL *m = GRAPH_m(g); GR_ASSERT(is_vertex(g,from), "add_edge is_vertex(g, from\n"); GR_ASSERT(is_vertex(g,from), "add_edge is_vertex(g, to\n"); /* are there any free edges? */ if(GRAPH_efree(g) == -1) /* grow the edge list if no free edges */ grow_edge(g); /* get a free edge */ new_edge = GRAPH_efree(g); /* reset the free edge pointer */ GRAPH_efree(g)= EDGE_nfrom(&GRAPH_e_i(g,new_edge)); /* store the user information */ EDGE_user(&GRAPH_e_i(g,new_edge)) = user; /* from vertex is = from */ EDGE_from(&GRAPH_e_i(g,new_edge)) = from; /* to vertex is = to */ EDGE_to(&GRAPH_e_i(g,new_edge)) = to; /* incr. from count for from vertex */ VERTEX_fcnt(&GRAPH_v_i(g,from))++; /* incr. to count for to vertex */ VERTEX_tcnt(&GRAPH_v_i(g,to))++; /* incr. total used edge count */ GRAPH_ecnt(g)++; /* set up the list of from edges for the from vertex */ e2 = VERTEX_from(&GRAPH_v_i(g,from)); EDGE_nfrom(&GRAPH_e_i(g,new_edge)) = e2; VERTEX_from(&GRAPH_v_i(g,from)) = new_edge; /* set up the list of to edges for the to vertex */ e2 = VERTEX_to(&GRAPH_v_i(g,to)); EDGE_nto(&GRAPH_e_i(g,new_edge)) = e2; VERTEX_to(&GRAPH_v_i(g,to)) = new_edge; /* set the recursive edge field to be zero */ EDGE_etype(&GRAPH_e_i(g,new_edge)) = 0; return new_edge; }
/*---------------------------------------------------------------------*/ void* delete_vertex(GRAPH *g, VINDEX vertex) { void *user; EINDEX from, nfrom, to, nto; GR_ASSERT(is_vertex(g, vertex), "delete vertex is_vertex\n"); user = VERTEX_user(&GRAPH_v_i(g,vertex)); /* delete the from edges */ from = VERTEX_from(&GRAPH_v_i(g,vertex)); while (from != INVALID_EINDEX) { nfrom = EDGE_nfrom(&GRAPH_e_i(g,from)); delete_edge(g, from); from = nfrom; } /* delete the to edges */ to = VERTEX_to(&GRAPH_v_i(g,vertex)); while (to != INVALID_EINDEX) { nto = EDGE_nto(&GRAPH_e_i(g,to)); delete_edge(g, to); to = nto; } VERTEX_fcnt(&GRAPH_v_i(g,vertex)) = -1; VERTEX_from(&GRAPH_v_i(g,vertex)) = GRAPH_vfree(g); GRAPH_vfree(g) = vertex; GRAPH_vcnt(g)--; return user; }
unsigned vertex(double* x, double* y) { unsigned cmd = m_src->vertex(x, y); if(is_vertex(cmd)) ++m_points; if(is_move_to(cmd)) ++m_contours; return cmd; }
//------------------------------------------------------------------------ void vcgen_contour::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist(x, y)); } else { if(is_end_poly(cmd)) { m_closed = get_close_flag(cmd); if(m_orientation == path_flags_none) { m_orientation = get_orientation(cmd); } } } } }
/*---------------------------------------------------------------*/ void* get_edge(GRAPH *g, VINDEX from, VINDEX to) { EINDEX e; GR_ASSERT(is_vertex(g, from), "get_edge is_vertex from\n"); GR_ASSERT(is_vertex(g, to), "get_edge is_vertex to\n"); e = VERTEX_from(&GRAPH_v_i(g, from)); while ( e != INVALID_EINDEX ) { if(EDGE_to(&GRAPH_e_i(g,e)) == to) break; e = (EDGE_nfrom(&GRAPH_e_i(g,e))); } return EDGE_user(&GRAPH_e_i(g,e)); }
/*---------------------------------------------------------------*/ int edge_count(GRAPH* g, VINDEX from, VINDEX to) { int count= 0; EINDEX e; GR_ASSERT(is_vertex(g, from), "edge_count is_vertex from\n"); GR_ASSERT(is_vertex(g, to), "edge_count is_vertex to\n"); e = VERTEX_from(&GRAPH_v_i(g, from)); while ( e != INVALID_EINDEX ) { if(EDGE_to(&GRAPH_e_i(g,e)) == to) ++count; e = (EDGE_nfrom(&GRAPH_e_i(g,e))); } return count; }
/* Count the vertices in a matrix of external points */ static size_t count_vertices(const dd_MatrixPtr generators) { dd_rowrange i; int vertex_count = 0; for (i = 0; i < generators->rowsize; i++) { /* Check if row is vertex (first column 0) */ if (is_vertex(generators->matrix[i][0])) vertex_count++; } return vertex_count; }
void vcgen_stroke::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist_cmd(x, y, cmd)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist_cmd(x, y, cmd)); } else { m_closed = get_close_flag(cmd); } } }
//------------------------------------------------------------------------ void path_renderer::move_to(double x, double y, bool rel) // M, m { if(rel && m_storage.total_vertices()) { double x2,y2; unsigned cmd = m_storage.last_vertex(&x2,&y2); if(is_end_poly(cmd)) { // rewind until we find a real vertex unsigned idx = m_storage.total_vertices()-1; while(idx && !is_vertex(m_storage.vertex(--idx,&x2,&y2))); } x += x2; y += y2; } m_storage.move_to(x, y); }
//------------------------------------------------------------------------ void vcgen_bspline::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(point_d(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(point_d(x, y)); } else { m_closed = get_close_flag(cmd); } } }
//------------------------------------------------------------------------ void vcgen_smooth_poly1::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist(x, y)); } else { m_closed = get_close_flag(cmd); } } }
int hit_test(double x, double y, double r) { m_affine.inverse_transform(&x, &y); r /= m_affine.scale(); unsigned i; for(i = 0; i < m_path.total_vertices(); i++) { double vx, vy; unsigned cmd = m_path.vertex(i, &vx, &vy); if(is_vertex(cmd)) { if(calc_distance(x, y, vx, vy) <= r) { return i; } } } return -1; }
double path_length(VertexSource& vs, unsigned path_id = 0) { double len = 0.0; double start_x = 0.0; double start_y = 0.0; double x1 = 0.0; double y1 = 0.0; double x2 = 0.0; double y2 = 0.0; bool first = true; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x2, &y2))) { if(is_vertex(cmd)) { if(first || is_move_to(cmd)) { start_x = x2; start_y = y2; } else { len += calc_distance(x1, y1, x2, y2); } x1 = x2; y1 = y2; first = false; } else { if(is_close(cmd) && !first) { len += calc_distance(x1, y1, start_x, start_y); } } } return len; }
//------------------------------------------------------------------------ void vcgen_markers_term::add_vertex(double x, double y, unsigned cmd) { if(is_move_to(cmd)) { if(m_markers.size() & 1) { // Initial state, the first coordinate was added. // If two of more calls of start_vertex() occures // we just modify the last one. m_markers.modify_last(coord_type(x, y)); } else { m_markers.add(coord_type(x, y)); } } else { if(is_vertex(cmd)) { if(m_markers.size() & 1) { // Initial state, the first coordinate was added. // Add three more points, 0,1,1,0 m_markers.add(coord_type(x, y)); m_markers.add(m_markers[m_markers.size() - 1]); m_markers.add(m_markers[m_markers.size() - 3]); } else { if(m_markers.size()) { // Replace two last points: 0,1,1,0 -> 0,1,2,1 m_markers[m_markers.size() - 1] = m_markers[m_markers.size() - 2]; m_markers[m_markers.size() - 2] = coord_type(x, y); } } } } }
/* * Parse the generator output. Find the generators which are vertices * (non-rays) add their corresponding inequalities to an output set. * * Returns a matrix where each row contains the x-coordinate of the vertex, * y-coordinate of the vertex, and 0-based index of the inequality which bounds * the polytope to the right of the vertex. output_size is set to the total * length of the ouptut. */ static double *list_extreme_vertices(const dd_MatrixPtr generators, const dd_SetFamilyPtr incidence, const size_t nrows, long lower_bound_index, /*OUT*/ size_t * output_size) { assert(generators->rowsize > 0); assert(generators->colsize > 2); set_type cur_vert_set, next_vert_set, s; dd_rowrange i; long elem; size_t out_row = 0, r; size_t vertex_count = count_vertices(generators); /* Last vertex intersects with upper bound - not output */ *output_size = 3 * (vertex_count - 1); double *output = (double *) malloc(sizeof(double) * (*output_size)); /* Sorted indices into generators */ size_t *indices = sort_generators(generators); assert(*output_size > 0); /* Loop over vertices in generators, extracting solutions * * For vertices 0..n_vertices-2, find the inequality incident to the vertex * also incident in the next vertex. */ for (i = 0; i < vertex_count - 1; i++) { r = indices[i]; assert(is_vertex(generators->matrix[r][0])); assert(is_vertex(generators->matrix[indices[i + 1]][0])); assert(out_row < vertex_count - 1); cur_vert_set = incidence->set[r]; next_vert_set = incidence->set[indices[i + 1]]; /* Sets should be same size */ assert(cur_vert_set[0] == next_vert_set[0]); set_initialize(&s, cur_vert_set[0]); set_int(s, cur_vert_set, next_vert_set); /* Remove added index for first item */ /*if (!i)*/ /*set_delelem(s, lower_bound_index);*/ /* Set may have > 1 solution if ~identical slopes and intercepts due to * rounding. */ /*assert(set_card(s) == 1); */ /* Only one item in the set */ elem = set_first(s); set_free(s); /* Fill output row */ int base = out_row * 3; output[base] = *generators->matrix[r][1]; /* x */ output[base + 1] = *generators->matrix[r][2]; /* y */ output[base + 2] = (double) (elem - 1); /* ineq index, converted to 0-base */ out_row++; } free(indices); return output; }
/*---------------------------------------------------------------*/ int num_succs(GRAPH *g, VINDEX vertex) { GR_ASSERT(is_vertex(g,vertex), "num_succs is_vertex\n"); return (VERTEX_fcnt(&GRAPH_v_i(g,vertex))); }
/*---------------------------------------------------------------*/ void* get_vertex(GRAPH *g, VINDEX vertex) { GR_ASSERT(is_vertex(g,vertex), "get_vertex\n"); return (VERTEX_user(&GRAPH_v_i(g,vertex))); }
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y) { unsigned cmd = path_cmd_stop; for(;;) { cmd = m_vpgen.vertex(x, y); if(!is_stop(cmd)) break; if(m_poly_flags && !m_vpgen.auto_unclose()) { *x = 0.0; *y = 0.0; cmd = m_poly_flags; m_poly_flags = 0; break; } if(m_vertices < 0) { if(m_vertices < -1) { m_vertices = 0; return path_cmd_stop; } m_vpgen.move_to(m_start_x, m_start_y); m_vertices = 1; continue; } double tx, ty; cmd = m_source->vertex(&tx, &ty); if(is_vertex(cmd)) { if(is_move_to(cmd)) { if(m_vpgen.auto_close() && m_vertices > 2) { m_vpgen.line_to(m_start_x, m_start_y); m_poly_flags = path_cmd_end_poly | path_flags_close; m_start_x = tx; m_start_y = ty; m_vertices = -1; continue; } m_vpgen.move_to(tx, ty); m_start_x = tx; m_start_y = ty; m_vertices = 1; } else { m_vpgen.line_to(tx, ty); ++m_vertices; } } else { if(is_end_poly(cmd)) { m_poly_flags = cmd; if(is_closed(cmd) || m_vpgen.auto_close()) { if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close; if(m_vertices > 2) { m_vpgen.line_to(m_start_x, m_start_y); } m_vertices = 0; } } else { // path_cmd_stop if(m_vpgen.auto_close() && m_vertices > 2) { m_vpgen.line_to(m_start_x, m_start_y); m_poly_flags = path_cmd_end_poly | path_flags_close; m_vertices = -2; continue; } break; } } } return cmd; }