BlinkenArea - GitList
Repositories
Blog
Wiki
dxfngc
Code
Commits
Branches
Tags
Search
Tree:
48bbb1b
Branches
Tags
master
dxfngc
src
polygons.cpp
implement converting paths of layer into CGAL polygons
Stefan Schuermans
commited
48bbb1b
at 2013-01-27 16:03:24
polygons.cpp
Blame
History
Raw
/* drawing (DXF) to G-code (NGC) converter * Copyright 2013 Stefan Schuermans <stefan@schuermans.info> * Copyleft: CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/ */ #include <boost/shared_ptr.hpp> #include <iostream> #include <vector> #include <CGAL/Exact_predicates_exact_constructions_kernel.h> #include <CGAL/Polygon_2.h> #include <CGAL/Polygon_with_holes_2.h> #include <CGAL/create_offset_polygons_2.h> #include <CGAL/Boolean_set_operations_2.h> #include "layer.h" #include "path.h" #include "point.h" #include "polygons.h" /** * @brief clear all polygons */ void Polygons::clear() { mPolys.clear(); } /** * @brief add polygons from layer * @param[in] layer layer to obtain the polygons from * @param[in] eqDist maximum distance of two points to be considered equal * @return if the layer could be converted to polygons and imported */ bool Polygons::addLayer(const Layer &layer, double eqDist) { // convert all paths to simple polygons CgPolyVec simples; Layer::Paths::const_iterator path; for (path = layer.mPaths.begin(); path != layer.mPaths.end(); ++path) { // skip empty paths if (path->mPoints.empty()) continue; // check that path is closed if (!path->mPoints.front().equals(path->mPoints.back(), eqDist)) { std::cerr << "path not closed" << std::endl; return false; } // create simple polygon from path // - do not add last point to polygon, as it is the same as the first one CgPoly simple; Path::Points::const_iterator pt; for (pt = path->mPoints.begin(); pt + 1 != path->mPoints.end(); ++pt) simple.push_back(CgPoint(pt->mX, pt->mY)); // check that polygon is simple if (!simple.is_simple()) { std::cerr << "path is not simple (maybe self-itersecting?)" << std::endl; return false; } // ensure orientation is clockwise (must be the same for all polygons) if (simple.is_clockwise_oriented()) simple.reverse_orientation(); // collect polygons simples.push_back(simple); } // for path // check that no partly overlaps are present // deterine which polygon is contained in which one std::vector<ssize_t> contained_in; // idx: contained poly, val: containing poly ssize_t ia, ib; CgPolyVec::const_iterator a, b; for (a = simples.begin(); a != simples.end(); ++a) contained_in.push_back(-1); // not contained in any polygon for (a = simples.begin(), ia = 0; a != simples.end(); ++a, ++ia) { b = a; ib = ia; for (++b, ++ib; b != simples.end(); ++b, ++ib) { // A and B intersect each other if (CGAL::do_intersect(*a, *b)) { // compute differences A - B and B - A CgPolyHolesVec a_b, b_a; CGAL::difference(*a, *b, std::back_inserter(a_b)); CGAL::difference(*b, *a, std::back_inserter(b_a)); if (a_b.empty()) { // A and B are identical if (b_a.empty()) { std::cerr << "duplicate polygons found - meaning is undefined" << std::endl; return false; } // B contains A (A is hole in B) else { if (contained_in.at(ia) >= 0) { std::cerr << "polygon contained in multiple polygons" " - meaning is undefined" << std::endl; return false; } contained_in.at(ia) = ib; } } else { // A contains B (B is hole in A) if (b_a.empty()) { if (contained_in.at(ib) >= 0) { std::cerr << "polygon contained in multiple polygons" " - meaning is undefined" << std::endl; return false; } contained_in.at(ib) = ia; } // A and B overlap partly else { std::cerr << "polygons overlap partly - meaning is undefined" << std::endl; return false; } } } } // for b } // for a // add found polygons to member variable for (ia = 0; (size_t)ia < contained_in.size(); ++ia) { // outer polygon if (contained_in.at(ia) < 0) { CgPolyHoles poly(simples.at(ia)); // find and add holes for (ib = 0; (size_t)ib < contained_in.size(); ++ib) if (contained_in.at(ib) == ia) poly.add_hole(simples.at(ib)); // add polygon to member variable mPolys.push_back(poly); } } return true; } /** * @brief load polygons from layer * @param[in] layer layer to obtain the polygons from * @param[in] eqDist maximum distance of two points to be considered equal * @return if the layer could be converted to polygons and imported */ bool Polygons::loadLayer(const Layer &layer, double eqDist) { clear(); return addLayer(layer, eqDist); }