Ticket #180: sharp_spike_fix.patch

File sharp_spike_fix.patch, 8.2 kB (added by dfaubion, 6 months ago)

Fixes the sharps spike for acute inner angles, but the continuity issues from line to line remain unchanged. Any ideas?

  • include/mapnik/ctrans.hpp

     
    3030#include <mapnik/envelope.hpp> 
    3131#include <mapnik/coord_array.hpp> 
    3232#include <mapnik/proj_transform.hpp> 
     33#include <mapnik/vertex.hpp> 
    3334 
     35#include <mapnik/vertex.hpp>  
     36#ifndef M_PI  
     37#define M_PI 3.14159265358979323846  
     38#endif  
     39 
     40#ifdef MAPNIK_DEBUG  
     41#include <iostream>  
     42#endif  
     43 
    3444namespace mapnik { 
    3545   typedef coord_array<coord2d> CoordinateArray; 
    3646     
     
    123133      int dy_; 
    124134   }; 
    125135    
     136   template <typename Transform,typename Geometry> struct MAPNIK_DECL coord_transform4 { 
     137     
     138    /** 
     139     * Creates a new coord_transform4. 
     140     */ 
     141    coord_transform4(Transform const& t,  Geometry const& geom,  proj_transform const& prj_trans )  
     142        : t_(t),   
     143                geom_(geom),   
     144                prj_trans_(prj_trans),  
     145                offset_(0.0),  
     146                m_status(initial) {}  
     147         
     148    // Enum representing the status or the tranformation process. 
     149    enum status  
     150    {   
     151        initial,   
     152        start,  
     153        first,   
     154        process,  
     155        last_vertex,  
     156        angle_joint,  
     157        end   
     158    };  
     159  
     160    double get_offset() const  
     161    {  
     162        return offset_;  
     163    }  
     164      
     165    void set_offset(double offset)  
     166    {  
     167        offset_ = offset;  
     168    }  
     169  
     170    bool is_acute(double x0,double y0,double x1,double y1,double x2,double y2)  
     171    {  
     172        double dx0 = x0 - x1;  
     173        double dy0 = y0 - y1;  
     174        double dx1 = x2 - x1;  
     175        double dy1 = y2 - y1;  
     176        double product = dx0 * dx1 + dy0 * dy1;  
     177        return product > 0;  
     178    }  
     179  
     180        /** 
     181         * Reads the x and y values of the next vertex and assigns the  
     182         * values of the locations of the x and y parameters to them.   
     183         * Returns the next command associated with the vertex based 
     184         * from where in the line the point is read. 
     185         */ 
     186        /* 
     187         * Basically copied out of mapservers line offset algorithm 
     188         * (msOffsetPolyline). 
     189         */ 
     190    unsigned vertex(double * x , double  * y)  
     191    { 
     192        double z=0;  
     193         
     194        if (offset_==0.0)  
     195        {  
     196            unsigned command = geom_.vertex(x,y);  
     197            prj_trans_.backward(*x,*y,z);  
     198            t_.forward(x,y);  
     199            return command;  
     200        }  
     201        else  
     202        {  
     203            while(true){ 
     204                switch(m_status)  
     205                {  
     206                    case end:  
     207                        return SEG_END;  
     208                        break;  
     209                    case initial:  
     210                        m_pre_cmd = geom_.vertex(x,y); 
     211                        prj_trans_.backward(*x,*y,z);  
     212                        t_.forward(x,y);  
     213                        m_pre_x = *x;  
     214                        m_pre_y = *y; 
     215                    case start:  
     216                        m_cur_cmd = geom_.vertex(&m_cur_x, &m_cur_y); 
     217                        prj_trans_.backward(m_cur_x,m_cur_y,z); 
     218                        t_.forward(&m_cur_x,&m_cur_y); 
     219                    case first: 
     220                        angle_a = atan2((m_pre_y-m_cur_y),(m_pre_x-m_cur_x)); 
     221                        dx_pre = cos(angle_a + M_PI/2); 
     222                        dy_pre = sin(angle_a + M_PI/2); 
     223                        #ifdef MAPNIK_DEBUG 
     224                            std::clog << "offsetting line by: " << offset_ << "\n";  
     225                            std::clog << "initial dx=" << (dx_pre * offset_) << " dy=" << (dy_pre * offset_) << "\n";  
     226                        #endif 
     227                        *x = m_pre_x + (dx_pre * offset_); 
     228                        *y = m_pre_y + (dy_pre * offset_); 
     229                        m_status = process; 
     230                        return SEG_MOVETO; 
     231                    case process:  
     232                        switch(m_cur_cmd)  
     233                        {  
     234                            case SEG_LINETO:  
     235                                m_next_cmd = geom_.vertex(&m_next_x, &m_next_y);  
     236                                prj_trans_.backward(m_next_x,m_next_y,z);  
     237                                t_.forward(&m_next_x,&m_next_y);  
     238                                switch(m_next_cmd)  
     239                                {  
     240                                    case SEG_LINETO:  
     241                                        m_status = angle_joint;  
     242                                        break;  
     243                                    default:  
     244                                        m_status = last_vertex;  
     245                                        break;  
     246                                } 
     247                                break;  
     248                            case SEG_END:  
     249                                m_status = end;  
     250                                return SEG_END;  
     251                        }  
     252                        break;  
     253                    case last_vertex:  
     254                        dx_curr = cos(angle_a + M_PI/2);  
     255                        dy_curr = sin(angle_a + M_PI/2);  
     256                        *x = m_cur_x + (dx_curr * offset_);  
     257                        *y = m_cur_y + (dy_curr * offset_);  
     258                        m_status = end;  
     259                        return m_cur_cmd;  
     260                    case angle_joint: 
     261                        dx_curr = cos(angle_a + M_PI/2);  
     262                        dy_curr = sin(angle_a + M_PI/2); 
     263                         
     264                        sin_curve = dx_curr*dy_pre-dy_curr*dx_pre; 
     265                        cos_curve = -dx_pre*dx_curr-dy_pre*dy_curr; 
     266                         
     267                        #ifdef MAPNIK_DEBUG 
     268                            std::clog << "sin_curve value: " << sin_curve << "\n"; 
     269                        #endif 
     270                        if(-0.3 < sin_curve && sin_curve < 0.3) { 
     271                                                        angle_b = atan2((m_cur_y-m_next_y),(m_cur_x-m_next_x));  
     272                                                        h = tan((angle_b - angle_a)/2.0);  
     273                                                        *x = m_cur_x + dx_curr * offset_ - h * dy_curr * offset_;  
     274                                                        *y = m_cur_y + dy_curr * offset_ + h * dx_curr * offset_;  
     275                                                } else { 
     276                                                        base_shift = -1.0*(1.0+cos_curve)/sin_curve; 
     277                                                        *x = m_cur_x + (dx_curr + base_shift*dy_curr)*offset_; 
     278                                                        *y = m_cur_y + (dy_curr - base_shift*dx_curr)*offset_; 
     279                                                } 
     280                         
     281                        // Save old shit 
     282                        m_cur_x = m_next_x;  
     283                        m_cur_y = m_next_y;  
     284                        angle_a = angle_b;  
     285                        m_pre_cmd = m_cur_cmd;  
     286                        m_cur_cmd = m_next_cmd;  
     287                        m_status = process;  
     288                        return m_pre_cmd;  
     289             }  
     290          }  
     291       }  
     292    }  
     293  
     294    void rewind (unsigned pos)  
     295    {  
     296        geom_.rewind(pos);  
     297        m_status = initial;  
     298    } 
     299     
     300    private:  
     301        Transform const& t_;  
     302        Geometry const& geom_;  
     303        proj_transform const& prj_trans_;  
     304        int offset_;  
     305        double dx_pre;  
     306        double dy_pre; 
     307        double dx_curr;  
     308        double dy_curr; 
     309        double base_shift; 
     310        double sin_curve; 
     311        double cos_curve; 
     312        double angle_a;  
     313        double angle_b;  
     314        double h;  
     315        // processing state  
     316        status       m_status;  
     317        // source vertex lookahead queue  
     318        unsigned       m_pre_cmd;  
     319        double         m_pre_x;  
     320        double         m_pre_y;  
     321        unsigned       m_cur_cmd;  
     322        double         m_cur_x;  
     323        double         m_cur_y;  
     324        unsigned       m_next_cmd;  
     325        double         m_next_x;  
     326        double         m_next_y; 
     327         
     328         
     329  
     330    };  
     331    
    126332   class CoordTransform 
    127333   { 
    128334      private: 
     
    133339         Envelope<double> extent_; 
    134340         double offset_x_; 
    135341         double offset_y_; 
     342          
    136343      public: 
    137344         CoordTransform(int width,int height,const Envelope<double>& extent, 
    138345                        double offset_x = 0, double offset_y = 0) 
    139             :width_(width),height_(height),extent_(extent),offset_x_(offset_x),offset_y_(offset_y) 
     346            : width_(width), 
     347            height_(height), 
     348            extent_(extent), 
     349            offset_x_(offset_x), 
     350            offset_y_(offset_y) 
     351             
    140352         { 
    141353            sx_ = ((double)width_)/extent_.width(); 
    142354            sy_ = ((double)height_)/extent_.height();