//========================================================================================== // arc_point.txt // Author: Clif Collins Date: Jan 2010 //========================================================================================== //========================================================================================== // arcToPoint //========================================================================================== function arcToPoint(arc) { var points,x,y,cos,sin,p,angle; points = new Array(); x = arc.radius; y = 0; //---------- First Point ----------- angle = (arc.start / 180) * Math.PI; cos = Math.cos(angle); sin = Math.sin(angle); p = new Object(); p.x = ((x * cos) - (y * sin)) + arc.cx; p.y = ((x * sin) + (y * cos)) + arc.cy; points[0] = p //---------- Mid Point ----------- angle = ((arc.start + (arc.sweep / 2)) / 180) * Math.PI; cos = Math.cos(angle); sin = Math.sin(angle); p = new Object(); p.x = ((x * cos) - (y * sin)) + arc.cx; p.y = ((x * sin) + (y * cos)) + arc.cy; points[1] = p //---------- End Point ----------- angle = ((arc.start + arc.sweep) / 180) * Math.PI; cos = Math.cos(angle); sin = Math.sin(angle); p = new Object(); p.x = ((x * cos) - (y * sin)) + arc.cx; p.y = ((x * sin) + (y * cos)) + arc.cy; points[2] = p return points; } //====================================================================== // pointToArc //====================================================================== function pointToArc(pnt) { var arc,b1,b2,y2,aline,bline,dx,dy,pnt; var sdir,cdir,edir; var x1,y1,x2,y2,x3,y3; var ts,tc,te,rev; x1 = pnt[0].x; y1 = pnt[0].y; x2 = pnt[1].x; y2 = pnt[1].y; x3 = pnt[2].x; y3 = pnt[2].y; arc = new Object(); arc.start = 0; arc.sweep = 360; arc.radius = 0.0; arc.rev = true; //---------------------- Arc Center / Radius ------------------ b1 = bisectLine(x1,y1,x2,y2) // PERPENDICULAR BISECT if (b1 == null) return arc; b2 = bisectLine(x2,y2,x3,y3) // PERPENDICULAR BISECT if (b2 == null) return arc; pnt = isectLineLine(b1,b2); if (pnt == null) return arc; // lines do not intersect arc.cx = pnt.x; arc.cy = pnt.y dx = arc.cx - x1; dy = arc.cy - y1; arc.radius = Math.sqrt(dx*dx + dy*dy); //--------------------- Arc Angles ------------------------ sdir = lineAngle(arc.cx,arc.cy,x1,y1); cdir = lineAngle(arc.cx,arc.cy,x2,y2); edir = lineAngle(arc.cx,arc.cy,x3,y3); sdir = (sdir + 360) % 360; cdir = (cdir + 360) % 360; edir = (edir + 360) % 360; ts = Math.max(sdir,edir); te = Math.min(sdir,edir); tc = cdir; sdir = ts; edir = te; ts = ts - te tc = tc - te // ASSUME ORDERED ts = (ts + 360) % 360; tc = (tc + 360) % 360; if (ts > tc) { arc.rev = false; ts = sdir; sdir = (edir + 360) % 360; edir = ts; } //-------------- Set Arc ------------------ arc.start = sdir; arc.sweep = edir - sdir; if (arc.sweep > 360) arc.sweep = (360 - arc.sweep) % 360; return arc; } //====================================================================== // bisectLine //====================================================================== function bisectLine(x1,y1,x2,y2) { var A,B,C,length; var dx,dy,x,y,lin; dx = x2 - x1; dy = y2 - y1; length = Math.sqrt(dx*dx + dy*dy); if (length < 0.000001) return null; A = (y2 - y1) / length; B = (x1 - x2) / length; C = (-A * x1) - (B * y1) x = (x1 + x2) / 2.0; y = (y1 + y2) / 2.0; lin = new Object(); lin.A = B lin.B = -A lin.C = ((-lin.A) * x) - (lin.B * y) return lin; } //====================================================================== // isectLineLine //====================================================================== function isectLineLine(L1,L2) { var d,pnt; d = (L1.A * L2.B) - (L2.A * L1.B) if (Math.abs(d) < 0.00001) return null; pnt = new Object(); pnt.x = ((L1.B * L2.C) - (L2.B * L1.C)) / d pnt.y = ((L1.A * L2.C) - (L2.A * L1.C)) / (-d) return pnt; } //====================================================================== // lineAngle //====================================================================== function lineAngle(x1,y1,x2,y2) { var dir,dx,dy; dir = 0; dx = x2 - x1 dy = y2 - y1 if (Math.abs(dx) > 0.00001) { d = dy / dx dir = Math.atan(d); if (isNaN(dir)) dir = 0; if (Math.abs(dir) < 0.00001) dir = 0; if (dx < 0 && dy < 0) dir = dir + Math.PI; if (dx < 0 && dy >= 0) dir = dir + Math.PI; } else { dir = 270 / 180 * Math.PI; if (y2 > y1) dir = 90 / 180 * Math.PI; if (Math.abs(y2-y1) < 0.00001) dir = 0; } dir = dir * 180 / Math.PI; dir = (dir + 360) % 360; return dir; }