<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 <NAME>
 *
 * 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
 *
 *****************************************************************************/

// mapnik
#include <mapnik/group/group_layout_manager.hpp>

// boost
#include <boost/variant.hpp>

// std
#include <cmath>

namespace mapnik
{

// This visitor will process offsets for the given layout
struct process_layout : public boost::static_visitor<>
{
    // The vector containing the existing, centered item bounding boxes
    const vector<bound_box> &member_boxes_;
    
    // The vector to populate with item offsets
    vector<pixel_position> &member_offsets_;
    
    // The origin point of the member boxes
    // i.e. The member boxes are positioned around input_origin,
    //      and the offset values should position them around (0,0)
    const pixel_position &input_origin_;

    process_layout(const vector<bound_box> &member_bboxes, 
                   vector<pixel_position> &member_offsets,
                   const pixel_position &input_origin)
       : member_boxes_(member_bboxes), 
         member_offsets_(member_offsets),
         input_origin_(input_origin)
    {
    }

    // arrange group memebers in centered, horizontal row
    void operator()(simple_row_layout const& layout) const
    {
        double total_width = (member_boxes_.size() - 1) * layout.get_item_margin();
        for (auto const& box : member_boxes_)
        {
            total_width += box.width();
        }
        
        double x_offset = -(total_width / 2.0);
        for (auto const& box : member_boxes_)
        {
            member_offsets_.push_back(pixel_position(x_offset - box.minx(), -input_origin_.y));
            x_offset += box.width() + layout.get_item_margin();
        }
    }

    // arrange group members in x horizontal pairs of 2,
    // one to the left and one to the right of center in each pair
    void operator()(pair_layout const& layout) const
    {
        member_offsets_.resize(member_boxes_.size());
        double y_margin = layout.get_item_margin();
        double x_margin = y_margin / 2.0;

        if (member_boxes_.size() == 1)
        {
            member_offsets_[0] = pixel_position(0, 0) - input_origin_;
            return;
        }

        bound_box layout_box;
        size_t middle_ifirst = (member_boxes_.size() - 1) >> 1, top_i = 0, bottom_i = 0;
        if (middle_ifirst % 2 == 0)
        {
            layout_box = make_horiz_pair(0, 0.0, 0, x_margin, layout.get_max_difference());
            top_i = middle_ifirst - 2;
            bottom_i = middle_ifirst + 2;
        }
        else
        {
            top_i = middle_ifirst - 1;
            bottom_i = middle_ifirst + 1;
        }

        while (bottom_i >= 0 && top_i < member_offsets_.size())
        {
            layout_box.expand_to_include(make_horiz_pair(top_i, layout_box.miny() - y_margin, -1, x_margin, layout.get_max_difference()));
            layout_box.expand_to_include(make_horiz_pair(bottom_i, layout_box.maxy() + y_margin, 1, x_margin, layout.get_max_difference()));
            top_i -= 2;
            bottom_i += 2;
        }

    }
  
private:

    // Place member bound boxes at [ifirst] and [ifirst + 1] in a horizontal pairi, vertically
    //   align with pair_y, store corresponding offsets, and return bound box of combined pair
    // Note: x_margin is the distance between box edge and x center
    bound_box make_horiz_pair(size_t ifirst, double pair_y, int y_dir, double x_margin, double max_diff) const
    {
        // two boxes available for pair
        if (ifirst + 1 < member_boxes_.size())
        {
            double x_center = member_boxes_[ifirst].width() - member_boxes_[ifirst + 1].width();
            if (max_diff < 0.0 || std::abs(x_center) <= max_diff)
            {
                x_center = 0.0;
            }

            bound_box pair_box = box_offset_align(ifirst, x_center - x_margin, pair_y, -1, y_dir);
            pair_box.expand_to_include(box_offset_align(ifirst + 1, x_center + x_margin, pair_y, 1, y_dir));
            return pair_box;
        }
        
        // only one box available for this "pair", so keep x-centered and handle y-offset
        return box_offset_align(ifirst, 0, pair_y, 0, y_dir);
    }


    // Offsets member bound box at [i] and align with (x, y), in direction <x_dir, y_dir>
    // stores corresponding offset, and returns modified bounding box
    bound_box box_offset_align(size_t i, double x, double y, int x_dir, int y_dir) const
    {
        const bound_box &box = member_boxes_[i];
        pixel_position offset((x_dir == 0 ? x - input_origin_.x : x - (x_dir < 0 ? box.maxx() : box.minx())),
                             (y_dir == 0 ? y - input_origin_.y : y - (y_dir < 0 ? box.maxy() : box.miny())));

        member_offsets_[i] = offset;
        return bound_box(box.minx() + offset.x, box.miny() + offset.y, box.maxx() + offset.x, box.maxy() + offset.y);
    }
};

bound_box group_layout_manager::offset_box_at(size_t i)
{
    handle_update();
    const pixel_position &offset = member_offsets_.at(i);
    const bound_box &box = member_boxes_.at(i);
    return box2d<double>(box.minx() + offset.x, box.miny() + offset.y,
                         box.maxx() + offset.x, box.maxy() + offset.y);
}

void group_layout_manager::handle_update()
{
    if (update_layout_)
    {
       member_offsets_.clear();
       boost::apply_visitor(process_layout(member_boxes_, member_offsets_, input_origin_), layout_);
       update_layout_ = false;
    }     
}

}
<commit_msg>fix a few sign comparison warnings<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 <NAME>
 *
 * 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
 *
 *****************************************************************************/

// mapnik
#include <mapnik/group/group_layout_manager.hpp>

