//---------------------------------------------------------------------------- // streaming //---------------------------------------------------------------------------- Object* Polyline::Factory (Stream& rkStream) { Polyline* pkObject = new Polyline; Stream::Link* pkLink = new Stream::Link(pkObject); pkObject->Load(rkStream,pkLink); return pkObject; }
void Polygon::equally_spaced_points(double distance, Points* points) const { Polyline polyline; this->split_at_first_point(&polyline); polyline.equally_spaced_points(distance, points); }
Polyline AvoidCrossingPerimeters::travel_to(GCode &gcodegen, Point point) { if (this->use_external_mp || this->use_external_mp_once) { // get current origin set in gcodegen // (the one that will be used to translate the G-code coordinates by) Point scaled_origin = Point::new_scale(gcodegen.origin.x, gcodegen.origin.y); // represent last_pos in absolute G-code coordinates Point last_pos = gcodegen.last_pos(); last_pos.translate(scaled_origin); // represent point in absolute G-code coordinates point.translate(scaled_origin); // calculate path Polyline travel = this->_external_mp->shortest_path(last_pos, point); // translate the path back into the shifted coordinate system that gcodegen // is currently using for writing coordinates travel.translate(scaled_origin.negative()); return travel; } else { return this->_layer_mp->shortest_path(gcodegen.last_pos(), point); } }
//---------------------------------------------------------------------------- void GelatinBlob::DoPhysical () { m_pkModule->Update(GetTimeInSeconds()); // Update sphere surface. The particle system and sphere maintain their // own copy of the vertices, so this update is necessary. Vector3f* akVertex = m_spkSphere->Vertices(); int i; for (i = 0; i < 12; i++) akVertex[i] = m_pkModule->Position(i); m_spkSphere->UpdateModelBound(); // update the segments representing the springs int iNumSprings = m_pkModule->GetNumSprings(); for (i = 0; i < iNumSprings; i++) { int iV0, iV1; float fConstant, fLength; m_pkModule->GetSpring(i,iV0,iV1,fConstant,fLength); Polyline* pkPoly = WmlStaticCast(Polyline,m_spkSegments->GetChild(i)); Vector3f* akVertex = pkPoly->Vertices(); akVertex[0] = m_pkModule->Position(iV0); akVertex[1] = m_pkModule->Position(iV1); } }
TriangleMesh* MeshSweeper::makeBox( const vec3& center, const vec3& normal, const vec3& up, const vec3& size, const mat4& m) //[]----------------------------------------------------[] //| Make box 1 | //[]----------------------------------------------------[] { Polyline poly; vec3 N(normal.versor()); vec3 U(up.cross(normal).versor()); vec3 V(N.cross(U)); N *= size.z * (REAL)0.5; U *= size.x * (REAL)0.5; V *= size.y * (REAL)0.5; poly.mv(center - U - V - N); poly.mv(center + U - V - N); poly.mv(center + U + V - N); poly.mv(center - U + V - N); poly.close(); return makeCylinder(poly, 2 * N, m); }
Points Polygon::equally_spaced_points(double distance) const { Polyline* polyline = this->split_at_first_point(); Points pts = polyline->equally_spaced_points(distance); delete polyline; return pts; }
void Canvas::load(string path) { cout << "load" << endl; for (int i = 0; i < lines.size(); i++) { lines[i]->release(); delete lines[i]; } lines.clear(); while (!joints.empty()) { delete joints.back(); joints.pop_back(); } int lines_n; int n; ifstream file(path.c_str()); if (file.is_open()) { int i = 0; file >> n; for (int i = 0; i < n; i++) { Joint *v = new Joint(); v->setupGui(); file >> v->p.x; file >> v->p.y; int fixed; file >> fixed; v->fixed = (bool)fixed; *v->fixed_toggle = v->fixed; v->joint_type = JOINT_REVOLUTE; v->id = i; joints.push_back(v); } file >> lines_n; for (int i = 0; i < lines_n; i++) { lines.push_back(new Polyline()); Polyline *l = lines.back(); l->id = lines.size() - 1; file >> n; file >> l->closed; for (int i = 0; i < n; i++) { Vertex v; file >> v.p.x; file >> v.p.y; l->addBack(&v); } if (l->closed) { l->back->next = l->front; l->front->prev = l->back; } l->update(); } file.close(); }
Polyline::Polyline(const Polyline& ply) : GeoObject(), _ply_pnts(ply._ply_pnts) { for (size_t k(0); k < ply.getNumberOfPoints(); ++k) _ply_pnt_ids.push_back(ply.getPointID(k)); if (ply.getNumberOfPoints() > 0) for (size_t k(0); k < ply.getNumberOfPoints(); ++k) _length.push_back(ply.getLength(k)); }
Polyline* ProgressBar::getBorder(int index) { int y2 = yy+myHeight; Polyline* p = new Polyline(5); p->addNextVertex(startX[index],yy,BLACK); p->addNextVertex(startX[index]+myWidth/segs,yy,BLACK); p->addNextVertex(startX[index]+myWidth/segs,y2,BLACK); p->addNextVertex(startX[index],y2,BLACK); p->addNextVertex(startX[index],yy,BLACK); return p; }
Polyline * Factory::getRandPolyline() { Polyline * pl = new Polyline(); int N = iRand(1, 10); for (int i = 0; i < N; i++) { Point * p = getRandPoint(); pl->addPoint(* p); delete p; } return pl; }
bool isLineSegmentIntersecting(const Polyline& ply, GEOLIB::Point const& s0, GEOLIB::Point const& s1) { const size_t n(ply.getNumberOfPoints() - 1); bool intersect(false); GEOLIB::Point intersection_pnt; for (size_t k(0); k < n && !intersect; k++) { intersect = MathLib::lineSegmentIntersect(*(ply.getPoint(k)), *(ply.getPoint(k + 1)), s0, s1, intersection_pnt); } return intersect; }
int main() { srand((unsigned) time(NULL)); try { XList<Shape*> list; // filling list of figures with random figures of all types. int numberOfElements = rand() % 100; for(int i = 0; i < numberOfElements; i++) { switch (i % 5) { case 0: list.pushElementToBack(new Point("TestPoint", rand() % 100, rand() % 100)); break; case 1: list.pushElementToBack(new Circle("TestCircle", rand() % 100, rand() % 100, rand() % 100)); break; case 2: list.pushElementToBack(new Rect("TestRect", rand() % 100, rand() % 100, rand() % 100, rand() % 100)); break; case 3: list.pushElementToBack(new Square("TestSquare", rand() % 100, rand() % 100, rand() % 100)); break; case 4: Polyline* pol = new Polyline("TestPol"); Point p1("pol_point_1", rand() % 100, rand() % 100); Point p2("pol_point_2", rand() % 100, rand() % 100); Point p3("pol_point_3", rand() % 100, rand() % 100); pol->addPoint(p1); pol->addPoint(p2); pol->addPoint(p3); list.pushElementToBack(pol); break; } } std::cout << "Number of shapes " << Shape::getNumberOfShapes() << "\n"; XList<Shape*>::Iterator it = list.begin(); for(it = list.begin(); it != list.end(); ++it) { std::cout << "\n" << **it << "\n"; } std::cout << "Number of shapes " << Shape::getNumberOfShapes() << "\n"; for(it = list.begin(); it != list.end(); ++it) { delete *it; } // should be zero std::cout << "Number of shapes " << Shape::getNumberOfShapes() << "\n"; return 0; } catch (std::exception ex) { std::cerr << ex.what(); return 1; } }
// this function is what is required by task #3 here: https://sites.google.com/site/kostovoop/tasks // Составить и отладить программу: // - создать некий XList фигур, наполнить его случайным образом конкретными фигурами всех типов; // - вывести в std::cout общее кол-во фигур с помощью Shape::GetCount(); // - напечатать в std::cout сведения обо всех фигурах, находящихся в списке; // - очистить память; // - вывести в std::cout общее кол-во фигур с помощью Shape::GetCount() – удостовериться, что там 0; // - завершить работу программы. void task3() { XList<Shape> shapesList; // pt, circle, rect, square, polyline Point * pt = new Point("a point", 10, 100); // 1 Circle * circle = new Circle("a circle", 30, Point("circle center", 10, 20)); // 2 Rect * rect = new Rect("a rect", 10, -30, 10, -100); // 2 Square * square = new Square("a square", 40, 20, 10); // 2 Polyline * line = new Polyline("line"); // 1 Point * pt1 = new Point("", 10, 20); Point * pt2 = new Point("", 20, 20); Point * pt3 = new Point("", 20, 40); Point * pt4 = new Point("", 10, 40); line->AddPoint(*pt1); line->AddPoint(*pt2); line->AddPoint(*pt3); line->AddPoint(*pt4); shapesList.pushBack(pt); shapesList.pushBack(circle); shapesList.pushBack(rect); shapesList.pushBack(square); shapesList.pushBack(line); std::cout << "Total number of shapes is: " << Shape::getCount() << std::endl; assert(Shape::getCount() == 16); // 5 figures in list and their copies, 4 points in the polyline, rect's origin, square's origin, circle's center XList<Shape>::Iterator it = shapesList.begin(); int l = shapesList.numberOfElements() + 1; while(--l > 0){ Shape * shape = it.currentItem(); std::cout << *shape << std::endl; it.next(); } shapesList.clearList(); // freeing memory delete pt; delete circle; delete square; delete rect; delete line; delete pt1; delete pt2; delete pt3; delete pt4; std::cout << "Total number of shapes is now: " << Shape::getCount() << std::endl; assert(Shape::getCount() == 0); }
//---------------------------------------------------------------------------- bool Polylines::OnInitialize () { if ( !Application::OnInitialize() ) return false; // set up camera ms_spkCamera->SetFrustum(1.0f,1000.0f,-0.55f,0.55f,0.4125f,-0.4125f); Vector3f kCLoc(4.0f,0.0f,0.0f); Vector3f kCLeft(0.0f,-1.0f,0.0f); Vector3f kCUp(0.0f,0.0f,1.0f); Vector3f kCDir(-1.0f,0.0f,0.0f); ms_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir); // set up scene m_spkScene = new Node(1); int iVertexQuantity = 128; Vector3f* akVertex = new Vector3f[iVertexQuantity]; ColorRGB* akColor = new ColorRGB[iVertexQuantity]; for (int i = 0; i < iVertexQuantity; i++) { akVertex[i].X() = Mathf::SymmetricRandom(); akVertex[i].Y() = Mathf::SymmetricRandom(); akVertex[i].Z() = Mathf::SymmetricRandom(); akColor[i].r = Mathf::UnitRandom(); akColor[i].g = Mathf::UnitRandom(); akColor[i].b = Mathf::UnitRandom(); } bool bClosed = true; bool bContiguous = true; Polyline* pkPoints = new Polyline(iVertexQuantity,akVertex,NULL, akColor,NULL,bClosed); pkPoints->Contiguous() = bContiguous; m_spkScene->AttachChild(pkPoints); // initial update of objects ms_spkCamera->Update(); m_spkScene->UpdateGS(0.0f); m_spkScene->UpdateRS(); m_spkMotionObject = m_spkScene; m_bTurretActive = true; SetTurretAxes(); m_fTrnSpeed = 0.01f; m_fRotSpeed = 0.001f; return true; }
bool operator==(Polyline const& lhs, Polyline const& rhs) { if (lhs.getNumberOfPoints() != rhs.getNumberOfPoints()) return false; const size_t n(lhs.getNumberOfPoints()); for (size_t k(0); k < n; k++) { if (lhs.getPointID(k) != rhs.getPointID(k)) return false; } return true; }
void BezierSpline::convertFromPolyline(const Polyline &polyline, int smooth_coefficient) { float scale = 1.0/smooth_coefficient; int n = polyline.numPoints(); assert(n >= 2); for (int i = 0; i < n; ++i) addControlPoint(polyline.getPoint(i)); // for (int i = 0; i < n; ++i) // { // if (i == 0) // is first // { // Eigen::Vector3f p1 = polyline.getPoint(i); // Eigen::Vector3f p2 = polyline.getPoint(i+1); // Eigen::Vector3f tangent = (p2 - p1); // Eigen::Vector3f q1 = p1 + scale * tangent; // addControlPoint(p1); // addControlPoint(q1); // } else if (i == n - 1) // { // Eigen::Vector3f p0 = polyline.getPoint(i-1); // Eigen::Vector3f p1 = polyline.getPoint(i); // Eigen::Vector3f tangent = (p1 - p0); // Eigen::Vector3f q0 = p1 - scale * tangent; // addControlPoint(q0); // addControlPoint(p1); // } else // { // Eigen::Vector3f p0 = polyline.getPoint(i-1); // Eigen::Vector3f p1 = polyline.getPoint(i); // Eigen::Vector3f p2 = polyline.getPoint(i+1); // Eigen::Vector3f tangent = (p2 - p0).normalized(); // Eigen::Vector3f q0 = p1 - scale * tangent * (p1 - p0).norm(); // Eigen::Vector3f q1 = p1 + scale * tangent * (p2 - p1).norm(); // addControlPoint(q0); // addControlPoint(p1); // addControlPoint(q1); // } // } setClosed(polyline.closed()); }
/** * Loads the globe from a YAML file. * @param node YAML node. */ void RuleGlobe::load(const YAML::Node &node) { if (node["data"]) { loadDat(CrossPlatform::getDataFile(node["data"].as<std::string>())); } for (YAML::const_iterator i = node["polygons"].begin(); i != node["polygons"].end(); ++i) { Polygon *polygon = new Polygon(3); polygon->load(*i); _polygons.push_back(polygon); } for (YAML::const_iterator i = node["polylines"].begin(); i != node["polylines"].end(); ++i) { Polyline *polyline = new Polyline(3); polyline->load(*i); _polylines.push_back(polyline); } }
int main(){ XList<Shape*> shapes; Point * point1 = new Point(0., 2., "point_1"); shapes.push_back(point1); Point * point2 = new Point(2., 2., "point_2"); shapes.push_back(point2); Point * point3 = new Point(2., 0., "point_3"); shapes.push_back(point3); Point * point4 = new Point(0., 0., "point_4"); shapes.push_back(point4); Circle * circle = new Circle(point4, 10., "circle_1"); shapes.push_back(circle); Rect * rect = new Rect(point1, point2, point3, point4, "rectangle"); shapes.push_back(rect); try { Square * square = new Square(point1, point2, point3, point4, "square"); shapes.push_back(square); } catch (const char* error){ // std::cout << "EXCEPTION RAISED: " << error << std::endl; } Polyline * polyline = new Polyline("polyline"); polyline->AddPoint(point1); polyline->AddPoint(point2); polyline->AddPoint(point3); polyline->AddPoint(point4); shapes.push_back(polyline); for (XList<Shape*>::iterator it = shapes.begin(); it != NULL; ++it) { std::cout << *it; } printf("Number of shapes = %d\n", Shape::GetCount()); for (XList<Shape*>::iterator it = shapes.begin(); it != NULL; ++it) { delete *it; } printf("Number of shapes = %d\n", Shape::GetCount()); return 0; }
bool Polygon::isPartOfPolylineInPolygon(const Polyline& ply) const { const std::size_t ply_size (ply.getNumberOfPoints()); // check points for (std::size_t k(0); k < ply_size; k++) { if (isPntInPolygon (*(ply.getPoint(k)))) { return true; } } GeoLib::Point s; for (auto polygon_seg : *this) { for (auto polyline_seg : ply) { if (GeoLib::lineSegmentIntersect(polyline_seg, polygon_seg, s)) { return true; } } } return false; }
bool containsEdge(const Polyline& ply, size_t id0, size_t id1) { if (id0 == id1) { std::cerr << "no valid edge id0 == id1 == " << id0 << "\n"; return false; } if (id0 > id1) BASELIB::swap(id0, id1); const size_t n(ply.getNumberOfPoints() - 1); for (size_t k(0); k < n; k++) { size_t ply_pnt0(ply.getPointID(k)); size_t ply_pnt1(ply.getPointID(k + 1)); if (ply_pnt0 > ply_pnt1) BASELIB::swap(ply_pnt0, ply_pnt1); if (ply_pnt0 == id0 && ply_pnt1 == id1) return true; } return false; }
// This method accepts &point in print coordinates. std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string comment) { /* Define the travel move as a line between current position and the taget point. This is expressed in print coordinates, so it will need to be translated by $self->origin in order to get G-code coordinates. */ Polyline travel; travel.append(this->last_pos()); travel.append(point); // check whether a straight travel move would need retraction bool needs_retraction = this->needs_retraction(travel, role); // if a retraction would be needed, try to use avoid_crossing_perimeters to plan a // multi-hop travel path inside the configuration space if (needs_retraction && this->config.avoid_crossing_perimeters && !this->avoid_crossing_perimeters.disable_once) { travel = this->avoid_crossing_perimeters.travel_to(*this, point); // check again whether the new travel path still needs a retraction needs_retraction = this->needs_retraction(travel, role); } // Re-allow avoid_crossing_perimeters for the next travel moves this->avoid_crossing_perimeters.disable_once = false; this->avoid_crossing_perimeters.use_external_mp_once = false; // generate G-code for the travel move std::string gcode; if (needs_retraction) gcode += this->retract(); // use G1 because we rely on paths being straight (G0 may make round paths) Lines lines = travel.lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) gcode += this->writer.travel_to_xy(this->point_to_gcode(line->b), comment); return gcode; }
bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role) { if (travel.length() < scale_(EXTRUDER_CONFIG(retract_before_travel))) { // skip retraction if the move is shorter than the configured threshold return false; } if (role == erSupportMaterial) { const SupportLayer* support_layer = dynamic_cast<const SupportLayer*>(this->layer); if (support_layer != NULL && support_layer->support_islands.contains(travel)) { // skip retraction if this is a travel move inside a support material island return false; } } if (this->config.only_retract_when_crossing_perimeters && this->layer != NULL) { if (this->config.fill_density.value > 0 && this->layer->any_internal_region_slice_contains(travel)) { /* skip retraction if travel is contained in an internal slice *and* internal infill is enabled (so that stringing is entirely not visible) */ return false; } else if (this->layer->any_bottom_region_slice_contains(travel) && this->layer->upper_layer != NULL && this->layer->upper_layer->slices.contains(travel) && (this->config.bottom_solid_layers.value >= 2 || this->config.fill_density.value > 0)) { /* skip retraction if travel is contained in an *infilled* bottom slice but only if it's also covered by an *infilled* upper layer's slice so that it's not visible from above (a bottom surface might not have an upper slice in case of a thin membrane) */ return false; } } // retract if only_retract_when_crossing_perimeters is disabled or doesn't apply return true; }
void calculatePolylineFromCP(const std::vector<Vector2d> &aCPs) { // build a polyline from our control points, for visible. polyline.clear(); polyline.setPosition(Vector2d(400, 400) ); for (unsigned int i = 0; i < aCPs.size(); ++i) polyline.addVertex( aCPs[i] ); // to do the evaluation of the curve, get an array pos on the curve std::vector<Vector2d> aPos; for (int i = 0; i <= 200; ++i) aPos.push_back( evaluateCubicBezier_deCasteljau(aCPs, i * 1.0f / 200) ); // we use those pos on the curve to simulate a curve by a polyline, for visible. curvePolyline.clear(); curvePolyline.setPosition(Vector2d(400, 400) ); for (unsigned int i = 0; i < aPos.size(); ++i) curvePolyline.addVertex( aPos[i] ); }
// This method accepts &point in print coordinates. std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string comment) { /* Define the travel move as a line between current position and the taget point. This is expressed in print coordinates, so it will need to be translated by this->origin in order to get G-code coordinates. */ Polyline travel; travel.append(this->last_pos()); travel.append(point); std::string gcode; // check whether a straight travel move would need retraction bool needs_retraction = this->needs_retraction(travel, role); std::stringstream ss; ss << ";needs retr 1: " << needs_retraction << "\n"; gcode += ss.str(); // if a retraction would be needed, try to use avoid_crossing_perimeters to plan a // multi-hop travel path inside the configuration space if (needs_retraction && this->config.avoid_crossing_perimeters && !this->avoid_crossing_perimeters.disable_once) { travel = this->avoid_crossing_perimeters.travel_to(*this, point); gcode += ";HERE!!!!!\n"; // check again whether the new travel path still needs a retraction needs_retraction = this->needs_retraction(travel, role); std::stringstream ss; ss << ";needs retr 2: " << needs_retraction << "\n"; gcode += ss.str(); //if (needs_retraction && this->layer_index > 1) exit(0); } //needs_retraction = true; //vladi //if (this->first_layer) needs_retraction = false;//vladi // Re-allow avoid_crossing_perimeters for the next travel moves this->avoid_crossing_perimeters.disable_once = false; this->avoid_crossing_perimeters.use_external_mp_once = false; // generate G-code for the travel move //if (travel.lines().begin()->length() * SCALING_FACTOR > 2 && this->first_layer) needs_retraction = true; //std::size_t found = comment.find("infill"); bool willDoInfill = (comment.find("infill") != std::string::npos); //if (comment.find("infill") != std::string::npos && this->first_layer) needs_retraction = false; if (needs_retraction) gcode += this->retract(); // use G1 because we rely on paths being straight (G0 may make round paths) Lines lines = travel.lines(); double path_length = 0; for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { const double line_length = line->length() * SCALING_FACTOR; path_length += line_length; std::stringstream ss1; ss1 << ";Will Travel: " << line_length << ", on layer height: " << this->layer->print_z << ", id" << this->layer->id() << "\n"; gcode += ss1.str(); if (this->first_layer && line_length > 3 && !willDoInfill) { if (needs_retraction) { gcode += this->unretract(); gcode += this->writer.travel_to_z(this->layer->print_z, "extrude move on layer height"); } else { gcode += this->writer.travel_to_z(0.1, "extrude move 333"); } double fil_sq = 3.14f *1.75f*1.75f/4; double exr_line = 0.1f*0.4f; double e = exr_line *line_length/fil_sq; //double e_per_mm = this->writer.extruder()->e_per_mm3 * path.mm3_per_mm; // gcode += "G1 F6000\n"; gcode += this->writer.extrude_to_xy(this->point_to_gcode(line->b), e, comment); gcode += this->writer.travel_to_z(this->layer->print_z, "return"); lowerSpeed = true; } else { gcode += this->writer.travel_to_xy(this->point_to_gcode(line->b), comment); } } if (this->config.cooling) this->elapsed_time += path_length / this->config.get_abs_value("travel_speed"); return gcode; }
void MedialAxis::build(Polylines* polylines) { /* // build bounding box (we use it for clipping infinite segments) // --> we have no infinite segments this->bb = BoundingBox(this->lines); */ construct_voronoi(this->lines.begin(), this->lines.end(), &this->vd); /* // DEBUG: dump all Voronoi edges { for (VD::const_edge_iterator edge = this->vd.edges().begin(); edge != this->vd.edges().end(); ++edge) { if (edge->is_infinite()) continue; Polyline polyline; polyline.points.push_back(Point( edge->vertex0()->x(), edge->vertex0()->y() )); polyline.points.push_back(Point( edge->vertex1()->x(), edge->vertex1()->y() )); polylines->push_back(polyline); } return; } */ // collect valid edges (i.e. prune those not belonging to MAT) // note: this keeps twins, so it contains twice the number of the valid edges this->edges.clear(); for (VD::const_edge_iterator edge = this->vd.edges().begin(); edge != this->vd.edges().end(); ++edge) { // if we only process segments representing closed loops, none if the // infinite edges (if any) would be part of our MAT anyway if (edge->is_secondary() || edge->is_infinite()) continue; this->edges.insert(&*edge); } // count valid segments for each vertex std::map< const VD::vertex_type*,std::set<const VD::edge_type*> > vertex_edges; std::set<const VD::vertex_type*> entry_nodes; for (VD::const_vertex_iterator vertex = this->vd.vertices().begin(); vertex != this->vd.vertices().end(); ++vertex) { // get a reference to the list of valid edges originating from this vertex std::set<const VD::edge_type*>& edges = vertex_edges[&*vertex]; // get one random edge originating from this vertex const VD::edge_type* edge = vertex->incident_edge(); do { if (this->edges.count(edge) > 0) // only count valid edges edges.insert(edge); edge = edge->rot_next(); // next edge originating from this vertex } while (edge != vertex->incident_edge()); // if there's only one edge starting at this vertex then it's a leaf size_t edge_count = edges.size(); if (edge_count == 1) { entry_nodes.insert(&*vertex); } } // prune recursively while (!entry_nodes.empty()) { // get a random entry node const VD::vertex_type* v = *entry_nodes.begin(); // get edge starting from v assert(!vertex_edges[v].empty()); const VD::edge_type* edge = *vertex_edges[v].begin(); if (!this->is_valid_edge(*edge)) { // if edge is not valid, erase it from edge list (void)this->edges.erase(edge); (void)this->edges.erase(edge->twin()); // decrement edge counters for the affected nodes const VD::vertex_type* v1 = edge->vertex1(); (void)vertex_edges[v].erase(edge); (void)vertex_edges[v1].erase(edge->twin()); // also, check whether the end vertex is a new leaf if (vertex_edges[v1].size() == 1) { entry_nodes.insert(v1); } else if (vertex_edges[v1].empty()) { entry_nodes.erase(v1); } } // remove node from the set to prevent it from being visited again entry_nodes.erase(v); } // iterate through the valid edges to build polylines while (!this->edges.empty()) { const VD::edge_type& edge = **this->edges.begin(); // start a polyline Polyline polyline; polyline.points.push_back(Point( edge.vertex0()->x(), edge.vertex0()->y() )); polyline.points.push_back(Point( edge.vertex1()->x(), edge.vertex1()->y() )); // remove this edge and its twin from the available edges (void)this->edges.erase(&edge); (void)this->edges.erase(edge.twin()); // get next points this->process_edge_neighbors(edge, &polyline.points); // get previous points Points pp; this->process_edge_neighbors(*edge.twin(), &pp); polyline.points.insert(polyline.points.begin(), pp.rbegin(), pp.rend()); // append polyline to result if it's not too small if (polyline.length() > this->max_width) polylines->push_back(polyline); } }
Polyline MotionPlanner::shortest_path(const Point &from, const Point &to) { // lazy generation of configuration space if (!this->initialized) this->initialize(); // if we have an empty configuration space, return a straight move if (this->islands.empty()) { Polyline p; p.points.push_back(from); p.points.push_back(to); return p; } // Are both points in the same island? int island_idx = -1; for (ExPolygons::const_iterator island = this->islands.begin(); island != this->islands.end(); ++island) { if (island->contains(from) && island->contains(to)) { // since both points are in the same island, is a direct move possible? // if so, we avoid generating the visibility environment if (island->contains(Line(from, to))) { Polyline p; p.points.push_back(from); p.points.push_back(to); return p; } island_idx = island - this->islands.begin(); break; } } // get environment ExPolygonCollection env = this->get_env(island_idx); if (env.expolygons.empty()) { // if this environment is empty (probably because it's too small), perform straight move // and avoid running the algorithms on empty dataset Polyline p; p.points.push_back(from); p.points.push_back(to); return p; // bye bye } // Now check whether points are inside the environment. Point inner_from = from; Point inner_to = to; if (!env.contains(from)) { // Find the closest inner point to start from. inner_from = this->nearest_env_point(env, from, to); } if (!env.contains(to)) { // Find the closest inner point to start from. inner_to = this->nearest_env_point(env, to, inner_from); } // perform actual path search MotionPlannerGraph* graph = this->init_graph(island_idx); Polyline polyline = graph->shortest_path(graph->find_node(inner_from), graph->find_node(inner_to)); polyline.points.insert(polyline.points.begin(), from); polyline.points.push_back(to); { // grow our environment slightly in order for simplify_by_visibility() // to work best by considering moves on boundaries valid as well ExPolygonCollection grown_env; offset(env, &grown_env.expolygons, +SCALED_EPSILON); // remove unnecessary vertices polyline.simplify_by_visibility(grown_env); } /* SVG svg("shortest_path.svg"); svg.draw(this->outer); svg.arrows = false; for (MotionPlannerGraph::adjacency_list_t::const_iterator it = graph->adjacency_list.begin(); it != graph->adjacency_list.end(); ++it) { Point a = graph->nodes[it - graph->adjacency_list.begin()]; for (std::vector<MotionPlannerGraph::neighbor>::const_iterator n = it->begin(); n != it->end(); ++n) { Point b = graph->nodes[n->target]; svg.draw(Line(a, b)); } } svg.arrows = true; svg.draw(from); svg.draw(inner_from, "red"); svg.draw(to); svg.draw(inner_to, "red"); svg.draw(*polyline, "red"); svg.Close(); */ return polyline; }
Polyline MotionPlannerGraph::shortest_path(size_t from, size_t to) { // this prevents a crash in case for some reason we got here with an empty adjacency list if (this->adjacency_list.empty()) return Polyline(); const weight_t max_weight = std::numeric_limits<weight_t>::infinity(); std::vector<weight_t> dist; std::vector<node_t> previous; { // number of nodes size_t n = this->adjacency_list.size(); // initialize dist and previous dist.clear(); dist.resize(n, max_weight); dist[from] = 0; // distance from 'from' to itself previous.clear(); previous.resize(n, -1); // initialize the Q with all nodes std::set<node_t> Q; for (node_t i = 0; i < n; ++i) Q.insert(i); while (!Q.empty()) { // get node in Q having the minimum dist ('from' in the first loop) node_t u; { double min_dist = -1; for (std::set<node_t>::const_iterator n = Q.begin(); n != Q.end(); ++n) { if (dist[*n] < min_dist || min_dist == -1) { u = *n; min_dist = dist[*n]; } } } Q.erase(u); // stop searching if we reached our destination if (u == to) break; // Visit each edge starting from node u const std::vector<neighbor> &neighbors = this->adjacency_list[u]; for (std::vector<neighbor>::const_iterator neighbor_iter = neighbors.begin(); neighbor_iter != neighbors.end(); ++neighbor_iter) { // neighbor node is v node_t v = neighbor_iter->target; // skip if we already visited this if (Q.find(v) == Q.end()) continue; // calculate total distance weight_t alt = dist[u] + neighbor_iter->weight; // if total distance through u is shorter than the previous // distance (if any) between 'from' and 'v', replace it if (alt < dist[v]) { dist[v] = alt; previous[v] = u; } } } } Polyline polyline; for (node_t vertex = to; vertex != -1; vertex = previous[vertex]) polyline.points.push_back(this->nodes[vertex]); polyline.points.push_back(this->nodes[from]); polyline.reverse(); return polyline; }
/** * Loads the globe from a YAML file. * @param node YAML node. */ void RuleGlobe::load(const YAML::Node &node) { if (node["data"]) { for (std::list<Polygon*>::iterator i = _polygons.begin(); i != _polygons.end(); ++i) { delete *i; } _polygons.clear(); loadDat(CrossPlatform::getDataFile(node["data"].as<std::string>())); } if (node["polygons"]) { for (std::list<Polygon*>::iterator i = _polygons.begin(); i != _polygons.end(); ++i) { delete *i; } _polygons.clear(); for (YAML::const_iterator i = node["polygons"].begin(); i != node["polygons"].end(); ++i) { Polygon *polygon = new Polygon(3); polygon->load(*i); _polygons.push_back(polygon); } } if (node["polylines"]) { for (std::list<Polyline*>::iterator i = _polylines.begin(); i != _polylines.end(); ++i) { delete *i; } _polylines.clear(); for (YAML::const_iterator i = node["polylines"].begin(); i != node["polylines"].end(); ++i) { Polyline *polyline = new Polyline(3); polyline->load(*i); _polylines.push_back(polyline); } } if (node["textures"]) { for (std::map<int, Texture*>::iterator i = _textures.begin(); i != _textures.end(); ++i) { delete i->second; } _textures.clear(); for (YAML::const_iterator i = node["textures"].begin(); i != node["textures"].end(); ++i) { int id = (*i)["id"].as<int>(); Texture *texture = new Texture(id); texture->load(*i); _textures[id] = texture; } } Globe::COUNTRY_LABEL_COLOR = node["countryColor"].as<int>(Globe::COUNTRY_LABEL_COLOR); Globe::CITY_LABEL_COLOR = node["cityColor"].as<int>(Globe::CITY_LABEL_COLOR); Globe::BASE_LABEL_COLOR = node["baseColor"].as<int>(Globe::BASE_LABEL_COLOR); Globe::LINE_COLOR = node["lineColor"].as<int>(Globe::LINE_COLOR); if (node["oceanPalette"]) { Globe::OCEAN_COLOR = Palette::blockOffset(node["oceanPalette"].as<int>(Globe::OCEAN_COLOR)); } }
const PolylineEdge *operator*() const { CARVE_ASSERT(idx >= 0 && idx < base->edgeCount()); return base->edge((size_t)idx); }
const Vertex *operator*() const { CARVE_ASSERT(idx >= 0 && idx < base->vertexCount()); return base->vertex((size_t)idx); }