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

#ifndef MAPNIK_METAWRITER_JSON_HPP
#define MAPNIK_METAWRITER_JSON_HPP

// mapnik
#include <mapnik/metawriter.hpp>
#include <mapnik/parse_path.hpp>

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

// stl
#include <fstream>

namespace mapnik {


/** Write JSON data to a stream object. */
class metawriter_json_stream : public metawriter, private boost::noncopyable
{
public:
    metawriter_json_stream(metawriter_properties dflt_properties);
    ~metawriter_json_stream();
    virtual void add_box(box2d<double> const& box, Feature const& feature,
                         CoordTransform const& t,
                         metawriter_properties const& properties);
    virtual void add_text(boost::ptr_vector<text_path> &placements,
                          box2d<double> const& extents,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties);
    virtual void add_polygon(path_type & path,
                             Feature const& feature,
                             CoordTransform const& t,
                             metawriter_properties const& properties);
    virtual void add_line(path_type & path,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties);

    virtual void start(metawriter_property_map const& properties);
    virtual void stop();
    /** Set output stream. This function has to be called before the first output is made. */
    void set_stream(std::ostream *f) { f_ = f; }
    /** Get output stream. */
    std::ostream *get_stream() const { return f_; }
    /** Only write header/footer to file with one or more features. */
    void set_output_empty(bool output_empty) { output_empty_ = output_empty; }
    /** See set_output_empty(). */
    bool get_output_empty() { return output_empty_; }
    void set_pixel_coordinates(bool on) { pixel_coordinates_ = on; }
    bool get_pixel_coordinates() { return pixel_coordinates_; }
    virtual void set_map_srs(projection const& proj);

protected:
    enum {
        HEADER_NOT_WRITTEN = -1,
        STOPPED = -2,
        STARTED = 0
    };

    /** Features written. */
    int count_;
    bool output_empty_;
    /** Transformation from map srs to output srs. */
    proj_transform *trans_;
    projection output_srs_;
    bool pixel_coordinates_;

    virtual void write_header();

    inline void write_feature_header(std::string type) {
        if (count_ == STOPPED)
        {
            MAPNIK_LOG_WARN(metawrite_json) << "Metawriter: instance not started before using it.";
        }

        if (count_ == HEADER_NOT_WRITTEN) write_header();
        if (count_++) *f_ << ",\n";

        *f_  << "{ \"type\": \"Feature\",\n  \"geometry\": { \"type\": \"" << type << "\",\n    \"coordinates\":";
    }

    void write_properties(Feature const& feature, metawriter_properties const& properties);

    inline void write_point(CoordTransform const& t, double x, double y, bool last = false)
    {
        double z = 0.0;
        if (!pixel_coordinates_) {
            t.backward(&x, &y);
            trans_->forward(x, y, z);
        }
        *f_ << "[" << x << "," << y << "]";
        if (!last) {
            *f_ << ",";
        }
    }

    void write_line_polygon(path_type & path, CoordTransform const& t, bool polygon);

private:
    std::ostream *f_;
};

/** Shared pointer to metawriter_json_stream object. */
typedef boost::shared_ptr<metawriter_json_stream> metawriter_json_stream_ptr;

/** JSON writer. */
class metawriter_json : public metawriter_json_stream
{
public:
    metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn);

