147 lines
5.6 KiB
C++
147 lines
5.6 KiB
C++
/*****************************************************************************
|
|
*
|
|
* This file is part of Mapnik (c++ mapping toolkit)
|
|
*
|
|
* Copyright (C) 2006 Artem Pavlenko
|
|
* Copyright (C) 2006 10East Corp.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*****************************************************************************/
|
|
|
|
//$Id$
|
|
|
|
#ifndef __PLACEMENT_FINDER__
|
|
#define __PLACEMENT_FINDER__
|
|
|
|
#include <mapnik/ctrans.hpp>
|
|
#include <mapnik/label_collision_detector.hpp>
|
|
#include <mapnik/text_symbolizer.hpp>
|
|
#include <mapnik/shield_symbolizer.hpp>
|
|
#include <mapnik/geometry.hpp>
|
|
#include <mapnik/text_path.hpp>
|
|
#include <mapnik/text_placements.hpp>
|
|
|
|
#include <queue>
|
|
|
|
namespace mapnik
|
|
{
|
|
typedef text_path placement_element;
|
|
|
|
struct placement : boost::noncopyable
|
|
{
|
|
placement(string_info & info_, shield_symbolizer const& sym, double scale_factor, unsigned w, unsigned h, bool has_dimensions_= false);
|
|
|
|
placement(string_info & info_, text_symbolizer const& sym, double scale_factor);
|
|
|
|
~placement();
|
|
|
|
string_info & info; // should only be used for finding placement. doesn't necessarily match placements.vertex() values
|
|
|
|
double scale_factor_;
|
|
label_placement_e label_placement;
|
|
|
|
std::queue< box2d<double> > envelopes;
|
|
|
|
//output
|
|
boost::ptr_vector<placement_element> placements;
|
|
|
|
int wrap_width;
|
|
bool wrap_before; // wraps text at wrap_char immediately before current word
|
|
unsigned char wrap_char;
|
|
int text_ratio;
|
|
|
|
int label_spacing; // distance between repeated labels on a single geometry
|
|
unsigned label_position_tolerance; //distance the label can be moved on the line to fit, if 0 the default is used
|
|
bool force_odd_labels; //Always try render an odd amount of labels
|
|
|
|
double max_char_angle_delta;
|
|
double minimum_distance;
|
|
double minimum_padding;
|
|
double minimum_path_length;
|
|
bool avoid_edges;
|
|
bool has_dimensions;
|
|
bool allow_overlap;
|
|
std::pair<double, double> dimensions;
|
|
bool collect_extents;
|
|
box2d<double> extents;
|
|
};
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
|
class placement_finder : boost::noncopyable
|
|
{
|
|
public:
|
|
placement_finder(DetectorT & detector);
|
|
placement_finder(DetectorT & detector, box2d<double> const& extent);
|
|
|
|
//Try place a single label at the given point
|
|
void find_point_placement(placement & p, text_placement_info_ptr po, double pos_x, double pos_y, double angle=0.0, unsigned line_spacing=0, unsigned character_spacing=0);
|
|
|
|
//Iterate over the given path, placing point labels with respect to label_spacing
|
|
template <typename T>
|
|
void find_point_placements(placement & p, text_placement_info_ptr po, T & path);
|
|
|
|
//Iterate over the given path, placing line-following labels with respect to label_spacing
|
|
template <typename T>
|
|
void find_line_placements(placement & p, text_placement_info_ptr po, T & path);
|
|
|
|
void update_detector(placement & p);
|
|
|
|
void clear();
|
|
|
|
private:
|
|
///Helpers for find_line_placement
|
|
|
|
///Returns a possible placement on the given line, does not test for collisions
|
|
//index: index of the node the current line ends on
|
|
//distance: distance along the given index that the placement should start at, this includes the offset,
|
|
// as such it may be > or < the length of the current line, so this must be checked for
|
|
//orientation: if set to != 0 the placement will be attempted with the given orientation
|
|
// otherwise it will autodetect the orientation.
|
|
// If >= 50% of the characters end up upside down, it will be retried the other way.
|
|
// RETURN: 1/-1 depending which way up the string ends up being.
|
|
std::auto_ptr<placement_element> get_placement_offset(placement & p,
|
|
const std::vector<vertex2d> & path_positions,
|
|
const std::vector<double> & path_distances,
|
|
int & orientation, unsigned index, double distance);
|
|
|
|
///Tests wether the given placement_element be placed without a collision
|
|
// Returns true if it can
|
|
// NOTE: This edits p.envelopes so it can be used afterwards (you must clear it otherwise)
|
|
bool test_placement(placement & p, const std::auto_ptr<placement_element> & current_placement, const int & orientation);
|
|
|
|
///Does a line-circle intersect calculation
|
|
// NOTE: Follow the strict pre conditions
|
|
// Pre Conditions: x1,y1 is within radius distance of cx,cy. x2,y2 is outside radius distance of cx,cy
|
|
// This means there is exactly one intersect point
|
|
// Result is returned in ix, iy
|
|
void find_line_circle_intersection(
|
|
const double &cx, const double &cy, const double &radius,
|
|
const double &x1, const double &y1, const double &x2, const double &y2,
|
|
double &ix, double &iy);
|
|
|
|
///General Internals
|
|
|
|
|
|
|
|
DetectorT & detector_;
|
|
box2d<double> const& dimensions_;
|
|
};
|
|
}
|
|
|
|
#endif
|
|
|