Esempio n. 1
0
void CurveViewRange::normalize() {
  float xMin = m_xMin;
  float xMax = m_xMax;
  float yMin = m_yMin;
  float yMax = m_yMax;
  float newXMin = clipped((xMin+xMax)/2 - 5.3f, false);
  float newXMax = clipped((xMin+xMax)/2 + 5.3f, true);
  if (!std::isnan(newXMin) && !std::isnan(newXMax)) {
    m_xMin = newXMin;
    m_xMax = newXMax;
    m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax);
  }
  if (m_xMin < 0.0f) {
    m_xMin = -k_displayLeftMarginRatio*2.0f*5.3f;
    m_xMax = m_xMin + 2.0f*5.3f;
  }
  m_yAuto = false;
  float newYMin = clipped((yMin+yMax)/2 - 3.1f, false);
  float newYMax = clipped((yMin+yMax)/2 + 3.1f, true);
  if (!std::isnan(newYMin) && !std::isnan(newYMax)) {
    m_yMin = newYMin;
    m_yMax = newYMax;
    m_yGridUnit = computeGridUnit(Axis::Y, m_yMin, m_yMax);
  }
}
Esempio n. 2
0
		void generateTriangles(unsigned short *buffer, int resolution, int x1, int y1, int x2, int y2, unsigned char *clipBuffer)
		{
			for(int y = y1; y < y2; y += lodFactor)
			for(int x = x1; x < x2; x += lodFactor)
			{
				int position = y * resolution + x;

				int f1 = position + lodFactor + resolution * lodFactor;
				int f2 = position;
				int f3 = position + resolution * lodFactor;
				if(!clipped(f1, f2, f3, clipBuffer))
				{
					buffer[faceAmount++] = f1;
					buffer[faceAmount++] = f2;
					buffer[faceAmount++] = f3;
				}

				int f4 = position;
				int f5 = position + resolution * lodFactor + lodFactor;
				int f6 = position + lodFactor;
				if(!clipped(f1, f2, f3, clipBuffer))
				{
					buffer[faceAmount++] = f4;
					buffer[faceAmount++] = f5;
					buffer[faceAmount++] = f6;
				}
			}
		}
Esempio n. 3
0
		bool clipped(int f1, int f2, int f3, unsigned char *clipBuffer) const
		{
			bool f1Clip = clipped(f1, clipBuffer);
			bool f2Clip = clipped(f2, clipBuffer);
			bool f3Clip = clipped(f3, clipBuffer);

			if(f1Clip && f2Clip && f3Clip)
				return true;

			return false;
		}
Esempio n. 4
0
void
WPiano::clipCursor()
{
	if (!mouse_captured_)
		return;
	QRect v = viewport();
	QPoint p1 = mapToGlobal(v.topLeft());
	QPoint p2 = mapToGlobal(v.bottomRight());
	int x = clipped(QCursor::pos().x(), p1.x(), p2.x());
	int y = clipped(QCursor::pos().y(), p1.y(), p2.y());
	QCursor::setPos(QPoint(x, y));
}
 void operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     for (unsigned i=0;i<iterations_;++i)
     {
         for (mapnik::geometry_type & geom : paths)
         {
             poly_clipper clipped(geom,ps,
                                  agg::clipper_and,
                                  agg::clipper_non_zero,
                                  agg::clipper_non_zero,
                                  1);
             clipped.rewind(0);
             unsigned cmd;
             double x,y;
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {}
         }
     }
 }
Esempio n. 6
0
void
_cleanup_path(PathIterator& path, const agg::trans_affine& trans,
              bool remove_nans, bool do_clip,
              const agg::rect_base<double>& rect,
              e_snap_mode snap_mode, double stroke_width,
              bool do_simplify, bool return_curves,
              std::vector<double>& vertices,
              std::vector<npy_uint8>& codes)
{
    typedef agg::conv_transform<PathIterator>  transformed_path_t;
    typedef PathNanRemover<transformed_path_t> nan_removal_t;
    typedef PathClipper<nan_removal_t>         clipped_t;
    typedef PathSnapper<clipped_t>             snapped_t;
    typedef PathSimplifier<snapped_t>          simplify_t;
    typedef agg::conv_curve<simplify_t>        curve_t;

    transformed_path_t tpath(path, trans);
    nan_removal_t      nan_removed(tpath, remove_nans, path.has_curves());
    clipped_t          clipped(nan_removed, do_clip, rect);
    snapped_t          snapped(clipped, snap_mode, path.total_vertices(), stroke_width);
    simplify_t         simplified(snapped, do_simplify, path.simplify_threshold());

    vertices.reserve(path.total_vertices() * 2);
    codes.reserve(path.total_vertices());

    if (return_curves)
    {
        __cleanup_path(simplified, vertices, codes);
    }
    else
    {
        curve_t curve(simplified);
        __cleanup_path(curve, vertices, codes);
    }
}
Esempio n. 7
0
 bool validate() const
 {
     std::string expected_wkt("Polygon((181 286.666667,233 454,315 340,421 446,463 324,559 466,631 321.320755,631 234.386861,528 178,394 229,329 138,212 134,183 228,200 264,181 238.244444,181 286.666667),(313 190,440 256,470 248,510 305,533 237,613 263,553 397,455 262,405 378,343 287,249 334,229 191,313 190))");
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     if (paths.size() != 1)
     {
         std::clog << "paths.size() != 1\n";
         return false;
     }
     mapnik::geometry_type const& geom = paths[0];
     mapnik::vertex_adapter va(geom);
     poly_clipper clipped(extent_, va);
     unsigned cmd;
     double x,y;
     mapnik::geometry_type geom2(mapnik::geometry_type::types::Polygon);
     while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
         geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
     }
     std::string expect = expected_+".png";
     std::string actual = expected_+"_actual.png";
     auto env = mapnik::envelope(geom);
     if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
     {
         std::clog << "generating expected image: " << expect << "\n";
         render(geom2,env,expect);
     }
     render(geom2,env,actual);
     return benchmark::compare_images(actual,expect);
 }
