trigonometry - Java Draw Arc Between 2 Points -


i'm having trouble drawing smallest arc described 3 points: arc center, "anchored" end point, , second point gives other end of arc determining radius. used law of cosines determine length of arc , tried using atan starting degree, starting position arc off.

i managed arc lock onto anchor point (x1,y1) when it's in quadrant 2, work when in quadrant 2.

solutions can see have bunch of if-statements determine location of 2 points relative each other, i'm curious if i'm overlooking simple. appreciated.

sscce:

import javax.swing.jcomponent; import javax.swing.jframe;  import java.awt.event.mouseevent; import java.awt.event.mouselistener; import java.awt.geom.*; import java.awt.*; import java.util.*;  class canvas extends jcomponent {     float circlex, circley, x1, y1, x2, y2, dx, dy, dx2, dy2, radius, radius2;     random random = new random();      public canvas() {          //setup.           x1 = random.nextint(250);         y1 = random.nextint(250);          //cant have x2 == circlex         while (x1 == 150 || y1 == 150)         {             x1 = random.nextint(250);             y1 = random.nextint(250);         }          circlex = 150; //circle center dead center.         circley = 150;           //radius between 2 points must equal.         dx = math.abs(circlex-x1);         dy = math.abs(circley-y1);          //c^2 = a^2 + b^2 solve radius         radius = (float) math.sqrt((float)math.pow(dx, 2) + (float)math.pow(dy, 2));          //2nd random point         x2 = random.nextint(250);         y2 = random.nextint(250);          //i need push out radius length, because radius equal both points.         dx2 = math.abs(circlex-x2);         dy2 = math.abs(circley-y2);         radius2 = (float) math.sqrt((float)math.pow(dx2, 2) + (float)math.pow(dy2, 2));          dx2 *= radius/radius2;         dy2 *= radius/radius2;          y2 = circley+dy2;         x2 = circlex+dx2;         //radius equal both points.     }      public void paintcomponent(graphics g2) {         graphics2d g = (graphics2d) g2;         g.setrenderinghint(renderinghints.key_antialiasing,                 renderinghints.value_antialias_on);         g.setstroke(new basicstroke(2.0f, basicstroke.cap_butt,                 basicstroke.join_bevel));          arc2d.float centerpoint = new arc2d.float(150-2,150-2,4,4, 0, 360, arc2d.open);         arc2d.float point1 = new arc2d.float(x1-2, y1-2, 4, 4, 0, 360, arc2d.open);         arc2d.float point2 = new arc2d.float(x2-2, y2-2, 4, 4, 0, 360, arc2d.open);          //3 points drawn in black         g.setcolor(color.black);         g.draw(centerpoint);         g.draw(point1);         g.draw(point2);          float start = 0;         float distance;          //form right triangle find length of hypotenuse.         distance = (float) math.sqrt(math.pow(math.abs(x2-x1),2) + math.pow(math.abs(y2-y1), 2));          //law of cosines determine internal angle between 2 points.         distance = (float) (math.acos(((radius*radius) + (radius*radius) - (distance*distance)) / (2*radius*radius)) * 180/math.pi);          float deltay = circley - y1;         float deltax = circlex - x1;          float deltay2 = circley - y2;         float deltax2 = circlex - x2;          float angleindegrees = (float) ((float) math.atan((float) (deltay / deltax)) * 180 / math.pi);         float angleindegrees2 = (float) ((float) math.atan((float) (deltay2 / deltax2)) * 180 / math.pi);          start = angleindegrees;          //q2 works.         if (x1 < circlex)         {             if (y1 < circley)             {                 start*=-1;                 start+=180;             } else if (y2 > circlex) {                 start+=180;                 start+=distance;             }         }          //system.out.println("start: " + start);         //arc drawn in blue         g.setcolor(color.blue);         arc2d.float arc = new arc2d.float(circlex-radius,  //center x                                            circley-radius,  //center y rotates around point.                                           radius*2,                                           radius*2,                                           start, //start degree                                           distance, //distance travel                                           arc2d.open); //type of arc.         g.draw(arc);     } }  public class angle implements mouselistener {      canvas view;     jframe window;      public angle() {         window = new jframe();         view = new canvas();         view.addmouselistener(this);         window.setdefaultcloseoperation(jframe.exit_on_close);         window.setbounds(30, 30, 400, 400);         window.getcontentpane().add(view);         window.setvisible(true);     }      public static void main(string[] a) {         new angle();     }      @override     public void mouseclicked(mouseevent arg0) {         window.getcontentpane().remove(view);         view = new canvas();         window.getcontentpane().add(view);         view.addmouselistener(this);         view.revalidate();         view.repaint();     }      @override     public void mouseentered(mouseevent arg0) {         // todo auto-generated method stub      }      @override     public void mouseexited(mouseevent arg0) {         // todo auto-generated method stub      }      @override     public void mousepressed(mouseevent arg0) {         // todo auto-generated method stub      }      @override     public void mousereleased(mouseevent arg0) {         // todo auto-generated method stub      } } 

perhaps help. tests click , drag set 2 points rather random numbers. it's considerably simpler attempting , other solutions posted far.

notes:

  • math.atan2() friend in problems this.
  • little helper functions make easier reason code.
  • it's best practice use instance variables independent values , compute dependent values in local variables.
  • my code fixes swing usage problems calling swing functions main thread.

code follows:

import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import javax.swing.*; import javax.swing.event.mouseinputadapter;  class testcanvas extends jcomponent {      float x0 = 150f, y0 = 150f;   // arc center. subscript 0 used center throughout.     float xa = 200f, ya = 150f;   // arc anchor point.  subscript anchor.     float xd = 150f, yd =  50f;   // point determining arc angle. subscript d determiner.      // return distance point arc center.     float dist0(float x, float y) {         return (float)math.sqrt(sqr(x - x0) + sqr(y - y0));     }      // return polar angle of point relative arc center.     float angle0(float x, float y) {         return (float)math.todegrees(math.atan2(y0 - y, x - x0));     }      @override     protected void paintcomponent(graphics g0) {         graphics2d g = (graphics2d) g0;          // can draw center point.         dot(g, x0, y0);          // radii of anchor , det point.         float ra = dist0(xa, ya);         float rd = dist0(xd, yd);          // if either 0 there's nothing else draw.         if (ra == 0 || rd == 0) { return; }          // angles center points.         float aa = angle0(xa, ya);         float ad = angle0(xd, yd);  // (xb, yb) work fine, too.          // draw arc , other dots.         g.draw(new arc2d.float(x0 - ra, y0 - ra, // box upper left                 2 * ra, 2 * ra,                  // box width , height                 aa, anglediff(aa, ad),           // angle start, extent                  arc2d.open));         dot(g, xa, ya);          // use similar triangles second dot location.         float xb = x0 + (xd - x0) * ra / rd;         float yb = y0 + (yd - y0) * ra / rd;         dot(g, xb, yb);     }      // helper functions.      // draw small dot current color.     static void dot(graphics2d g, float x, float y) {         final int rad = 2;         g.fill(new ellipse2d.float(x - rad, y - rad, 2 * rad, 2 * rad));     }      // return square of float.     static float sqr(float x) { return x * x; }      // find angular difference between , b, -180 <= diff < 180.     static float anglediff(float a, float b) {         float d = b - a;         while (d >= 180f) { d -= 360f; }         while (d < -180f) { d += 360f; }         return d;     }      // construct test canvas mouse handling.     testcanvas() {         addmouselistener(mouselistener);         addmousemotionlistener(mouselistener);     }      // listener changes arc parameters click , drag.     mouseinputadapter mouselistener = new mouseinputadapter() {         boolean mousedown = false; // left mouse button down?          @override         public void mousepressed(mouseevent e) {             if (e.getbutton() == mouseevent.button1) {                 mousedown = true;                 xa = xd = e.getx();                 ya = yd = e.gety();                 repaint();             }         }          @override         public void mousereleased(mouseevent e) {             if (e.getbutton() == mouseevent.button1) {                 mousedown = false;             }         }          @override         public void mousedragged(mouseevent e) {             if (mousedown) {                 xd = e.getx();                 yd = e.gety();                 repaint();             }         }     }; }  public class test extends jframe {      public test() {         setsize(400, 400);         setlocationrelativeto(null);         setdefaultcloseoperation(jframe.exit_on_close);         getcontentpane().add(new testcanvas());     }      public static void main(string[] args) {         // swing code must run in ui thread,         // must invoke setvisible rather calling it.         swingutilities.invokelater(new runnable() {             @override             public void run() {                 new test().setvisible(true);             }         });     } } 

Comments

Popular posts from this blog

blackberry 10 - how to add multiple markers on the google map just by url? -

php - guestbook returning database data to flash -

delphi - Dynamic file type icon -