File indexing completed on 2026-04-09 07:48:47
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include <stdio.h>
0033 #include <math.h>
0034 #include <assert.h>
0035
0036
0037
0038 struct Point
0039 {
0040 double x ;
0041 double y ;
0042 int i ;
0043 int n ;
0044
0045 void dump(const char* msg) const
0046 {
0047 printf("Point %s : i %d n %d (%10.4f, %10.4f) \n", msg, i, n, x, y );
0048 }
0049
0050 void copy(const Point& other)
0051 {
0052 x = other.x ;
0053 y = other.y ;
0054 i = other.i ;
0055 n = other.n ;
0056 }
0057
0058 void set(double x_, double y_, int i_, int n_ )
0059 {
0060 x = x_ ;
0061 y = y_ ;
0062 i = i_ ;
0063 n = n_ ;
0064 }
0065
0066 static Point make(double px, double py, int i=-1, int n=-1)
0067 {
0068 Point p ;
0069 p.x = px;
0070 p.y = py;
0071 p.i = i ;
0072 p.n = n ;
0073 return p ;
0074 }
0075
0076 double distance(const Point& other) const
0077 {
0078 double dx = other.x - x ;
0079 double dy = other.y - y ;
0080 return sqrt(dx*dx + dy*dy) ;
0081 }
0082 };
0083
0084 struct Circle
0085 {
0086 Point center ;
0087 double radius ;
0088
0089 static Circle make(double cx, double cy, double r )
0090 {
0091 Circle c ;
0092 c.center = Point::make(cx, cy);
0093 c.radius = r ;
0094 return c ;
0095 }
0096
0097 bool is_point_inside( const Point& point)
0098 {
0099 double d = center.distance(point) ;
0100 bool inside = d - radius < 0. ;
0101 return inside ;
0102 }
0103 };
0104
0105
0106 struct Mask
0107 {
0108 bool* a ;
0109 int n ;
0110
0111 Mask(int n_)
0112 :
0113 a(new bool[n_]),
0114 n(n_)
0115 {
0116 }
0117
0118
0119 int first() const
0120 {
0121 for(int i=0 ; i < n ; i++) if(a[i]) return i ;
0122 return -1 ;
0123 }
0124
0125 int last() const
0126 {
0127 for(int i=0 ; i < n ; i++) if(a[n-1-i]) return n-1-i ;
0128 return -1 ;
0129 }
0130
0131 int count() const
0132 {
0133 int tot = 0 ;
0134 for(int i=0 ; i < n ; i++) if(a[i]) tot += 1 ;
0135 return tot ;
0136 }
0137
0138 void dump(const char* msg) const
0139 {
0140 printf("Mask %s n %d first %d last %d count %d \n", msg, n, first(), last(), count() );
0141 }
0142
0143
0144 };
0145
0146
0147 struct Ellipse
0148 {
0149 Point center ;
0150 double ax ;
0151 double ay ;
0152
0153 static Ellipse make( double px, double py, double ax_, double ay_ )
0154 {
0155 Ellipse e ;
0156 e.center = Point::make( px, py);
0157 e.ax = ax_ ;
0158 e.ay = ay_ ;
0159 return e ;
0160 }
0161
0162 void get_point( Point& p, int i, int n ) const
0163 {
0164
0165
0166
0167
0168
0169
0170
0171 assert( i > -1 && i < n );
0172
0173 double fraction = double(i)/double(n) ;
0174 double t = M_PI*2.*fraction ;
0175
0176 p.x = ax*cos(t) + center.x ;
0177 p.y = ay*sin(t) + center.y ;
0178 p.i = i ;
0179 p.n = n ;
0180 }
0181
0182 void dump_point( const char* msg, int i, int n ) const
0183 {
0184 Point point ;
0185 get_point(point, i, n );
0186 printf("%s i %3d/%d point %10.4f %10.4f \n", msg, i, n, point.x, point.y );
0187 }
0188
0189 void dump_points( const Mask& mask ) const
0190 {
0191 for(int i=0 ; i < mask.n ; i++)
0192 {
0193 if(!mask.a[i]) continue ;
0194 dump_point("", i, mask.n );
0195 }
0196 }
0197
0198 };
0199
0200
0201 struct Intersect
0202 {
0203 Point* p ;
0204 int mx ;
0205 int count ;
0206
0207 static Intersect make(int mx_)
0208 {
0209 Intersect isect ;
0210 isect.p = new Point[mx_] ;
0211 isect.mx = mx_ ;
0212 isect.count = 0 ;
0213 return isect ;
0214 }
0215
0216 void add(const Point& point)
0217 {
0218 assert( count < mx );
0219 p[count].copy(point) ;
0220 count += 1 ;
0221 }
0222
0223 void dump(const char* msg)
0224 {
0225 printf("Intersect %s : count %d crossings \n", msg, count );
0226 for(int i=0 ; i < count ; i++)
0227 {
0228 p[i].dump("p");
0229 }
0230
0231 }
0232
0233 };
0234
0235
0236
0237 struct Ellipse_Intersect_Circle
0238 {
0239 Ellipse ellipse ;
0240 Circle circle ;
0241 int n ;
0242 #ifdef WITH_MASK
0243 Mask* mask ;
0244 #endif
0245 Intersect intersect ;
0246 bool verbose ;
0247
0248 enum {
0249 INSIDE,
0250 OUTSIDE
0251 };
0252
0253
0254 static Ellipse_Intersect_Circle make(double e_cx, double e_cy, double e_ax, double e_ay, double c_cx, double c_cy, double c_r, int n, bool verbose )
0255 {
0256 Ellipse_Intersect_Circle ec ;
0257 ec.ellipse = Ellipse::make( e_cx, e_cy, e_ax, e_ay );
0258 ec.circle = Circle::make( c_cx, c_cy, c_r );
0259 ec.n = n ;
0260 ec.intersect = Intersect::make(4) ;
0261 ec.verbose = verbose ;
0262
0263 int ni = ec.find_intersects();
0264 if(verbose)
0265 {
0266 printf("Ellipse_Intersect_Circle found %d intersects\n", ni );
0267 ec.intersect.dump("EC") ;
0268 }
0269
0270
0271 #ifdef WITH_MASK
0272 ec.mask = new Mask(n) ;
0273 ec.find_mask();
0274 #endif
0275
0276 return ec ;
0277 }
0278
0279
0280 int find_intersects()
0281 {
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292 Point e ;
0293 ellipse.get_point(e, 0, n );
0294 int s0 = circle.is_point_inside(e) ? INSIDE : OUTSIDE ;
0295 int s_prev = s0 ;
0296
0297 for(int i=1 ; i < n ; i++)
0298 {
0299 ellipse.get_point(e, i, n );
0300 int s = circle.is_point_inside(e) ? INSIDE : OUTSIDE ;
0301 if( s != s_prev ) intersect.add(e) ;
0302 s_prev = s ;
0303 }
0304
0305 if( s_prev != s0 ) intersect.add(e) ;
0306
0307 return intersect.count ;
0308 }
0309
0310 #ifdef WITH_MASK
0311 int find_mask()
0312 {
0313 Point e ;
0314 int num_inside = 0 ;
0315 for(int i=0 ; i < mask->n ; i++)
0316 {
0317 ellipse.get_point(e, i, mask->n );
0318 bool inside = circle.is_point_inside(e);
0319 mask->a[i] = inside ;
0320 if(inside) num_inside += 1 ;
0321 }
0322 if(verbose) mask->dump("ellipse points inside circle");
0323 return num_inside ;
0324 }
0325 #endif
0326
0327 };
0328
0329