    virtual void start(metawriter_property_map const& properties);
    virtual void stop();<commit_msg>+ fix GeoJSON output in metawriter_json   (FIXME: output proper geometry types - don't shortcut to Multi***)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 <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
 *
 *****************************************************************************/

#ifndef MAPNIK_METAWRITER_JSON_HPP
#define MAPNIK_METAWRITER_JSON_HPP

// mapnik
#include <mapnik/metawriter.hpp>
#include <mapnik/parse_path.hpp>

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

// stl
#include <fstream>

namespace mapnik {


/** Write JSON data to a stream object. */
class metawriter_json_stream : public metawriter, private boost::noncopyable
{
public:
    metawriter_json_stream(metawriter_properties dflt_properties);
    ~metawriter_json_stream();
    
    virtual void add_box(box2d<double> const& box, Feature const& feature,
                         CoordTransform const& t,
                         metawriter_properties const& properties);
    virtual void add_text(boost::ptr_vector<text_path> &placements,
                          box2d<double> const& extents,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties);
    virtual void add_polygon(path_type & path,
                             Feature const& feature,
                             CoordTransform const& t,
                             metawriter_properties const& properties);
    virtual void add_line(path_type & path,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties);

    virtual void start(metawriter_property_map const& properties);
    virtual void stop();
    /** Set output stream. This function has to be called before the first output is made. */
    void set_stream(std::ostream *f) { f_ = f; }
    /** Get output stream. */
    std::ostream *get_stream() const { return f_; }
    /** Only write header/footer to file with one or more features. */
    void set_output_empty(bool output_empty) { output_empty_ = output_empty; }
    /** See set_output_empty(). */
||||||| parent of 5f30f85... + fix GeoJSON output in metawriter_json
    void add_box(box2d<double> const& box, Feature const& feature,
                 CoordTransform const& t,
                 metawriter_properties const& properties);
    void add_text(boost::ptr_vector<text_path> &placements,
                  box2d<double> const& extents,
                  Feature const& feature,
                  CoordTransform const& t,
                  metawriter_properties const& properties);
    template <typename T>
    void add_polygon(T & path,
                     Feature const& feature,
                     CoordTransform const& t,
                     metawriter_properties const& properties);   
    
    template <typename T>
    void add_line(T & path,
                  Feature const& feature,
                  CoordTransform const& t,
                  metawriter_properties const& properties)
    {
        write_feature_header("MultiLineString");

        *f_ << " [";
        double x, y, last_x=0.0, last_y=0.0;
        unsigned cmd, last_cmd = SEG_END;
        path.rewind(0);

        int polygon_count = 0;
        while ((cmd = path.vertex(&x, &y)) != SEG_END) {
            if (cmd == SEG_LINETO) {
                if (last_cmd == SEG_MOVETO) {
                    //Start new polygon/line
                    if (polygon_count++) *f_ << "], ";
                    *f_ << "[";
                    write_point(t, last_x, last_y, true);
                }
                *f_ << ",";
                write_point(t, x, y, true);
            }
            last_x = x;
            last_y = y;
            last_cmd = cmd;
        }
        *f_ << "]]";
    
        write_properties(feature, properties);
    }
    
    void start(metawriter_property_map const& properties);
    void stop();    
    void set_stream(std::ostream *f) { f_ = f; }    
    std::ostream *get_stream() const { return f_; }    
    void set_output_empty(bool output_empty) { output_empty_ = output_empty; }    
=======
    void add_box(box2d<double> const& box, Feature const& feature,
                 CoordTransform const& t,
                 metawriter_properties const& properties);
    void add_text(boost::ptr_vector<text_path> &placements,
                  box2d<double> const& extents,
                  Feature const& feature,
                  CoordTransform const& t,
                  metawriter_properties const& properties);
    template <typename T>
    void add_polygon(T & path,
                     Feature const& feature,
                     CoordTransform const& t,
                     metawriter_properties const& properties);   
    
    template <typename T>
    void add_line(T & path,
                  Feature const& feature,
                  CoordTransform const& t,
                  metawriter_properties const& properties)
    {
        write_feature_header("MultiLineString");
        *f_ << " [";
        
        path.rewind(0);    
        double x, y;
        unsigned cmd;        
        int ring_count = 0;
        while ((cmd = path.vertex(&x, &y)) != SEG_END) 
        {
            if (cmd == SEG_MOVETO) 
            {
                if (ring_count++ != 0) *f_ << "], ";
                *f_ << "[";
                write_point(t, x, y, true);
            }
            else if (cmd == SEG_LINETO) 
            {            
                *f_ << ",";
                write_point(t, x, y, true);
            }
        }
        if (ring_count != 0) *f_ << "]";
        *f_ << "]";
            
        write_properties(feature, properties);
    }
    
    void start(metawriter_property_map const& properties);
    void stop();    
    void set_stream(std::ostream *f) { f_ = f; }    
    std::ostream *get_stream() const { return f_; }    
    void set_output_empty(bool output_empty) { output_empty_ = output_empty; }    
>>>>>>> 5f30f85... + fix GeoJSON output in metawriter_json
    bool get_output_empty() { return output_empty_; }
    void set_pixel_coordinates(bool on) { pixel_coordinates_ = on; }
    bool get_pixel_coordinates() { return pixel_coordinates_; }
    virtual void set_map_srs(projection const& proj);

protected:
    enum {
        HEADER_NOT_WRITTEN = -1,
        STOPPED = -2,
        STARTED = 0
    };

    /** Features written. */
    int count_;
    bool output_empty_;
    /** Transformation from map srs to output srs. */
    proj_transform *trans_;
    projection output_srs_;
    bool pixel_coordinates_;

    virtual void write_header();

    inline void write_feature_header(std::string type) {
        if (count_ == STOPPED)
        {
            MAPNIK_LOG_WARN(metawrite_json) << "Metawriter: instance not started before using it.";
        }

        if (count_ == HEADER_NOT_WRITTEN) write_header();
        if (count_++) *f_ << ",\n";

        *f_  << "{ \"type\": \"Feature\",\n  \"geometry\": { \"type\": \"" << type << "\",\n    \"coordinates\":";
    }

    void write_properties(Feature const& feature, metawriter_properties const& properties);

    inline void write_point(CoordTransform const& t, double x, double y, bool last = false)
    {
        double z = 0.0;
        if (!pixel_coordinates_) {
            t.backward(&x, &y);
            trans_->forward(x, y, z);
        }
        *f_ << "[" << x << "," << y << "]";
        if (!last) {
            *f_ << ",";
        }
    }
<<<<<<< HEAD

    void write_line_polygon(path_type & path, CoordTransform const& t, bool polygon);

||||||| parent of 5f30f85... + fix GeoJSON output in metawriter_json
    
    template <typename T>
    void write_line_polygon(T & path, CoordTransform const& t, bool polygon);
    

    
    
=======
    
>>>>>>> 5f30f85... + fix GeoJSON output in metawriter_json
private:
    std::ostream *f_;
};

/** Shared pointer to metawriter_json_stream object. */
typedef boost::shared_ptr<metawriter_json_stream> metawriter_json_stream_ptr;

/** JSON writer. */
class metawriter_json : public metawriter_json_stream
{
public:
    metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn);

    virtual void start(metawriter_property_map const& properties);
    virtual void stop();
{'fraction_non_alphanumeric': 0.12134575716622804, 'fraction_numerical': 0.005832562771178605, 'mean_word_length': 2.312912346842601, 'pattern_counts': {'":': 8, '<': 105, '<?xml version=': 0, '>': 48, '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': '1060893', 'n_tokens_mistral': 4051, 'n_tokens_neox': 3875, 'n_words': 1156}