void remove_connection_at(Vec2f world_pos){ float threshold = 20.0; for(auto it = backend.connections.begin();it != backend.connections.end();it++){ ConnectionInfo &cinf = *it; int inlet = cinf.inlet; int outlet = cinf.outlet; NodeViewer * start = node_view[cinf.out_node]; NodeViewer * end = node_view[cinf.in_node]; Vec2f pos_start = start->outlets[outlet].pos + Vec2f(INLET_SIZE/2,INLET_SIZE/2); Vec2f pos_end = end->inlets[inlet].pos + Vec2f(INLET_SIZE/2,INLET_SIZE/2); if(line_point_distance(pos_start.x,pos_start.y,pos_end.x,pos_end.y, world_pos.x,world_pos.y) < threshold){ backend.remove_connection(it); return; } } }
bool check_point(Vec2f p, float distance_threshold){ float d = line_point_distance(pos_start.x,pos_start.y,pos_end.x,pos_end.y,p.x,p.y); float scaling =scale > 1 ? sqrt(scale) : 1.0; return d < distance_threshold/scaling; }
void decimate_inplace(MutableTriangleTopology& mesh, RawField<TV,VertexId> X, const T distance, const T max_angle, const int min_vertices, const T boundary_distance) { if (mesh.n_vertices() <= min_vertices) return; const T area = sqr(distance); const T sign_sqr_min_cos = sign_sqr(max_angle > .99*pi ? -1 : cos(max_angle)); // Finds the best edge to collapse v along. Returns (q(e),dst(e)). const auto best_collapse = [&mesh,X](const VertexId v) { Quadric q = compute_quadric(mesh,X,v); // Find the best edge, ignoring normal constraints T min_q = inf; HalfedgeId min_e; for (const auto e : mesh.outgoing(v)) { const T qx = q(X[mesh.dst(e)]); if (min_q > qx) { min_q = qx; min_e = e; } } return tuple(min_q,mesh.dst(min_e)); }; // Initialize quadrics and heap Heap heap(mesh.n_vertices_); for (const auto v : mesh.vertices()) { const auto qe = best_collapse(v); if (qe.x <= area) heap.inv_heap[v] = heap.heap.append(tuple(v,qe.x,qe.y)); } heap.make(); // Update the quadric information for a vertex const auto update = [&heap,best_collapse,area](const VertexId v) { const auto qe = best_collapse(v); if (qe.x <= area) heap.set(v,qe.x,qe.y); else heap.erase(v); }; // Repeatedly collapse the best vertex while (heap.size()) { const auto v = heap.pop(); // Do these vertices still exist? if (mesh.valid(v.x) && mesh.valid(v.y)) { const auto e = mesh.halfedge(v.x,v.y); // Is the collapse invalid? if (e.valid() && mesh.is_collapse_safe(e)) { const auto vs = mesh.src(e), vd = mesh.dst(e); const auto xs = X[vs], xd = X[vd]; // Are we moving a boundary vertex too far from its two boundary lines? { const auto b = mesh.halfedge(vs); if (mesh.is_boundary(b)) { const auto x0 = X[mesh.dst(b)], x1 = X[mesh.src(mesh.prev(b))]; if ( line_point_distance(simplex(xs,x0),xd) > boundary_distance || line_point_distance(simplex(xs,x1),xd) > boundary_distance) goto bad; } } // Do the normals change too much? if (sign_sqr_min_cos > -1) for (const auto ee : mesh.outgoing(vs)) if (e!=ee && !mesh.is_boundary(ee)) { const auto v2 = mesh.opposite(ee); if (v2 != vd) { const auto x1 = X[mesh.dst(ee)], x2 = X[v2]; const auto n0 = cross(x2-x1,xs-x1), n1 = cross(x2-x1,xd-x1); if (sign_sqr(dot(n0,n1)) < sign_sqr_min_cos*sqr_magnitude(n0)*sqr_magnitude(n1)) goto bad; } } // Collapse vs onto vd, then update the heap mesh.unsafe_collapse(e); if (mesh.n_vertices() <= min_vertices) break; update(vd); for (const auto e : mesh.outgoing(vd)) update(mesh.dst(e)); } } bad:; } }