Esempio n. 8
0
 bool operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         for ( mapnik::geometry_type const& geom : paths)
         {
             mapnik::vertex_adapter va(geom);
             poly_clipper clipped(extent_, va);
             unsigned cmd;
             double x,y;
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
                 count++;
             }
         }
         unsigned expected_count = 31;
         if (count != expected_count) {
             std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
Esempio n. 9
0
std::string clip_line(mapnik::box2d<double> const& bbox,
                      mapnik::geometry_type & geom)
{
    using line_clipper = agg::conv_clip_polyline<mapnik::geometry_type>;
    line_clipper clipped(geom);
    clipped.clip_box(bbox.minx(),bbox.miny(),bbox.maxx(),bbox.maxy());
    return dump_path(clipped);
}
Esempio n. 10
0
std::string clip_line(mapnik::box2d<double> const& bbox,
                      mapnik::path_type const& path)
{
    using line_clipper = agg::conv_clip_polyline<mapnik::vertex_adapter>;
    mapnik::vertex_adapter va(path);
    line_clipper clipped(va);
    clipped.clip_box(bbox.minx(),bbox.miny(),bbox.maxx(),bbox.maxy());
    return dump_path(clipped);
}
Esempio n. 11
0
 void operator() (geometry::polygon_vertex_adapter<double> & va)
 {
     using clipped_geometry_type = agg::conv_clip_polygon<geometry::polygon_vertex_adapter<double> >;
     using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
     clipped_geometry_type clipped(va);
     clipped.clip_box(clip_box_.minx(),clip_box_.miny(),clip_box_.maxx(),clip_box_.maxy());
     path_type path(t_, clipped, prj_trans_);
     path.vertex(&x_,&y_);
 }
Esempio n. 12
0
void CurveViewRange::roundAbscissa() {
  float xMin = m_xMin;
  float xMax = m_xMax;
  float newXMin = clipped(std::round((xMin+xMax)/2) - (float)Ion::Display::Width/2.0f, false);
  float newXMax = clipped(std::round((xMin+xMax)/2) + (float)Ion::Display::Width/2.0f-1.0f, true);
  if (std::isnan(newXMin) || std::isnan(newXMax)) {
    return;
  }
  m_xMin = newXMin;
  m_xMax = newXMax;
  if (m_xMin < 0.0f) {
    m_xMin = -k_displayLeftMarginRatio*(float)Ion::Display::Width;
    m_xMax = m_xMin+(float)Ion::Display::Width;
  }
  m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax);
  if (m_delegate) {
    m_delegate->didChangeRange(this);
  }
}
void  agg_renderer<T>::process(line_pattern_symbolizer const& sym,
                               mapnik::feature_ptr const& feature,
                               proj_transform const& prj_trans)
{
    typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
    typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
    typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
    typedef agg::renderer_base<agg::pixfmt_rgba32_plain> renderer_base;
    typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
    typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;

    agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
    agg::pixfmt_rgba32_plain pixf(buf);

    std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature);

    boost::optional<marker_ptr> mark = marker_cache::instance()->find(filename,true);
    if (!mark) return;

    if (!(*mark)->is_bitmap())
    {
        std::clog << "### Warning only images (not '" << filename << "') are supported in the line_pattern_symbolizer\n";
        return;
    }

    boost::optional<image_ptr> pat = (*mark)->get_bitmap_data();

    if (!pat) return;

    box2d<double> ext = query_extent_ * 1.1;
    renderer_base ren_base(pixf);
    agg::pattern_filter_bilinear_rgba8 filter;
    pattern_source source(*(*pat));
    pattern_type pattern (filter,source);
    renderer_type ren(ren_base, pattern);
    // TODO - should be sensitive to buffer size
    ren.clip_box(0,0,width_,height_);
    rasterizer_type ras(ren);
    //metawriter_with_properties writer = sym.get_metawriter();
    for (unsigned i=0;i<feature->num_geometries();++i)
    {
        geometry_type & geom = feature->get_geometry(i);
        if (geom.num_points() > 1)
        {
            clipped_geometry_type clipped(geom);
            clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy());
            path_type path(t_,clipped,prj_trans);
            ras.add_path(path);
            //if (writer.first) writer.first->add_line(path, *feature, t_, writer.second);
        }
    }
}
Esempio n. 14
0
bool Animation::update(TimingUpdateReason reason)
{
    if (!m_timeline)
        return false;

    PlayStateUpdateScope updateScope(*this, reason, DoNotSetCompositorPending);

    clearOutdated();
    bool idle = playStateInternal() == Idle;

    if (m_content) {
        double inheritedTime = idle || isNull(m_timeline->currentTimeInternal())
            ? nullValue()
            : currentTimeInternal();

        if (!isNull(inheritedTime)) {
            double timeForClipping = m_held && (!limited(inheritedTime) || isNull(m_startTime))
                // Use hold time when there is no start time.
                ? inheritedTime
                // Use calculated current time when the animation is limited.
                : calculateCurrentTime();
            if (clipped(timeForClipping))
                inheritedTime = nullValue();
        }
        // Special case for end-exclusivity when playing backwards.
        if (inheritedTime == 0 && m_playbackRate < 0)
            inheritedTime = -1;
        m_content->updateInheritedTime(inheritedTime, reason);
    }

    if ((idle || limited()) && !m_finished) {
        if (reason == TimingUpdateForAnimationFrame && (idle || hasStartTime())) {
            if (idle) {
                // TODO(dstockwell): Fire the cancel event.
            } else {
                const AtomicString& eventType = EventTypeNames::finish;
                if (executionContext() && hasEventListeners(eventType)) {
                    double eventCurrentTime = currentTimeInternal() * 1000;
                    m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, eventCurrentTime, timeline()->currentTime());
                    m_pendingFinishedEvent->setTarget(this);
                    m_pendingFinishedEvent->setCurrentTarget(this);
                    m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent);
                }
            }
            m_finished = true;
        }
    }
    ASSERT(!m_outdated);
    return !m_finished || std::isfinite(timeToEffectChange());
}
Esempio n. 15
0
 bool operator()() const
 {
     mapnik::geometry::geometry<double> geom;
     if (!mapnik::from_wkt(wkt_in_, geom))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     if (mapnik::geometry::is_empty(geom))
     {
         std::clog << "empty geom!\n";
         return false;
     }
     if (!geom.is<mapnik::geometry::polygon<double>>())
     {
         std::clog << "not a polygon!\n";
         return false;
     }
     mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         mapnik::geometry::polygon_vertex_adapter<double> va(poly);
         poly_clipper clipped(va,ps,
                              agg::clipper_and,
                              agg::clipper_non_zero,
                              agg::clipper_non_zero,
                              1);
         clipped.rewind(0);
         unsigned cmd;
         double x,y;
         while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
             count++;
         }
         unsigned expected_count = 31;
         if (count != expected_count) {
             std::clog << "test2: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
Esempio n. 16
0
 bool operator()() const
 {
     mapnik::geometry::geometry<double> geom;
     if (!mapnik::from_wkt(wkt_in_, geom))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     if (mapnik::geometry::is_empty(geom))
     {
         std::clog << "empty geom!\n";
         return false;
     }
     if (!geom.is<mapnik::geometry::polygon<double>>())
     {
         std::clog << "not a polygon!\n";
         return false;
     }
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
         mapnik::geometry::polygon_vertex_adapter<double> va(poly);
         conv_clip clipped(va);
         clipped.clip_box(
                     extent_.minx(),
                     extent_.miny(),
                     extent_.maxx(),
                     extent_.maxy());
         unsigned cmd;
         double x,y;
         // NOTE: this rewind is critical otherwise
         // agg_conv_adapter_vpgen will give garbage
         // values for the first vertex
         clipped.rewind(0);
         while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
             count++;
         }
         unsigned expected_count = 30;
         if (count != expected_count) {
             std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
Esempio n. 17
0
		void createFace(unsigned short *buffer, int direction, int f1, int f2, int f3, int resolution, unsigned char *clipBuffer)
		{
			if(clipped(f1, f2, f3, clipBuffer))
				return;

			if(direction < 0)
			{
				buffer[faceAmount++] = f1;
				buffer[faceAmount++] = f2;
				buffer[faceAmount++] = f3;
			}
			else
			{
				buffer[faceAmount++] = f2;
				buffer[faceAmount++] = f1;
				buffer[faceAmount++] = f3;
			}
		}
 void operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     for (unsigned i=0;i<iterations_;++i)
     {
         for ( mapnik::geometry_type & geom : paths)
         {
             poly_clipper clipped(extent_, geom);
             unsigned cmd;
             double x,y;
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {}
         }
     }
 }
Esempio n. 19
0
 bool validate() const
 {
     std::string expected_wkt("Polygon((212 134,329 138,394 229,528 178,631 234.4,631 321.3,559 466,463 324,421 446,315 340,233 454,181 286.7,181 238.2,200 264,183 228),(313 190,229 191,249 334,343 287,405 378,455 262,553 397,613 263,533 237,510 305,470 248,440 256))");
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     if (paths.size() != 1)
     {
         std::clog << "paths.size() != 1\n";
         return false;
     }
     mapnik::geometry_type const& geom = paths[0];
     mapnik::vertex_adapter va(geom);
     poly_clipper clipped(va,ps,
                          agg::clipper_and,
                          agg::clipper_non_zero,
                          agg::clipper_non_zero,
                          1);
     clipped.rewind(0);
     unsigned cmd;
     double x,y;
     mapnik::geometry_type geom2(mapnik::geometry_type::types::Polygon);
     while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
         geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
     }
     std::string expect = expected_+".png";
     std::string actual = expected_+"_actual.png";
     auto env = mapnik::envelope(geom);
     if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
     {
         std::clog << "generating expected image: " << expect << "\n";
         render(geom2,env,expect);
     }
     render(geom2,env,actual);
     return benchmark::compare_images(actual,expect);
 }
