00001 #ifndef POINTLIST_H_IS_INCLUDED
00002 #define POINTLIST_H_IS_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "std/support.H"
00012
00013 namespace mlib {
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 template <class L,class P,class V,class S>
00031 class Pointlist : public ARRAY<P> {
00032
00033 protected:
00034
00035 ARRAY<double> _partial_length;
00036
00037 public:
00038
00039
00040
00041
00042
00043 Pointlist(int m=16) : ARRAY<P>(m), _partial_length(0) { }
00044
00045
00046 Pointlist(const ARRAY<P> &p) : ARRAY<P>(p), _partial_length(0) {
00047 update_length();
00048 }
00049
00050
00051
00052
00053
00054
00055
00056 P pt(int i) const { return (*this)[i]; }
00057
00058
00059 V vec(int i) const { return (*this)[i+1]-(*this)[i];}
00060
00061
00062 double segment_length(int i) const { return vec(i).length(); }
00063
00064
00065 S seg(int i) const { return S(pt(i), pt(i+1)); }
00066
00067
00068
00069
00070
00071
00072 V tan(int i) const {
00073 const int n = num()-1;
00074 if (i<0 || i>n || n<1)
00075 return V::null();
00076 if (i==0) return (vec(0)) .normalized();
00077 if (i==n) return (vec(n-1)).normalized();
00078 return (vec(i).normalized() + vec(i-1).normalized()).normalized();
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088 bool is_closed() const {
00089 return (num() > 2 && ((*this)[0] == last()));
00090 }
00091
00092
00093
00094
00095
00096
00097 bool is_straight(double len_scale=1e-5) const;
00098
00099
00100
00101
00102 bool self_intersects() const;
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 int nearest_point (const P &p) const;
00113
00114
00115 void closest (const P &p, P &, double &, int &) const;
00116
00117 double closest (const P &p, P &, int &) const;
00118
00119 P closest (const P &p) const;
00120
00121
00122
00123
00124
00125
00126
00127 P sum() const;
00128
00129
00130 P average () const { return empty() ? P::Origin() : sum()/num(); }
00131
00132
00133
00134 double dist_to_seg (const P &p, int k) const;
00135
00136
00137
00138 double avg_dist_to_seg (const P &p, int k) const;
00139
00140
00141 double dist(const P& p) const { return closest(p).dist(p); }
00142
00143
00144 double spread() const;
00145
00146
00147
00148 typename P::value_type min_val(int i) const;
00149
00150
00151
00152 typename P::value_type max_val(int i) const;
00153
00154
00155
00156
00157
00158
00159
00160
00161 void update_length();
00162
00163
00164 double partial_length(int i) const {
00165 return _partial_length.valid_index(i) ? _partial_length[i] : 0;
00166 }
00167
00168 double length() const { return _partial_length.last(); }
00169
00170 double avg_len() const
00171 { return (num() > 1) ? length()/(num()-1) : 0; }
00172
00173
00174
00175
00176
00177
00178
00179 P interpolate(double s, V *tan=0, int *segp=0, double *tp=0) const;
00180
00181
00182
00183
00184
00185 void interpolate_length(double s, int &seg, double &t) const;
00186
00187
00188 V get_tangent(double s) const;
00189
00190
00191
00192
00193
00194
00195 double invert (const P &p) const;
00196 double invert (const P &p, int seg) const;
00197
00198
00199
00200
00201
00202
00203
00204
00205 void translate (const V& vec) {
00206 for (int i = 0; i < num(); i++) (*this)[i] = (*this)[i] + vec;
00207 }
00208
00209
00210 void resample(int num_segs);
00211
00212
00213
00214
00215
00216
00217
00218 L clone_piece(int k1, int k2) const;
00219
00220
00221 void append (Pointlist<L,P,V,S> *poly);
00222
00223 void prepend (Pointlist<L,P,V,S> *poly);
00224
00225
00226
00227
00228
00229
00230 virtual void clear() {
00231 ARRAY<P>::clear();
00232 _partial_length.clear();
00233 }
00234
00235 virtual void shift(int p) {
00236 ARRAY<P>::shift(p);
00237 update_length();
00238 }
00239
00240
00241
00242 using ARRAY<P>::num;
00243 using ARRAY<P>::empty;
00244 using ARRAY<P>::last;
00245 using ARRAY<P>::valid_index;
00246
00247 };
00248
00249 }
00250
00251 #ifdef JOT_NEEDS_TEMPLATES_IN_H_FILE
00252 #include "pointlist.C"
00253 #endif
00254
00255 #endif // POINTLIST_H_IS_INCLUDED