Exemplo n.º 1
0
void placement_finder<DetectorT>::find_point_placements(T & shape_path)
{
    unsigned cmd;
    double new_x = 0.0;
    double new_y = 0.0;
    double old_x = 0.0;
    double old_y = 0.0;
    bool first = true;

    double total_distance = get_total_distance<T>(shape_path);
    shape_path.rewind(0);

    if (distance == 0) //Point data, not a line
    {
        double x, y;
        shape_path.vertex(&x,&y);
        find_point_placement(x, y);
        return;
    }

    if (total_distance < p.minimum_path_length)
        return;


    int num_labels = 1;
    if (p.label_spacing > 0)
        num_labels = static_cast<int> (floor(total_distance / pi.get_actual_label_spacing()));

    if (p.force_odd_labels && num_labels % 2 == 0)
        num_labels--;
    if (num_labels <= 0)
        num_labels = 1;

    //Read out the tolerance
    // No tolreance if not given (old behaviour)
    double tolerance_delta, tolerance;
    if (p.label_position_tolerance > 0)
    {
        tolerance = p.label_position_tolerance;
        tolerance_delta = std::max ( 1.0, p.label_position_tolerance/100.0 );
    }
    else
    {
        tolerance = 0.0;
        tolerance_delta = 1.0;
    }


    double distance = 0.0; // distance from last label
    double spacing = total_distance / num_labels;

    if (tolerance > spacing) tolerance = spacing;

    double target_distance = (spacing - tolerance) / 2; // first label should be placed at half the spacing
    double diff = 0.0;

    while (!agg::is_stop(cmd = shape_path.vertex(&new_x,&new_y))) //For each node in the shape
    {

        if (first || agg::is_move_to(cmd)) //Don't do any processing if it is the first node
        {
            first = false;
        }
        else
        {
            //Add the length of this segment to the total we have saved up
            double segment_length = std::sqrt(std::pow(old_x-new_x,2) + std::pow(old_y-new_y,2)); //Pythagoras
            distance += segment_length;

            //While we have enough distance to place text in
            while (distance > (target_distance + diff))
            {
                //Try place at the specified place
                double new_weight = (segment_length - (distance - target_distance  - diff))/segment_length;
                if (find_point_placement(old_x + (new_x-old_x)*new_weight, old_y + (new_y-old_y)*new_weight))
                {
                    distance -= target_distance; //Consume the spacing gap we have used up
                    target_distance = spacing; //Need to reset the target_distance as it is spacing/2 for the first label.
                    diff = 0.0;
                }
                else
                {
                    diff += tolerance_delta;
                    if (diff > tolerance) {
                        distance -= target_distance;
                        target_distance = spacing;
                        diff = 0.0;
                    }
                }
            }
        }

        old_x = new_x;
        old_y = new_y;
    }

}
bool placement_finder::find_line_placements(T & path, bool points)
{
    if (!layouts_.line_count()) return true; //TODO
    vertex_cache pp(path);

    bool success = false;
    while (pp.next_subpath())
    {
        if (points)
        {
            if (pp.length() <= 0.001)
            {
                success = find_point_placement(pp.current_position()) || success;
                continue;
            }
        }
        else
        {
            if ((pp.length() < text_props_->minimum_path_length * scale_factor_)
                ||
                (pp.length() <= 0.001) // Clipping removed whole geometry
                ||
                (pp.length() < layouts_.width()))
                {
                    continue;
                }
        }

        double spacing = get_spacing(pp.length(), points ? 0. : layouts_.width());

        //horizontal_alignment_e halign = layouts_.back()->horizontal_alignment();

        // halign == H_LEFT -> don't move
        if (horizontal_alignment_ == H_MIDDLE || horizontal_alignment_ == H_AUTO || horizontal_alignment_ == H_ADJUST)
        {
            if (!pp.forward(spacing / 2.0)) continue;
        }
        else if (horizontal_alignment_ == H_RIGHT)
        {
            if (!pp.forward(pp.length())) continue;
        }

        if (move_dx_ != 0.0) path_move_dx(pp, move_dx_);

        do
        {
            tolerance_iterator tolerance_offset(text_props_->label_position_tolerance * scale_factor_, spacing); //TODO: Handle halign
            while (tolerance_offset.next())
            {
                vertex_cache::scoped_state state(pp);
                if (pp.move(tolerance_offset.get())
                    && ((points && find_point_placement(pp.current_position()))
                        || (!points && single_line_placement(pp, text_props_->upright))))
                {
                    success = true;
                    break;
                }
            }
        } while (pp.forward(spacing));
    }
    return success;
}