Esempio n. 20
0
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement_clipped()
{
    while (!geometries_to_process_.empty())
    {
        if (geo_itr_ == geometries_to_process_.end())
        {
            //Just processed the last geometry. Try next placement.
            if (!next_placement()) return false; //No more placements
            //Start again from begin of list
            geo_itr_ = geometries_to_process_.begin();
            continue; //Reexecute size check
        }

        typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
        typedef coord_transform<CoordTransform,clipped_geometry_type> path_type;
        clipped_geometry_type clipped(**geo_itr_);
        clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy());
        path_type path(t_, clipped, prj_trans_);

        finder_->clear_placements();
        if (points_on_line_) {
            finder_->find_point_placements(path);
        } else {
            finder_->find_line_placements(path);
        }
        if (!finder_->get_results().empty())
        {
            //Found a placement
            if (points_on_line_)
            {
                finder_->update_detector();
            }
            geo_itr_ = geometries_to_process_.erase(geo_itr_);
            if (writer_.first) writer_.first->add_text(
                finder_->get_results(), finder_->get_extents(),
                feature_, t_, writer_.second);
            return true;
        }
        //No placement for this geometry. Keep it in geometries_to_process_ for next try.
        geo_itr_++;
    }
    return false;
}
Esempio n. 21
0
void Square::render(SDL_Renderer * renderer)
{
    uint8_t a = 255;
    if (100 != alpha)
    {
        SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
        a = alpha * 255 / 100;
    }
    SDL_SetRenderDrawColor(renderer, red, green, blue, a);

    if (clipped())
    {
        SDL_Rect projection { rect.x, rect.y, clipping.w, clipping.h };
        SDL_RenderFillRect(renderer, &projection);
    }
    else
    {
        SDL_RenderFillRect(renderer, &rect);
    }
}
Esempio n. 22
0
 bool operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         for (mapnik::geometry_type const& geom : paths)
         {
             mapnik::vertex_adapter va(geom);
             poly_clipper clipped(va,ps,
                                  agg::clipper_and,
                                  agg::clipper_non_zero,
                                  agg::clipper_non_zero,
                                  1);
             clipped.rewind(0);
             unsigned cmd;
             double x,y;
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
                 count++;
             }
         }
         unsigned expected_count = 29;
         if (count != expected_count) {
             std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
Esempio n. 23
0
 bool operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         for (mapnik::geometry_type const& geom : paths)
         {
             mapnik::vertex_adapter va(geom);
             conv_clip clipped(va);
             clipped.clip_box(
                         extent_.minx(),
                         extent_.miny(),
                         extent_.maxx(),
                         extent_.maxy());
             unsigned cmd;
             double x,y;
             // NOTE: this rewind is critical otherwise
             // agg_conv_adapter_vpgen will give garbage
             // values for the first vertex
             clipped.rewind(0);
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
                 count++;
             }
         }
         unsigned expected_count = 31;
         if (count != expected_count) {
             std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                                mapnik::feature_impl & feature,
                                proj_transform const& prj_trans)
{
    composite_mode_e comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_);
    std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
    value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
    value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
    value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);
    value_double opacity = get<value_double, keys::opacity>(sym, feature, common_.vars_);
    agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
    auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
    if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform);

    cairo_save_restore guard(context_);
    context_.set_operator(comp_op);

    boost::optional<mapnik::marker_ptr> marker = mapnik::marker_cache::instance().find(filename,true);
    if (!marker || !(*marker)) return;

    unsigned offset_x=0;
    unsigned offset_y=0;
    box2d<double> const& clip_box = clipping_extent(common_);
    pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym, feature, common_.vars_);
    if (alignment == LOCAL_ALIGNMENT)
    {
        double x0 = 0.0;
        double y0 = 0.0;

        if (feature.num_geometries() > 0)
        {
            using clipped_geometry_type = agg::conv_clip_polygon<geometry_type>;
            using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
            clipped_geometry_type clipped(feature.get_geometry(0));
            clipped.clip_box(clip_box.minx(), clip_box.miny(),
                             clip_box.maxx(), clip_box.maxy());
            path_type path(common_.t_, clipped, prj_trans);
            path.vertex(&x0, &y0);
        }
        offset_x = std::abs(clip_box.width() - x0);
        offset_y = std::abs(clip_box.height() - y0);
    }

    if ((*marker)->is_bitmap())
    {
        cairo_pattern pattern(**((*marker)->get_bitmap_data()), opacity);
        pattern.set_extend(CAIRO_EXTEND_REPEAT);
        pattern.set_origin(offset_x, offset_y);
        context_.set_pattern(pattern);
    }
    else
    {
        mapnik::rasterizer ras;
        image_ptr image = render_pattern(ras, **marker, image_tr, 1.0); //
        cairo_pattern pattern(*image, opacity);
        pattern.set_extend(CAIRO_EXTEND_REPEAT);
        pattern.set_origin(offset_x, offset_y);
        context_.set_pattern(pattern);
    }

    agg::trans_affine tr;
    auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (geom_transform) {
        evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_);
    }

    vertex_converter<cairo_context,clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag>
    converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);

    if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
    converter.set<transform_tag>(); //always transform
    converter.set<affine_transform_tag>();
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

    for ( geometry_type & geom : feature.paths())
    {
        if (geom.size() > 2)
        {
            converter.apply(geom);
        }
    }
    // fill polygon
    context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD);
    context_.fill();
}
void
PointCloudProjector::synchronized_callback(const sensor_msgs::PointCloud2ConstPtr& points_msg,
        const samplereturn_msgs::PatchArrayConstPtr& patches_msg)
{
    // create patch output message
    samplereturn_msgs::PatchArray positioned_patches;
    positioned_patches.header = patches_msg->header;
    positioned_patches.cam_info = patches_msg->cam_info;

    // create marker array debug message
    visualization_msgs::MarkerArray vis_markers;

    // create camera model object
    image_geometry::PinholeCameraModel model;
    model.fromCameraInfo(patches_msg->cam_info);

    // ensure tf is ready
    if(!listener_.canTransform(clipping_frame_id_, patches_msg->header.frame_id,
                patches_msg->header.stamp))
    {
        patches_out.publish( positioned_patches );
        return;
    }

    // get camera origin in clipping frame
    tf::StampedTransform camera;
    listener_.lookupTransform(clipping_frame_id_, patches_msg->header.frame_id,
            patches_msg->header.stamp, camera);
    Eigen::Vector3d camera_origin;
    tf::vectorTFToEigen(camera.getOrigin(), camera_origin);

    // scale and transform pointcloud into clipping frame
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr colorpoints(new pcl::PointCloud<pcl::PointXYZRGB>),
        points_native(new pcl::PointCloud<pcl::PointXYZRGB>),
        points_scaled(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::fromROSMsg(*points_msg, *points_native);
    // this scale is a horible hack to fix the manipulator point clouds
    Eigen::Transform<float, 3, Eigen::Affine> trans;
    trans.setIdentity();
    trans.scale(config_.pointcloud_scale);
    pcl::transformPointCloud(*points_native, *points_scaled, trans);
    pcl_ros::transformPointCloud(clipping_frame_id_, *points_scaled, *colorpoints, listener_);

    // id counter for debug markers
    int mid = 0;
    for(const auto& patch : patches_msg->patch_array)
    {
        samplereturn_msgs::Patch positioned_patch(patch);
        cv_bridge::CvImagePtr cv_ptr_mask;
        try {
            cv_ptr_mask = cv_bridge::toCvCopy(patch.mask, "mono8");
        }
        catch (cv_bridge::Exception& e) {
            ROS_ERROR("cv_bridge mask exception: %s", e.what());
            continue;
        }

        cv::Point2f roi_offset(patch.image_roi.x_offset, patch.image_roi.x_offset);
        Eigen::Vector4d ground_plane;
        // assume ground plane at z=0, in base_link xy plane for manipulators
        ground_plane << 0,0,1,0;
        float dimension, angle;
        tf::Stamped<tf::Point> world_point;
        if(samplereturn::computeMaskPositionAndSize(listener_,
                    cv_ptr_mask->image, roi_offset,
                    model, patches_msg->header.stamp, patches_msg->header.frame_id,
                    ground_plane, "base_link",
                    &dimension, &angle, &world_point,
                    NULL))
        {
            // if sample size is outside bounds, skip this patch
            if ((dimension > config_.max_major_axis) ||
                    (dimension < config_.min_major_axis)) {
                continue;
            }
        }


        // find bounding box of mask
        cv::Rect rect;
        samplereturn::computeBoundingBox(cv_ptr_mask->image, &rect);

        // turn image space bounding box into 4 3d rays
        cv::Point2d patch_origin(patch.image_roi.x_offset,
                patch.image_roi.y_offset);
        std::vector<cv::Point2d> rpoints;
        rpoints.push_back(cv::Point2d(rect.x,            rect.y) +
                patch_origin);
        rpoints.push_back(cv::Point2d(rect.x,            rect.y+rect.height) +
                patch_origin);
        rpoints.push_back(cv::Point2d(rect.x+rect.width, rect.y+rect.height) +
                patch_origin);
        rpoints.push_back(cv::Point2d(rect.x+rect.width, rect.y) +
                patch_origin);
        std::vector<Eigen::Vector3d> rays;
        rays.resize(rpoints.size());
        std::transform(rpoints.begin(), rpoints.end(), rays.begin(),
                [model, patches_msg, this](cv::Point2d uv) -> Eigen::Vector3d
                {
                    cv::Point3d xyz = model.projectPixelTo3dRay(uv);
                    tf::Stamped<tf::Vector3> vect(tf::Vector3(xyz.x, xyz.y, xyz.z),
                        patches_msg->header.stamp,
                        patches_msg->header.frame_id);
                    tf::Stamped<tf::Vector3> vect_t;
                    listener_.transformVector(clipping_frame_id_, vect, vect_t);
                    Eigen::Vector3d ray;
                    tf::vectorTFToEigen(vect_t, ray);
                    return ray;
                });

        // clip point cloud by the planes of the bounding volume
        // described by the rays above
        // Add one more clipping plane at z=0 in the clipping frame
        // to remove noise points below the ground
        pcl::PointIndices::Ptr clipped(new pcl::PointIndices);
        for(size_t i=0;i<rays.size()+1;i++)
        {
            Eigen::Vector4f plane;
            if(i<rays.size())
            {
                plane.segment<3>(0) = -rays[i].cross(rays[(i+1)%4]).cast<float>();
                plane[3] = -plane.segment<3>(0).dot(camera_origin.cast<float>());
            }
            else
            {
                plane << 0,0,1, config_.bottom_clipping_depth;
            }
            pcl::PlaneClipper3D<pcl::PointXYZRGB> clip(plane);
            std::vector<int> newclipped;
            clip.clipPointCloud3D(*colorpoints,  newclipped, clipped->indices);
            clipped->indices.resize(newclipped.size());
            std::copy(newclipped.begin(), newclipped.end(),
                    clipped->indices.begin());
        }

        // bail if the clipped pointcloud is empty
        if(clipped->indices.size() == 0)
        {
            continue;
        }

        // publish clipped pointcloud if anybody is listening
        if(debug_points_out.getNumSubscribers()>0)
        {
            pcl::PointCloud<pcl::PointXYZRGB> clipped_pts;
            pcl::ExtractIndices<pcl::PointXYZRGB> extract;
            extract.setInputCloud(colorpoints);
            extract.setIndices(clipped);
            extract.filter(clipped_pts);
            sensor_msgs::PointCloud2 clipped_msg;
            pcl::toROSMsg(clipped_pts, clipped_msg);
            debug_points_out.publish( clipped_msg );
        }

        // compute suitable z value for this patch
        // First, find min, max and sum
        typedef std::tuple<float, float, float> stats_tuple;
        stats_tuple z_stats = std::accumulate(
                clipped->indices.begin(), clipped->indices.end(),
                std::make_tuple(std::numeric_limits<float>().max(),
                                std::numeric_limits<float>().min(),
                                0.0f),
                [colorpoints](stats_tuple sum, int idx) -> stats_tuple
                {
                    return std::make_tuple(
                        std::min(std::get<0>(sum), colorpoints->points[idx].z),
                        std::max(std::get<1>(sum), colorpoints->points[idx].z),
                        std::get<2>(sum) + colorpoints->points[idx].z);
                });
        // use sum to find mean
        float z_min = std::get<0>(z_stats);
        float z_max = std::get<1>(z_stats);
        float z_mean = std::get<2>(z_stats)/float(clipped->indices.size());
        // build histogram of values larger than mean
        float hist_min = z_min + (z_mean-z_min)*config_.hist_min_scale;
        ROS_DEBUG("z_min: %04.3f z_mean: %04.3f z_max: %04.3f z_sum: %4.2f hist_min:%04.3f",
                z_min, z_mean, z_max, std::get<2>(z_stats), hist_min);
        const int NHIST = 20;
        int z_hist[NHIST];
        bzero(z_hist, NHIST*sizeof(int));
        std::accumulate(clipped->indices.begin(), clipped->indices.end(), z_hist,
                [colorpoints, hist_min, z_max](int *z_hist, int idx) -> int *
                {
                    float z = colorpoints->points[idx].z;
                    if(z>hist_min)
                    {
                        int zidx = floor((z-hist_min)*NHIST/(z_max-hist_min));
                        z_hist[zidx] ++;
                    }
                    return z_hist;
                });
        char debughist[2048];
        int pos=0;
        for(int i=0;i<NHIST;i++)
        {
            pos += snprintf(debughist+pos, 2048-pos, "%d, ", z_hist[i]);
        }
        debughist[pos] = '\x00';
        ROS_DEBUG("hist: %s", debughist);
        // select the most common value larger than the mean
        int * argmax = std::max_element( z_hist, z_hist + NHIST );
        ROS_DEBUG("argmax: %d", int(argmax - z_hist));
        float z_peak = (argmax - z_hist)*(z_max - hist_min)/NHIST + hist_min;
        if(z_peak>config_.maximum_patch_height)
        {
            ROS_INFO("Clipping z to max, was %f", z_peak);
            z_peak = config_.maximum_patch_height;
        }

        // project center of patch until it hits z_peak
        cv::Point2d uv = cv::Point2d(rect.x + rect.width/2, rect.y + rect.height/2) + patch_origin;
        cv::Point3d cvxyz = model.projectPixelTo3dRay(uv);
        tf::Stamped<tf::Vector3> patch_ray(
                tf::Vector3(
                    cvxyz.x,
                    cvxyz.y,
                    cvxyz.z),
                patches_msg->header.stamp,
                patches_msg->header.frame_id);
        tf::Stamped<tf::Vector3> clipping_ray;
        listener_.transformVector( clipping_frame_id_, patch_ray, clipping_ray);
        clipping_ray.normalize();
        double r = (z_peak - camera_origin.z())/clipping_ray.z();
        // finally, compute expected object position
        tf::Stamped<tf::Vector3> stamped_camera_origin(
                tf::Vector3(camera_origin.x(),
                    camera_origin.y(),
                    camera_origin.z()),
                patches_msg->header.stamp,
                clipping_frame_id_);

        tf::Vector3 object_position = stamped_camera_origin + r*clipping_ray;

        ROS_DEBUG_STREAM("patch_ray: (" <<
                patch_ray.x() << ", " << patch_ray.y() << ", " << patch_ray.z() << ") ");
        ROS_DEBUG_STREAM("clipping_ray: (" <<
                clipping_ray.x() << ", " << clipping_ray.y() << ", " << clipping_ray.z() << ") " << " z_peak: " << z_peak << " r: " << r);

        // put corresponding point_stamped in output message
        tf::Stamped<tf::Vector3> point(
                object_position,
                patches_msg->header.stamp,
                clipping_frame_id_);
        if(listener_.canTransform(output_frame_id_, point.frame_id_, point.stamp_))
        {
            tf::Stamped<tf::Vector3> output_point;
            listener_.transformPoint(output_frame_id_, point, output_point);
            tf::pointStampedTFToMsg(output_point, positioned_patch.world_point);
        }
        else
        {
            tf::pointStampedTFToMsg(point, positioned_patch.world_point);
        }
        positioned_patches.patch_array.push_back(positioned_patch);

        if(debug_marker_out.getNumSubscribers()>0)
        {
            visualization_msgs::Marker marker;
            marker.id = mid++;
            marker.type = visualization_msgs::Marker::SPHERE;
            marker.action = visualization_msgs::Marker::ADD;
            marker.header = positioned_patch.world_point.header;
            marker.pose.position = positioned_patch.world_point.point;
            marker.scale.x = 0.02;
            marker.scale.y = 0.02;
            marker.scale.z = 0.02;
            marker.color.r = 0.0;
            marker.color.g = 0.0;
            marker.color.b = 1.0;
            marker.color.a = 1.0;
            vis_markers.markers.push_back(marker);
        }
    }

    patches_out.publish( positioned_patches );

    if(debug_marker_out.getNumSubscribers()>0)
    {
        debug_marker_out.publish(vis_markers);
    }
}
Esempio n. 26
0
void wxNonOwnedWindow::HandleQueuedPaintRequests()
{
    if ( m_toPaint->IsEmpty() )
        return; // nothing to do

    if ( IsFrozen() || !IsShown() )
    {
        // nothing to do if the window is frozen or hidden; clear the queue
        // and return (note that it's OK to clear the queue even if the window
        // is frozen, because Thaw() calls Refresh()):
        m_toPaint->Clear();
        return;
    }

    // process queued paint requests:
    wxRect winRect(wxPoint(0, 0), GetSize());
    wxRect paintedRect;

    // important note: all DCs created from now until m_isPainting is reset to
    // false will not update the front buffer as this flag indicates that we'll
    // blit the entire back buffer to front soon
    m_isPainting = true;

    int requestsCount = 0;

    wxRect request;
    while ( m_toPaint->GetNext(request) )
    {
        requestsCount++;
        wxRect clipped(request);
        clipped.Intersect(winRect);
        if ( clipped.IsEmpty() )
            continue; // nothing to refresh

        wxLogTrace(TRACE_PAINT,
                   "%p ('%s'): processing paint request [%i,%i,%i,%i]",
                   this, GetName().c_str(),
                   clipped.x, clipped.y, clipped.GetRight(), clipped.GetBottom());

        PaintWindow(clipped);

        // remember rectangle covering all repainted areas:
        if ( paintedRect.IsEmpty() )
            paintedRect = clipped;
        else
            paintedRect.Union(clipped);
    }

    m_isPainting = false;

    m_toPaint->Clear();

    if ( paintedRect.IsEmpty() )
        return; // no painting occurred, no need to flip

    // Flip the surface to make the changes visible. Note that the rectangle we
    // flip is *superset* of the union of repainted rectangles (created as
    // "rectangles union" by wxRect::Union) and so some parts of the back
    // buffer that we didn't touch in this HandleQueuedPaintRequests call will
    // be copied to the front buffer as well. This is safe/correct thing to do
    // *only* because wx always use wxIDirectFBSurface::FlipToFront() and so
    // the back and front buffers contain the same data.
    //
    // Note that we do _not_ split m_toPaint into disjoint rectangles and
    // do FlipToFront() for each of them, because that could result in visible
    // updating of the screen; instead, we prefer to flip everything at once.

    DFBRegion r = {paintedRect.GetLeft(), paintedRect.GetTop(),
                   paintedRect.GetRight(), paintedRect.GetBottom()};
    DFBRegion *rptr = (winRect == paintedRect) ? NULL : &r;

    GetDfbSurface()->FlipToFront(rptr);

    wxLogTrace(TRACE_PAINT,
               "%p ('%s'): processed %i paint requests, flipped surface: [%i,%i,%i,%i]",
               this, GetName().c_str(),
               requestsCount,
               paintedRect.x, paintedRect.y,
               paintedRect.GetRight(), paintedRect.GetBottom());
}
void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                              mapnik::feature_ptr const& feature,
                              proj_transform const& prj_trans)
{
    typedef agg::conv_clip_polygon<geometry_type> clipped_geometry_type;
    typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
    typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
    typedef agg::wrap_mode_repeat wrap_x_type;
    typedef agg::wrap_mode_repeat wrap_y_type;
    typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_plain,
        agg::row_accessor<agg::int8u>, agg::pixel32_type> rendering_buffer;
    typedef agg::image_accessor_wrap<rendering_buffer,
        wrap_x_type,
        wrap_y_type> img_source_type;

    typedef agg::span_pattern_rgba<img_source_type> span_gen_type;

    typedef agg::renderer_scanline_aa<ren_base,
        agg::span_allocator<agg::rgba8>,
        span_gen_type> renderer_type;


    agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
    agg::pixfmt_rgba32_plain pixf(buf);
    ren_base renb(pixf);

    agg::scanline_u8 sl;
    ras_ptr->reset();
    set_gamma_method(sym,ras_ptr);

    std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature);
    boost::optional<mapnik::marker_ptr> marker;
    if ( !filename.empty() )
    {
        marker = marker_cache::instance()->find(filename, true);
    }
    else
    {
        std::clog << "### Warning: file not found: " << filename << "\n";
    }

    if (!marker) return;

    if (!(*marker)->is_bitmap())
    {
        std::clog << "### Warning only images (not '" << filename << "') are supported in the polygon_pattern_symbolizer\n";
        return;
    }


    boost::optional<image_ptr> pat = (*marker)->get_bitmap_data();

    if (!pat) return;

    unsigned w=(*pat)->width();
    unsigned h=(*pat)->height();
    agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)(*pat)->getBytes(),w,h,w*4);
    agg::span_allocator<agg::rgba8> sa;
    agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_plain,
        agg::row_accessor<agg::int8u>, agg::pixel32_type> pixf_pattern(pattern_rbuf);
    img_source_type img_src(pixf_pattern);

    unsigned num_geometries = feature->num_geometries();

    pattern_alignment_e align = sym.get_alignment();
    unsigned offset_x=0;
    unsigned offset_y=0;

    if (align == LOCAL_ALIGNMENT)
    {
        double x0=0,y0=0;
        if (num_geometries>0) // FIXME: hmm...?
        {
            clipped_geometry_type clipped(feature->get_geometry(0));
            clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy());
            path_type path(t_,clipped,prj_trans);
            path.vertex(&x0,&y0);
        }
        offset_x = unsigned(width_-x0);
        offset_y = unsigned(height_-y0);
    }

    span_gen_type sg(img_src, offset_x, offset_y);
    renderer_type rp(renb,sa, sg);
    //metawriter_with_properties writer = sym.get_metawriter();
    for (unsigned i=0;i<num_geometries;++i)
    {
        geometry_type & geom = feature->get_geometry(i);
        if (geom.num_points() > 2)
        {
            clipped_geometry_type clipped(geom);
            clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy());
            path_type path(t_,clipped,prj_trans);
            ras_ptr->add_path(path);
            //if (writer.first) writer.first->add_polygon(path, *feature, t_, writer.second);
        }
    }
    agg::render_scanlines(*ras_ptr, sl, rp);
}
Esempio n. 28
0
Py::Object
_path_module::convert_path_to_polygons(const Py::Tuple& args)
{
    typedef agg::conv_transform<PathIterator>  transformed_path_t;
    typedef PathNanRemover<transformed_path_t> nan_removal_t;
    typedef PathClipper<nan_removal_t>         clipped_t;
    typedef PathSimplifier<clipped_t>          simplify_t;
    typedef agg::conv_curve<simplify_t>        curve_t;

    typedef std::vector<double> vertices_t;

    args.verify_length(4);

    PathIterator path(args[0]);
    agg::trans_affine trans = py_to_agg_transformation_matrix(args[1].ptr(), false);
    double width = Py::Float(args[2]);
    double height = Py::Float(args[3]);

    bool do_clip = width != 0.0 && height != 0.0;

    bool simplify = path.should_simplify();

    transformed_path_t tpath(path, trans);
    nan_removal_t      nan_removed(tpath, true, path.has_curves());
    clipped_t          clipped(nan_removed, do_clip, width, height);
    simplify_t         simplified(clipped, simplify, path.simplify_threshold());
    curve_t            curve(simplified);

    Py::List polygons;
    vertices_t polygon;
    double x, y;
    unsigned code;

    polygon.reserve(path.total_vertices() * 2);

    while ((code = curve.vertex(&x, &y)) != agg::path_cmd_stop)
    {
        if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly)
        {
            if (polygon.size() >= 2)
            {
                polygon.push_back(polygon[0]);
                polygon.push_back(polygon[1]);
                _add_polygon(polygons, polygon);
            }
            polygon.clear();
        }
        else
        {
            if (code == agg::path_cmd_move_to)
            {
                _add_polygon(polygons, polygon);
                polygon.clear();
            }
            polygon.push_back(x);
            polygon.push_back(y);
        }
    }

    _add_polygon(polygons, polygon);

    return polygons;
}
Esempio n. 29
0
    bool validate() const
    {
        mapnik::geometry::geometry<double> geom;
        if (!mapnik::from_wkt(wkt_in_, geom))
        {
            throw std::runtime_error("Failed to parse WKT");
        }
        if (mapnik::geometry::is_empty(geom))
        {
            std::clog << "empty geom!\n";
            return false;
        }
        if (!geom.is<mapnik::geometry::polygon<double>>())
        {
            std::clog << "not a polygon!\n";
            return false;
        }
        mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
        mapnik::geometry::polygon_vertex_adapter<double> va(poly);


        conv_clip clipped(va);
        clipped.clip_box(
                    extent_.minx(),
                    extent_.miny(),
                    extent_.maxx(),
                    extent_.maxy());


        clipped.rewind(0);
        mapnik::geometry::polygon<double> poly2;
        mapnik::geometry::linear_ring<double> ring;
        // exterior ring
        unsigned cmd;
        double x, y, x0, y0;
        while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
        {
            if (cmd == mapnik::SEG_MOVETO)
            {
                x0 = x; y0 = y;
            }

            if (cmd == mapnik::SEG_CLOSE)
            {
                ring.emplace_back(x0, y0);
                break;
            }
            ring.emplace_back(x,y);
        }
        poly2.push_back(std::move(ring));
        // interior rings
        ring.clear();
        while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
        {
            if (cmd == mapnik::SEG_MOVETO)
            {
                x0 = x; y0 = y;
            }
            else if (cmd == mapnik::SEG_CLOSE)
            {
                ring.emplace_back(x0,y0);
                poly2.push_back(std::move(ring));
                ring.clear();
                continue;
            }
            ring.emplace_back(x,y);
        }

        std::string expect = expected_+".png";
        std::string actual = expected_+"_actual.png";
        mapnik::geometry::multi_polygon<double> mp;
        mp.emplace_back(poly2);
        auto env = mapnik::geometry::envelope(mp);
        if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
        {
            std::clog << "generating expected image: " << expect << "\n";
            render(mp,env,expect);
        }
        render(mp,env,actual);
        return benchmark::compare_images(actual,expect);
    }
