1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.4 3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 16 #include "agg_math.h" 17 #include "agg_vertex_sequence.h" 18 #include "agg_trans_single_path.h" 19 20 namespace agg 21 { 22 23 //------------------------------------------------------------------------ trans_single_path()24 trans_single_path::trans_single_path() : 25 m_base_length(0.0), 26 m_kindex(0.0), 27 m_status(initial), 28 m_preserve_x_scale(true) 29 { 30 } 31 32 //------------------------------------------------------------------------ reset()33 void trans_single_path::reset() 34 { 35 m_src_vertices.remove_all(); 36 m_kindex = 0.0; 37 m_status = initial; 38 } 39 40 //------------------------------------------------------------------------ move_to(double x,double y)41 void trans_single_path::move_to(double x, double y) 42 { 43 if(m_status == initial) 44 { 45 m_src_vertices.modify_last(vertex_dist(x, y)); 46 m_status = making_path; 47 } 48 else 49 { 50 line_to(x, y); 51 } 52 } 53 54 //------------------------------------------------------------------------ line_to(double x,double y)55 void trans_single_path::line_to(double x, double y) 56 { 57 if(m_status == making_path) 58 { 59 m_src_vertices.add(vertex_dist(x, y)); 60 } 61 } 62 63 64 //------------------------------------------------------------------------ finalize_path()65 void trans_single_path::finalize_path() 66 { 67 if(m_status == making_path && m_src_vertices.size() > 1) 68 { 69 unsigned i; 70 double dist; 71 double d; 72 73 m_src_vertices.close(false); 74 if(m_src_vertices.size() > 2) 75 { 76 if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 < 77 m_src_vertices[m_src_vertices.size() - 3].dist) 78 { 79 d = m_src_vertices[m_src_vertices.size() - 3].dist + 80 m_src_vertices[m_src_vertices.size() - 2].dist; 81 82 m_src_vertices[m_src_vertices.size() - 2] = 83 m_src_vertices[m_src_vertices.size() - 1]; 84 85 m_src_vertices.remove_last(); 86 m_src_vertices[m_src_vertices.size() - 2].dist = d; 87 } 88 } 89 90 dist = 0.0; 91 for(i = 0; i < m_src_vertices.size(); i++) 92 { 93 vertex_dist& v = m_src_vertices[i]; 94 double d = v.dist; 95 v.dist = dist; 96 dist += d; 97 } 98 m_kindex = (m_src_vertices.size() - 1) / dist; 99 m_status = ready; 100 } 101 } 102 103 104 105 //------------------------------------------------------------------------ total_length() const106 double trans_single_path::total_length() const 107 { 108 if(m_base_length >= 1e-10) return m_base_length; 109 return (m_status == ready) ? 110 m_src_vertices[m_src_vertices.size() - 1].dist : 111 0.0; 112 } 113 114 115 //------------------------------------------------------------------------ transform(double * x,double * y) const116 void trans_single_path::transform(double *x, double *y) const 117 { 118 if(m_status == ready) 119 { 120 if(m_base_length > 1e-10) 121 { 122 *x *= m_src_vertices[m_src_vertices.size() - 1].dist / 123 m_base_length; 124 } 125 126 double x1 = 0.0; 127 double y1 = 0.0; 128 double dx = 1.0; 129 double dy = 1.0; 130 double d = 0.0; 131 double dd = 1.0; 132 if(*x < 0.0) 133 { 134 // Extrapolation on the left 135 //-------------------------- 136 x1 = m_src_vertices[0].x; 137 y1 = m_src_vertices[0].y; 138 dx = m_src_vertices[1].x - x1; 139 dy = m_src_vertices[1].y - y1; 140 dd = m_src_vertices[1].dist - m_src_vertices[0].dist; 141 d = *x; 142 } 143 else 144 if(*x > m_src_vertices[m_src_vertices.size() - 1].dist) 145 { 146 // Extrapolation on the right 147 //-------------------------- 148 unsigned i = m_src_vertices.size() - 2; 149 unsigned j = m_src_vertices.size() - 1; 150 x1 = m_src_vertices[j].x; 151 y1 = m_src_vertices[j].y; 152 dx = x1 - m_src_vertices[i].x; 153 dy = y1 - m_src_vertices[i].y; 154 dd = m_src_vertices[j].dist - m_src_vertices[i].dist; 155 d = *x - m_src_vertices[j].dist; 156 } 157 else 158 { 159 // Interpolation 160 //-------------------------- 161 unsigned i = 0; 162 unsigned j = m_src_vertices.size() - 1; 163 if(m_preserve_x_scale) 164 { 165 unsigned k; 166 for(i = 0; (j - i) > 1; ) 167 { 168 if(*x < m_src_vertices[k = (i + j) >> 1].dist) 169 { 170 j = k; 171 } 172 else 173 { 174 i = k; 175 } 176 } 177 d = m_src_vertices[i].dist; 178 dd = m_src_vertices[j].dist - d; 179 d = *x - d; 180 } 181 else 182 { 183 i = unsigned(*x * m_kindex); 184 j = i + 1; 185 dd = m_src_vertices[j].dist - m_src_vertices[i].dist; 186 d = ((*x * m_kindex) - i) * dd; 187 } 188 x1 = m_src_vertices[i].x; 189 y1 = m_src_vertices[i].y; 190 dx = m_src_vertices[j].x - x1; 191 dy = m_src_vertices[j].y - y1; 192 } 193 double x2 = x1 + dx * d / dd; 194 double y2 = y1 + dy * d / dd; 195 *x = x2 - *y * dy / dd; 196 *y = y2 + *y * dx / dd; 197 } 198 } 199 200 201 } 202 203