// boost
#include <boost/variant.hpp>

// std
#include <cmath>

namespace mapnik
{

// This visitor will process offsets for the given layout
struct process_layout : public boost::static_visitor<>
{
    // The vector containing the existing, centered item bounding boxes
    const vector<bound_box> &member_boxes_;
    
    // The vector to populate with item offsets
    vector<pixel_position> &member_offsets_;
    
    // The origin point of the member boxes
    // i.e. The member boxes are positioned around input_origin,
    //      and the offset values should position them around (0,0)
    const pixel_position &input_origin_;

    process_layout(const vector<bound_box> &member_bboxes, 
                   vector<pixel_position> &member_offsets,
                   const pixel_position &input_origin)
       : member_boxes_(member_bboxes), 
         member_offsets_(member_offsets),
         input_origin_(input_origin)
    {
    }

    // arrange group memebers in centered, horizontal row
    void operator()(simple_row_layout const& layout) const
    {
        double total_width = (member_boxes_.size() - 1) * layout.get_item_margin();
        for (auto const& box : member_boxes_)
        {
            total_width += box.width();
        }
        
        double x_offset = -(total_width / 2.0);
        for (auto const& box : member_boxes_)
        {
            member_offsets_.push_back(pixel_position(x_offset - box.minx(), -input_origin_.y));
            x_offset += box.width() + layout.get_item_margin();
        }
    }

    // arrange group members in x horizontal pairs of 2,
    // one to the left and one to the right of center in each pair
    void operator()(pair_layout const& layout) const
    {
        member_offsets_.resize(member_boxes_.size());
        double y_margin = layout.get_item_margin();
        double x_margin = y_margin / 2.0;

        if (member_boxes_.size() == 1)
        {
            member_offsets_[0] = pixel_position(0, 0) - input_origin_;
            return;
        }

        bound_box layout_box;
        size_t middle_ifirst = (member_boxes_.size() - 1) >> 1;
        int top_i = 0;
        int bottom_i = 0;
        if (middle_ifirst % 2 == 0)
        {
            layout_box = make_horiz_pair(0, 0.0, 0, x_margin, layout.get_max_difference());
            top_i = middle_ifirst - 2;
            bottom_i = middle_ifirst + 2;
        }
        else
        {
            top_i = middle_ifirst - 1;
            bottom_i = middle_ifirst + 1;
        }

        while (bottom_i >= 0 && top_i < static_cast<int>(member_offsets_.size()))
        {
            layout_box.expand_to_include(make_horiz_pair(top_i, layout_box.miny() - y_margin, -1, x_margin, layout.get_max_difference()));
            layout_box.expand_to_include(make_horiz_pair(bottom_i, layout_box.maxy() + y_margin, 1, x_margin, layout.get_max_difference()));
            top_i -= 2;
            bottom_i += 2;
        }

    }
  
private:

    // Place member bound boxes at [ifirst] and [ifirst + 1] in a horizontal pairi, vertically
    //   align with pair_y, store corresponding offsets, and return bound box of combined pair
    // Note: x_margin is the distance between box edge and x center
    bound_box make_horiz_pair(size_t ifirst, double pair_y, int y_dir, double x_margin, double max_diff) const
    {
        // two boxes available for pair
        if (ifirst + 1 < member_boxes_.size())
        {
            double x_center = member_boxes_[ifirst].width() - member_boxes_[ifirst + 1].width();
            if (max_diff < 0.0 || std::abs(x_center) <= max_diff)
            {
                x_center = 0.0;
            }

            bound_box pair_box = box_offset_align(ifirst, x_center - x_margin, pair_y, -1, y_dir);
            pair_box.expand_to_include(box_offset_align(ifirst + 1, x_center + x_margin, pair_y, 1, y_dir));
            return pair_box;
        }
        
        // only one box available for this "pair", so keep x-centered and handle y-offset
        return box_offset_align(ifirst, 0, pair_y, 0, y_dir);
    }


    // Offsets member bound box at [i] and align with (x, y), in direction <x_dir, y_dir>
    // stores corresponding offset, and returns modified bounding box
    bound_box box_offset_align(size_t i, double x, double y, int x_dir, int y_dir) const
    {
        const bound_box &box = member_boxes_[i];
        pixel_position offset((x_dir == 0 ? x - input_origin_.x : x - (x_dir < 0 ? box.maxx() : box.minx())),
                             (y_dir == 0 ? y - input_origin_.y : y - (y_dir < 0 ? box.maxy() : box.miny())));

        member_offsets_[i] = offset;
        return bound_box(box.minx() + offset.x, box.miny() + offset.y, box.maxx() + offset.x, box.maxy() + offset.y);
    }
};

bound_box group_layout_manager::offset_box_at(size_t i)
{
    handle_update();
    const pixel_position &offset = member_offsets_.at(i);
    const bound_box &box = member_boxes_.at(i);
    return box2d<double>(box.minx() + offset.x, box.miny() + offset.y,
                         box.maxx() + offset.x, box.maxy() + offset.y);
}

void group_layout_manager::handle_update()
{
    if (update_layout_)
    {
       member_offsets_.clear();
       boost::apply_visitor(process_layout(member_boxes_, member_offsets_, input_origin_), layout_);
       update_layout_ = false;
    }     
}

}

{'fraction_non_alphanumeric': 0.12234415129582069, 'fraction_numerical': 0.010117518873064052, 'mean_word_length': 2.59139183901621, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6700312', 'n_tokens_mistral': 3984, 'n_tokens_neox': 3807, 'n_words': 1127}