Esempio n. 30
0
Py::Object
_path_module::convert_to_svg(const Py::Tuple& args)
{
    args.verify_length(5);

    PathIterator path(args[0]);
    agg::trans_affine trans = py_to_agg_transformation_matrix(args[1].ptr(), false);

    Py::Object clip_obj = args[2];
    bool do_clip;
    agg::rect_base<double> clip_rect(0, 0, 0, 0);
    if (clip_obj.isNone() || !clip_obj.isTrue())
    {
        do_clip = false;
    }
    else
    {
        double x1, y1, x2, y2;
        Py::Tuple clip_tuple(clip_obj);
        x1 = Py::Float(clip_tuple[0]);
        y1 = Py::Float(clip_tuple[1]);
        x2 = Py::Float(clip_tuple[2]);
        y2 = Py::Float(clip_tuple[3]);
        clip_rect.init(x1, y1, x2, y2);
        do_clip = true;
    }

    bool simplify;
    Py::Object simplify_obj = args[3];
    if (simplify_obj.isNone())
    {
        simplify = path.should_simplify();
    }
    else
    {
        simplify = simplify_obj.isTrue();
    }

    int precision = Py::Int(args[4]);

    #if PY_VERSION_HEX < 0x02070000
    char format[64];
    snprintf(format, 64, "%s.%dg", "%", precision);
    #endif

    typedef agg::conv_transform<PathIterator>  transformed_path_t;
    typedef PathNanRemover<transformed_path_t> nan_removal_t;
    typedef PathClipper<nan_removal_t>         clipped_t;
    typedef PathSimplifier<clipped_t>          simplify_t;

    transformed_path_t tpath(path, trans);
    nan_removal_t      nan_removed(tpath, true, path.has_curves());
    clipped_t          clipped(nan_removed, do_clip, clip_rect);
    simplify_t         simplified(clipped, simplify, path.simplify_threshold());

    size_t buffersize = path.total_vertices() * (precision + 5) * 4;
    char* buffer = (char *)malloc(buffersize);
    char* p = buffer;

    const char codes[] = {'M', 'L', 'Q', 'C'};
    const int  waits[] = {  1,   1,   2,   3};

    int wait = 0;
    unsigned code;
    double x = 0, y = 0;
    while ((code = simplified.vertex(&x, &y)) != agg::path_cmd_stop)
    {
        if (wait == 0)
        {
            *p++ = '\n';

            if (code == 0x4f)
            {
                *p++ = 'z';
                *p++ = '\n';
                continue;
            }

            *p++ = codes[code-1];
            wait = waits[code-1];
        }
        else
        {
            *p++ = ' ';
        }

        #if PY_VERSION_HEX >= 0x02070000
        char* str;
        str = PyOS_double_to_string(x, 'g', precision, 0, NULL);
        p += snprintf(p, buffersize - (p - buffer), str);
        PyMem_Free(str);
        *p++ = ' ';
        str = PyOS_double_to_string(y, 'g', precision, 0, NULL);
        p += snprintf(p, buffersize - (p - buffer), str);
        PyMem_Free(str);
        #else
        char str[64];
        PyOS_ascii_formatd(str, 64, format, x);
        p += snprintf(p, buffersize - (p - buffer), str);
        *p++ = ' ';
        PyOS_ascii_formatd(str, 64, format, y);
        p += snprintf(p, buffersize - (p - buffer), str);
        #endif

        --wait;
    }

    #if PY3K
    PyObject* result = PyUnicode_FromStringAndSize(buffer, p - buffer);
    #else
    PyObject* result = PyString_FromStringAndSize(buffer, p - buffer);
    #endif
    free(buffer);

    return Py::Object(result, true);
}