1 50 51 package org.openlaszlo.iv.flash.util; 52 53 import org.openlaszlo.iv.flash.api.*; 54 55 import org.openlaszlo.iv.flash.cache.*; 56 import org.openlaszlo.iv.flash.url.*; 57 58 import java.awt.geom.Rectangle2D ; 59 import java.awt.geom.Point2D ; 60 import java.awt.geom.AffineTransform ; 61 import java.io.*; 62 import java.util.*; 63 64 69 public class GeomHelper { 70 71 76 public static Rectangle2D newRectangle() { 77 return new Rectangle2D.Double (); 78 } 79 80 89 public static Rectangle2D newRectangle( int x, int y, int w, int h ) { 90 return new Rectangle2D.Double (x,y,w,h); 91 } 92 93 102 public static Rectangle2D newRectangle( double x, double y, double w, double h ) { 103 return new Rectangle2D.Double ((int)x,(int)y,(int)w,(int)h); 104 } 105 106 114 public static Rectangle2D calcBounds( AffineTransform m, Rectangle2D src, Rectangle2D dst ) { 115 double x0 = src.getMinX(); 116 double y0 = src.getMinY(); 117 double x1 = src.getMaxX(); 118 double y1 = src.getMaxY(); 119 double[] a = new double[] { 120 x0, y0, x1, y1, x0, y1, x1, y0 }; 125 m.transform( a, 0, a, 0, 4 ); 126 x0 = Math.min( Math.min(a[0],a[2]), Math.min(a[4],a[6]) ); 127 x1 = Math.max( Math.max(a[0],a[2]), Math.max(a[4],a[6]) ); 128 y0 = Math.min( Math.min(a[1],a[3]), Math.min(a[5],a[7]) ); 129 y1 = Math.max( Math.max(a[1],a[3]), Math.max(a[5],a[7]) ); 130 dst.setFrame( x0, y0, x1-x0, y1-y0 ); 131 return dst; 132 } 133 134 141 public static Rectangle2D calcBounds( AffineTransform m, Rectangle2D src ) { 142 return calcBounds( m, src, newRectangle() ); 143 } 144 145 152 public static Rectangle2D add( Rectangle2D dst, Rectangle2D src ) { 153 if( src == null ) return dst; 154 if( dst == null ) { 155 dst = (Rectangle2D ) src.clone(); 156 } else { 157 dst.add( src ); 158 } 159 return dst; 160 } 161 162 168 public static int getSize( Rectangle2D r ) { 169 int xmin = (int) r.getMinX(); 170 int xmax = (int) r.getMaxX(); 171 int ymin = (int) r.getMinY(); 172 int ymax = (int) r.getMaxY(); 173 174 int nBits = Util.getMinBitsS( Util.getMax(xmin,xmax,ymin,ymax) ); 175 int s = 5+nBits*4; 176 return (s+7)/8; 177 } 178 179 186 public static AffineTransform concatenate( AffineTransform m1, AffineTransform m2 ) { 187 AffineTransform res = (AffineTransform ) m1.clone(); 188 res.concatenate( m2 ); 189 return res; 190 } 191 192 private static final double c1 = 10000.0; 193 194 203 public static AffineTransform deScaleMatrix( AffineTransform m ) { 204 205 double scalex = 1.0; 206 double scaley = 1.0; 207 208 double[] r = new double[] { 0, c1, 0, 0, c1, 0 }; 209 210 m.transform( r, 0, r, 0, 3 ); 211 212 boolean mult = false; 213 double sz = getDist( r, 0 ); 214 if( Math.abs(sz-c1) > 1e-2 ) { 215 scaley = c1/sz; 216 mult = true; 217 } 218 sz = getDist( r, 2 ); 219 if( Math.abs(sz-c1) > 1e-2 ) { 220 scalex = c1/sz; 221 mult = true; 222 } 223 224 if( mult ) { 225 m.scale( scalex, scaley ); 226 } 227 return m; 228 } 229 230 238 public static double[] getMatrixScale( AffineTransform m ) { 239 240 double scalex = 1.0; 241 double scaley = 1.0; 242 243 double[] r = new double[] { 0, c1, 0, 0, c1, 0 }; 244 245 m.transform( r, 0, r, 0, 3 ); 246 247 double sz = getDist( r, 0 ); 248 if( Math.abs(sz-c1) > 1e-2 ) { 249 scaley = c1/sz; 250 } 251 sz = getDist( r, 2 ); 252 if( Math.abs(sz-c1) > 1e-2 ) { 253 scalex = c1/sz; 254 } 255 return new double[] {scalex, scaley}; 256 } 257 258 266 public static AffineTransform deRotateMatrix( AffineTransform m ) { 267 if( m.getShearX() == 0.0 && m.getShearY() == 0.0 ) return m; 268 269 double scalex = 1.0; 270 double scaley = 1.0; 271 272 double[] r = new double[] { 0, c1, 0, 0, c1, 0 }; 273 274 m.transform( r, 0, r, 0, 3 ); 275 276 double sz = getDist( r, 0 ); 277 if( Math.abs(sz-c1) > 1e-2 ) { 278 scaley = sz/c1; 279 } 280 sz = getDist( r, 2 ); 281 if( Math.abs(sz-c1) > 1e-2 ) { 282 scalex = sz/c1; 283 } 284 285 m.setTransform( scalex, 0, 0, scaley, m.getTranslateX(), m.getTranslateY() ); 286 return m; 287 } 288 289 295 public static double getDist( Rectangle2D r ) { 296 double dx = r.getWidth(); 297 double dy = r.getHeight(); 298 return Math.sqrt( dx*dx + dy*dy ); 299 } 300 301 307 public static double getDist( double[] r ) { 308 return getDist( r, 0 ); 309 } 310 311 318 public static double getDist( double[] r, int offset ) { 319 double dx = r[offset+2]-r[offset+0]; 320 double dy = r[offset+3]-r[offset+1]; 321 return Math.sqrt( dx*dx + dy*dy ); 322 } 323 324 332 public static Rectangle2D getTransformedSize( AffineTransform m, Rectangle2D r ) { 333 double[] a = new double[] { 0, r.getHeight(), 0, 0, r.getWidth(), 0 }; 334 335 m.transform( a, 0, a, 0, 3 ); 336 337 return newRectangle( 0, 0, getDist(a,2), getDist(a,0) ); 338 } 339 340 351 public static Point2D quadraticBezier( Point2D p0, Point2D p1, Point2D p2, double t ) { 352 double tt = t*t; double t1 = 1-t; double tt1 = t1*t1; double tt4 = 2*t*t1; 357 double x = p0.getX()*tt1 + p1.getX()*tt4 + p2.getX()*tt; 358 double y = p0.getY()*tt1 + p1.getY()*tt4 + p2.getY()*tt; 359 360 return new Point2D.Double (x,y); 361 } 362 363 375 public static Point2D cubicBezier( Point2D p0, Point2D p1, Point2D p2, Point2D p3, double t ) { 376 double tt = t*t; double ttt = tt*t; double t1 = 1-t; double tt1 = t1*t1; double tt2 = tt1*t1; double tt3 = 3*t*tt1; double tt4 = 3*tt*t1; 384 double x = p0.getX()*tt2 + p1.getX()*tt3 + p2.getX()*tt4 + p3.getX()*ttt; 385 double y = p0.getY()*tt2 + p1.getY()*tt3 + p2.getY()*tt4 + p3.getY()*ttt; 386 387 return new Point2D.Double (x, y); 388 } 389 390 435 public static Point2D [] CubicToQudratricBezier( Point2D p0, Point2D p1, Point2D p2, Point2D p3 ) { 436 IVVector quadPoints = new IVVector(); 437 438 Point2D q0 = p0; 440 Point2D q1 = getIntersectionPoint(p0, p1, p2, p3); 441 Point2D q2 = p3; 442 443 breakCubic( p0, p1, p2, p3, q0, q1, q2, 0.0, 1.0, quadPoints ); 445 446 Point2D [] res = new Point2D [ quadPoints.size() ]; 447 quadPoints.copyInto( res ); 448 return res; 449 } 450 451 private static void breakCubic( Point2D c0, Point2D c1, Point2D c2, Point2D c3, 452 Point2D q0, Point2D q1, Point2D q2, 453 double t0, double t1, IVVector result ) 454 { 455 double mp = t0+(t1-t0)*0.5; 457 Point2D cubic_mid_point = cubicBezier(c0, c1, c2, c3, mp); 458 459 Point2D quad_mid_point = quadraticBezier(q0, q1, q2, 0.5); 461 462 double dist = quad_mid_point.distance( cubic_mid_point ); 464 465 if( dist < 20 ) { 467 result.addElement( q0 ); 468 result.addElement( q1 ); 469 result.addElement( q2 ); 470 return; 471 } 472 473 Point2D dl = derivativeOfCubicBezier(c0, c1, c2, c3, mp); 475 476 dl.setLocation( dl.getX()+cubic_mid_point.getX(), dl.getY()+cubic_mid_point.getY() ); 478 479 Point2D qq1 = getIntersectionPoint(q0, q1, cubic_mid_point, dl); 481 breakCubic( c0, c1, c2, c3, q0, qq1, cubic_mid_point, t0, mp, result ); 482 483 qq1 = getIntersectionPoint(q2, q1, cubic_mid_point, dl); 485 breakCubic( c0, c1, c2, c3, cubic_mid_point, qq1, q2, mp, t1, result ); 486 } 487 488 498 private static Point2D derivativeOfCubicBezier( Point2D p0, Point2D p1, Point2D p2, Point2D p3, double t ) { 499 double ax = 3*p1.getX() - 3*p2.getX() - p0.getX() + p3.getX(); 500 double bx = 3*(p0.getX() - 2*p1.getX() + p2.getX()); 501 double cx = 3*(p1.getX() - p0.getX()); 502 503 double ay = 3*p1.getY() - 3*p2.getY() - p0.getY() + p3.getY(); 504 double by = 3*(p0.getY() - 2*p1.getY() + p2.getY()); 505 double cy = 3*(p1.getY() - p0.getY()); 506 507 double x = 3*ax*t*t + 2*bx*t + cx; 508 double y = 3*ay*t*t + 2*by*t + cy; 509 510 return new Point2D.Double (x, y); 511 } 512 513 524 public static Point2D getIntersectionPoint( Point2D a0, Point2D a1, Point2D b0, Point2D b1 ) { 525 double dAx = a1.getX()-a0.getX(); 526 double dAy = a1.getY()-a0.getY(); 527 double dBx = b1.getX()-b0.getX(); 528 double dBy = b1.getY()-b0.getY(); 529 double Fa = dAx*a0.getY() - dAy*a0.getX(); 530 double Fb = dBx*b0.getY() - dBy*b0.getX(); 531 double ddd = dBy*dAx - dBx*dAy; 532 533 double x = (Fa*dBx - Fb*dAx) / ddd; 534 double y = (Fa*dBy - Fb*dAy) / ddd; 535 536 return new Point2D.Double (x,y); 537 } 538 } 539 540 | Popular Tags |