• fullscreen
  • Circle.pde
  • Coupling.pde
  • Line.pde
  • Point.pde
  • circleAndLineCoupling.pde
  • geometry.pde
  • public class Circle {
    
      public boolean drawn;
      public boolean hovered;  //if mouse is on top of the circle
      public boolean resizing; 
      public float radius;    //Diameter IRL, wrong naming
      
      public Vect2 center; 
    
      Circle() {
        center = new Vect2(0,0);
        radius = 0;
        drawn = false;
        hovered = false;
      }
      
      Circle( Vect2 cen, float rad){
        center = cen;
        radius = rad;   
        drawn = false;
        hovered = false;
        
      }
    
      void draw() {
        stroke(33, 107, 22);
        if (hovered) {
          strokeWeight(3);
        } 
        else {
          strokeWeight(2);
        }
        noFill();
        ellipse(center.x, center.y, radius, radius);
      }
    }
    
    
    public class Coupling {
      boolean drawHelpers;              //shows whether to draw helper-lines;
      boolean exists;                   //true if coupling exists
      private boolean radiusSpecified;  //shows whether radius have been specified by user
      float radius;                   //Coupling's radius
      Vect2 center;                   //Coupling ARC's center point
      Vect2 couplingCircleEnd;        //end of coupling arc, laying on the initial circle.
      Vect2 couplingLineEnd;          //end of coupling arc, laying on the initial line
    
      Coupling() {
        drawHelpers = false;
        radiusSpecified = false;
        couplingCircleEnd = new Vect2();
        couplingLineEnd = new Vect2();
      }
    
      void setRadius(float rad) {
        radius = rad;
        radiusSpecified = true;
      }
    
    
      /*calculates and draws coupling with no radius specified */
      void draw(Line ln, Circle circl, Point pnt) {
    
        //find intersection between line and perpendicular drawn through circle center. 
        Vect2 A1_CenterLinePerp = Space2.closestPointOnLine(circl.center, ln.P1, ln.P2);
    
        //finding out angle of the perpendicar, drawn prom the center of the circle
        Vect2 XPar = new Vect2(400,circl.center.y); // lies on X border of the canvas
        Vect2 A1_XPar = Space2.closestPointOnLine(A1_CenterLinePerp, circl.center, XPar);
    
    
        float Perp1AngleSin = dist(A1_XPar.x, A1_XPar.y, A1_CenterLinePerp.x, A1_CenterLinePerp.y) / dist(A1_CenterLinePerp.x, A1_CenterLinePerp.y, circl.center.x, circl.center.y);
    
        float Perp1Angle = asin(Perp1AngleSin);
        println(Perp1Angle);
    
        Vect2 ellipsePoint = Space2.ellipsePoint( Perp1Angle, circl.radius, circl.radius );
        println(ellipsePoint);
    
        if (drawHelpers) {
          stroke(229, 238, 250);
          //draw perpendicular between circle center and a line
          line(A1_CenterLinePerp.x, A1_CenterLinePerp.y, circl.center.x, circl.center.y);
    
          line(A1_CenterLinePerp.x, A1_CenterLinePerp.y, A1_XPar.x, A1_XPar.y);
        }
      }
    
      /*calculates and draws coupling with radius specified by user*/
      void draw(Line ln, Circle circle, float couplingRad) {
        /*
        1. calculate extended radius (helperRadius)
         2. calculate helperCircle with extended redius
         3. calculate relational position of circle center to line by creatng perpendicular to it (helperPerp)
         4. calculate coordinates of a line (helperLine) , parallel to given line on a distance RADIUS
         5. calculate intersection point (this.coulpling) between helperLine and helperCircle. is is this.coplingCenter
         6. create helperRadius from helperCircle.center to this.coplingCenter
         6. calculate intersection given circle and helperRadius. It is couplingLineCircle
         7. calculate intersection beteween Coupling.radus and couplingLineEnd
         8. draw coupling arc
         */
    
        //***1
        float extendedRad = circle.radius + couplingRad;
        //***2
        Vect2 helperPerp = Space2.closestPointOnLine(circle.center, ln.P1, ln.P2);
    
        //***3
        //perp.line slope (or tg lapha)
        float helperPerpM = (circle.center.y - helperPerp.y)/(circle.center.x - helperPerp.x);
        //perp.line B
        //float helperPerpB = helperPerp.y - helperPerpM * helperPerp.x;
        //looking for dots, equally far situated from main line on a distance R
        Vect2 hp1, hp2;
        hp1 = new Vect2(0,0);
        hp2 = new Vect2(0,0);
    
        hp1.x = couplingRad / sqrt( 1 + sq(helperPerpM) ) + helperPerp.x;
        hp1.y = helperPerpM * (hp1.x - helperPerp.x) + helperPerp.y;
    
        hp2.x = -1*(couplingRad / sqrt ( 1 + sq ( helperPerpM) ) ) + helperPerp.x;
        hp2.y = helperPerpM * (hp2.x - helperPerp.x) + helperPerp.y;    
        
        
        //***4
        //choose closest one to the center of the initial circle - this one is going to belong to (helperLine)
        Vect2 closestPointForPar = new Vect2();
    
        if (dist(circle.center.x, circle.center.y, hp1.x, hp1.y) < dist(circle.center.x, circle.center.y, hp2.x, hp2.y)) {
          closestPointForPar = hp1;
        } 
        else {
          closestPointForPar = hp2;
        }
    
        //substituting formula for line, parallel to initial line and going through (closestPointForPar)
        float ParLineM = -1 / helperPerpM;          //slope is perpendicular to helper line
        float ParLineB = closestPointForPar.y - ParLineM * closestPointForPar.x;//B is substituted by knowing point and slope (b = y - k*x)
    
        //substituing second point on parallel line to draw the line grahically
        Vect2 secParPoint = new Vect2(0,0);
        Vect2 secParPoint2 = new Vect2(0,0);
            
        if ( ParLineM < 0) {
          secParPoint = new Vect2(0,ParLineB);
          secParPoint2 = new Vect2((-1)*ParLineB/ParLineM,0);
        }  else if ( ParLineM > 0 ) {
            secParPoint = new Vect2(width,ParLineM*width + ParLineB);
            secParPoint2 = new Vect2((-1)*ParLineB/ParLineM,0);
        }
    
        //*** 5
        //creating helper objects to be used for their intersection calculation. 
        Line helperLine = new Line(secParPoint,secParPoint2);
        Circle helperCircle = new Circle(circle.center, extendedRad);
        
        Vect2[] helpersIntersections;
        helpersIntersections = new Vect2[2];
        
        helpersIntersections[0] = new Vect2();
        helpersIntersections[1] = new Vect2();    
        
          
        
        //checking for helpers intersection
        if(Geometry.circleRayIntersect(helperLine, helperCircle)) {
          this.exists = true;
          helpersIntersections = Geometry.circleRayIntersectPoints(helperLine, helperCircle);
          
          //choosing helpersIntersections[0] for coupling center. helpersIntersections[1] can be chosen also. 
          center = helpersIntersections[0];
          
          //*** 6 
          Vect2[] couplingCircleInt = new Vect2[2];
          couplingCircleInt[0] = new Vect2();
          couplingCircleInt[1] = new Vect2();
          
          
          //creating helper line 
          Line circleCenCouplingRad = new Line(circle.center, center);
          
          //finding intersections between initial circle center and Coupling radius
          couplingCircleInt = Geometry.circleRayIntersectPoints(circleCenCouplingRad, circle);
                
          //choosing closest intersection for 
          if (dist(couplingCircleInt[0].x, couplingCircleInt[0].y, center.x, center.y) < dist(couplingCircleInt[1].x, couplingCircleInt[1].y, center.x, center.y)){
            couplingCircleEnd = couplingCircleInt[0];
          } else {
            couplingCircleEnd = couplingCircleInt[1];
          }
          
          couplingLineEnd = Space2.closestPointOnLine(center, ln.P1, ln.P2);
          radius = dist(couplingLineEnd.x, couplingLineEnd.y, center.x, center.y);
    
          //intersection angle calculation
          float tana = (center.y - couplingLineEnd.y )/(center.x- couplingLineEnd.x);  
          float lineRadAngle = atan(tana);      
          float tanb = (center.y - couplingCircleEnd.y)/(center.x - couplingCircleEnd.x);
          float circleRadAngle = atan(tanb);
    
          //drawing coupling (YEEAH!)
          stroke(247, 128, 0);
          
          //println("Circle angle : " + circleRadAngle + " line angle " + lineRadAngle);
          //if line tangent is negative
          if(ln.slope < 0){
            //if circle is above the line, i.e line is in 1st qurter
            if(Geometry.relativePosition(center,couplingLineEnd) ==1 ){
              //if circle end is in 1st quarter
              if(Geometry.relativePosition(center,couplingCircleEnd) == 1 || Geometry.relativePosition(center,couplingCircleEnd) == 4){  
                arc (center.x, center.y, radius, radius, 0 + lineRadAngle, 0 + circleRadAngle);  
              }
              //if circle end is in 2nd quarter
              if(Geometry.relativePosition(center,couplingCircleEnd) == 2 || Geometry.relativePosition(center,couplingCircleEnd) == 3){  
                arc (center.x, center.y, radius, radius, 0 + lineRadAngle, PI + circleRadAngle); 
              }
            
            //if circle is below the line, e.g line is in 3rd qurter
            }else if (Geometry.relativePosition(center,couplingLineEnd) == 3 ){
              //if circle radius is in 2nd quarter:
              if(Geometry.relativePosition(center,couplingCircleEnd) == 2 || Geometry.relativePosition(center,couplingCircleEnd) == 3){
                arc (center.x, center.y, radius, radius, PI + circleRadAngle , PI +  lineRadAngle); 
              }    
              //if cirle radius is in 1st quarter
              if(Geometry.relativePosition(center,couplingCircleEnd) == 1 || Geometry.relativePosition(center,couplingCircleEnd) == 4){
                arc (center.x, center.y, radius, radius, 0 + circleRadAngle , PI +  lineRadAngle);      
              }
            }
            
          //if line tangent is positive
          }else if(ln.slope > 0){
            //if circle is below the line
            if(Geometry.relativePosition(center,couplingLineEnd) == 4 ){
              //if circle radius is in 2nd quarter:
              if(Geometry.relativePosition(center,couplingCircleEnd) == 2  || Geometry.relativePosition(center,couplingCircleEnd) == 3){
                arc (center.x, center.y, radius, radius, 0 + lineRadAngle, PI + circleRadAngle ); 
              }    
              //if cirle radius is in 1st quarter
              if(Geometry.relativePosition(center,couplingCircleEnd) == 1 || Geometry.relativePosition(center,couplingCircleEnd) == 4){
                arc (center.x, center.y, radius, radius, 0 + lineRadAngle, 0 + circleRadAngle);      
              }     
              
              
            //if circle is above the line
            } else if (Geometry.relativePosition(center,couplingLineEnd) == 2){
              //if circle radius is in 1st quarter:
              if(Geometry.relativePosition(center,couplingCircleEnd) == 1 || Geometry.relativePosition(center,couplingCircleEnd) == 4){
                arc (center.x, center.y, radius, radius, 0 + circleRadAngle, PI + lineRadAngle ); 
              }    
              //if cirle radius is in 2nd quarter
              if(Geometry.relativePosition(center,couplingCircleEnd) == 2 || Geometry.relativePosition(center,couplingCircleEnd) == 3){
                arc (center.x, center.y, radius, radius, PI + circleRadAngle, PI + lineRadAngle);        
              }
            }
           // arc (center.x, center.y, radius, radius, lineRadAngle, circleRadAngle );      //positive tangent, circle below
          //arc (center.x, center.y, radius, radius, circleRadAngle, lineRadAngle + PI);    //positive tangent, circle above +++
          }
          
          
          
        } else {
          this.exists = false;
          //println("ERROR: Coupling can not be drawn. Helper circle and helper line  do not have intersection points!!!");
          return;
        }
    
        
        if (drawHelpers) {
          stroke(200, 200, 200);
          strokeWeight(1);
          noFill();
          ellipse(circle.center.x, circle.center.y, extendedRad, extendedRad); //helper circle
          line(circle.center.x, circle.center.y, helperPerp.x, helperPerp.y);  //perpendicular from circel center to initial line
          
          ellipse(closestPointForPar.x,closestPointForPar.y,2,2);              //intersection between perp. and the initial circle
          //println("Parallel line. tg:  " +  ParLineM + " B: " + ParLineB);
          line(secParPoint.x, secParPoint.y, secParPoint2.x, secParPoint2.y);  //helper line, perallel to initial
          
          ellipse(helpersIntersections[0].x, helpersIntersections[0].y, 2,2);  //intersection 1 between helpers (line and circle)
          ellipse(helpersIntersections[1].x, helpersIntersections[1].y, 2,2);  //intersection 2 between helpers (line and circle)
          line(circle.center.x, circle.center.y, center.x, center.y);          //line between circle center and intersection 1
          ellipse(couplingCircleEnd.x, couplingCircleEnd.y, 2,2);              //Coupling and circle intersection
          line(couplingLineEnd.x, couplingLineEnd.y, center.x, center.y);
          ellipse(couplingLineEnd.x, couplingLineEnd.y,2,2);
        }
      }
    }
    
    
    public class Line{
      /*
      Draws line for coupling
      
      Point is located on the closest dot of the line to the circle center by default. 
      If user sets point position manually, point is relocated. 
      */
      
      boolean drawn;         //indicates whether line have been drawn by user
      boolean hovered;       //indicates whether line is hovered by mouse
      boolean dragging;      //shows that line is dragging now
      boolean dragP1;    //p1 is in relocation process
      boolean dragP2;    //p2 is in relocation process
      boolean dragWhole; //all segment is in relocation process
      float slope;           //line's tg
      float b;
      
      Vect2 P1, P2;          //points of the line in vector form
      
      Line(){
        drawn = false;
        hovered = false;
        P1 = new Vect2();
        P2 = new Vect2();
      }
      
      Line(Vect2 p1, Vect2 p2){
        drawn = false;
        hovered = false;
        P1 = p1;
        P2 = p2;
        slope = (P2.y - P1.y)/(P2.x - P1.x);
      }
      
      
      void draw(){
        slope = (P2.y - P1.y)/(P2.x - P1.x);
        b = P2.y - slope * P2.x;
        
        if (hovered){
          strokeWeight(3);
          stroke(229, 100, 0);
          ellipse(P1.x, P1.y, 2,2);
          ellipse(P2.x, P2.y, 2,2);
        } else {
          strokeWeight(2);
        }
        noFill();
        stroke(229, 0, 0);
        line(P1.x, P1.y, P2.x, P2.y);
        strokeWeight(1);
        //println("Original line's slope is: " + slope + "line's B is: " + b);
      }
    
      public void setCouplingPoint(Vect2 point){
      }
    }
    
    class Point{
     
     boolean userSet;
     //int x,y;
     Vect2 pos;      //position
     int diameter;    //thickness of the dot
     int aShift;    //indicates how far point is located from A 
     boolean hovered;//shows if mouse is above the point
     Vect2 mousPos;
     boolean dragging;
     
     Point(){
       pos = new Vect2(0,0);
       userSet = false;
       diameter = 2;
     } 
     
     Point(float px, float py){
       pos = new Vect2(0,0);
       hovered = false;
       diameter = 2;
       pos.x = px;
       pos.y = py; 
     }
     
     void draw(){
       if (hovered) {
         stroke(255,255,0);
         ellipse(pos.x, pos.y, diameter+1, diameter+1);
       } else {
         stroke(0,0,205);
         ellipse(pos.x, pos.y, diameter, diameter);
       }
     }
     
     void draw(float px, float py){
       pos.x = px;
       pos.y = py;
       if (hovered) {
         stroke(255,255,0);
         ellipse(pos.x, pos.y, diameter+1, diameter+1);
       } else {
         stroke(0,0,205);
         ellipse(pos.x, pos.y, diameter, diameter);
       }
     }
     /*
     moves mouse along the line it belongs to, setting precision meanwhile
     */
     void move(Line ln, int newX, int newY){
       // find projection of new mouse position to the line, point belogs to
       mousPos = new Vect2(newX, newY);
       pos = Space2.closestPointOnLineSegment(mousePos, ln.P1, ln.P2);
       println(mousePos);
       println(pos);
       // calculate distance between projection and line.P1
       
       //update precision
     }
     
     //draws point in the middle of the given line
     void drawMiddle(Line ln){
       pos = Vect2.midpoint(ln.P1, ln.P2);
     }
    }
    
    import point2line.*;  //library with some geometry methods.
    import controlP5.*;    //GUI controls library
    
    ControlP5 controlP5;
    Textlabel circleTL;
    Textlabel lineTL;
    Textlabel couplingTL;
    Textfield radiusTF;
    Textlabel instructionsTL1, instructionsTL2, instructionsTL3;
    
    String circleMsg;
    String lineMsg;
    String couplingMsg;
    
    String couplingRadInput;
    
    Circle circle;    
    Line ln;
    Point P;
    Coupling cpl;
    
    Vect2 pCoord;
    Vect2 mousePos;      //shows current position of mouse cursor
    Vect2 mousePress;    //shows coordinates of mouse when it was pressed
    //Vect2 mouseChanged;  //shows shift of mouse
    
    public final int canvasHeight = 500;
    public final int canvasWidth = 400;
    
    void setup() {
      size(400,500);
      ellipseMode(RADIUS);
      
      circleMsg = "";
      lineMsg = "";
      couplingMsg = "";
      couplingRadInput = "";
      
      controlP5 = new ControlP5(this);
      
      radiusTF = controlP5.addTextfield("Coupling Radius",20,400,100,20);
      radiusTF.setText("50");
      circleTL = controlP5.addTextlabel("label","Circle:",20,440);
      lineTL = controlP5.addTextlabel("label1","Line:",20,460);
      couplingTL = controlP5.addTextlabel("label2","Coupling:",20,480);
      
      instructionsTL1 = controlP5.addTextlabel("label3", "To draw a circle, press Left mouse button and drag the mouse", 20, 5);
      instructionsTL2 = controlP5.addTextlabel("label4", "To draw a line, press right mouse button and drag the mouse",20, 15 );
      instructionsTL3 = controlP5.addTextlabel("label5", "To move circle or line along the canvas, drag them",20, 25 );
      
      circle = new Circle();
      ln = new Line();
      P = new Point();
      mousePos = new Vect2();
      pCoord = new Vect2();
      mousePress = new Vect2();
      cpl = new Coupling();
      
      
      background(255,255,255);
      smooth();
    }
    
    void draw() {
      background(0);//overwrites previous frame
        
      circle.draw();
      ln.draw();
        
      //taking user input
      couplingRadInput = radiusTF.getText();
      if (couplingRadInput != ""){
        try{
          cpl.radius = Float.valueOf(couplingRadInput.trim()).floatValue(); 
          cpl.radiusSpecified = true;
        } catch (NumberFormatException nfe){
          println("ERROR: radius shall be numerical");
        }
      }
        
      //draws coupling
      if ( circle.drawn && ln.drawn ){
        cpl.drawHelpers = true;
        if (cpl.radius > 0) {
          cpl.draw(ln, circle, cpl.radius);    //
          if(cpl.exists){
          couplingMsg = "COUPLING: radius: " + cpl.radius + "  Center (x: " + cpl.center.x + 
                     " y: " + cpl.center.y + ")";
          } else {
            couplingMsg = "!!Coupling with radius " + cpl.radius + " does not exist. Change radius";
          }
        } else {
          couplingMsg = "!!Coupling radius can not be negative";
        }
        couplingTL.setValue(couplingMsg);
      }
    }
    
    
    void mouseMoved(){
      mousePos.x = mouseX;
      mousePos.y = mouseY;  
      if (Geometry.pointOnEndOfLineSegment(ln,mousePos)){
        cursor(MOVE);
        return;
      }
      if (Geometry.pointOnLine(ln, mousePos)){
        /*mouse hovers a line*/
        ln.hovered = true;
        cursor(HAND);
        return;
      } else {
        ln.hovered = false;
        //cursor(ARROW);
        if(!ln.drawn || !circle.drawn){
          cursor(CROSS);
        }else{ 
          cursor(ARROW);
        }
      }
      
      //mouse hovers a circle
      if ( Geometry.pointInsideCircle(circle, mousePos)){
        circle.hovered = true;
        cursor(HAND);
        return;
      } else if (Geometry.pointOnCircleBorder(circle, mousePos)){
        /* mouse hovers the border of a circle */
        circle.hovered = true;
        cursor(MOVE);
        return;
      } else {
        circle.hovered = false;
        //cursor(ARROW);
        if(!ln.drawn || !circle.drawn){
          cursor(CROSS);
        }else{ 
          cursor(ARROW);
        }
      }    
    }
    
    
    
    void mousePressed() {
      if (mouseButton == LEFT) {
         mousePress = mousePos;
         if(ln.drawn && Geometry.pointInsideCircle(ln.P1, 4, mousePos ) ){
            ln.dragging = true;
            ln.dragP1 = true;
            return;
         }
         if(ln.drawn && Geometry.pointInsideCircle(ln.P2, 4, mousePos ) ){
            ln.dragging = true;
            ln.dragP2 = true;
            return;
         }
         if(ln.drawn && Geometry.pointOnLine(ln, mousePos)){
             mousePress.x = mouseX;
             mousePress.y = mouseY;
             ln.dragWhole = true;
             return;
         }
         if (circle.drawn && Geometry.pointOnCircleBorder(circle, mousePos)){
           mousePress.x = mouseX;
           mousePress.y = mouseY;
           circle.resizing = true;
           return;
         }
         if (!circle.drawn && !ln.hovered){
            circle.center.x = mouseX;
            circle.center.y = mouseY;
            return;
         }
      }
      else if(mouseButton == RIGHT) {
        if(!ln.drawn){
          ln.P1.x = mouseX;
          ln.P1.y = mouseY;
          ln.P2.x = mouseX;
          ln.P2.y = mouseY;
        }
      }
    }
    
    
    
    
    void mouseDragged() {
      //circle is drawing
      if(mouseButton == LEFT) {
        
        //change she shape of circle if circle is not drawn yet
        if (!circle.drawn && !ln.hovered){
          //draw the circle
          int relX = mouseX;
          int relY = mouseY;
          circle.radius = dist(circle.center.x, circle.center.y, relX, relY);
                
        } else if (ln.drawn && ln.dragWhole){
          /*
          change position of the whole line segment
          */
          Vect2 posDiff = new Vect2(mousePress.x - mouseX, mousePress.y - mouseY);
          ln.P1.subtract(posDiff);
          ln.P2.subtract(posDiff);
          mousePress.x=mouseX;
          mousePress.y=mouseY;
          //println("mp" + mousePress.x + ", " + mousePress.y + " posDiff: " + posDiff.x + ", " + posDiff.y);
          
        }else if (ln.drawn && ln.dragging && ln.dragP1){
          /*
          change position of line segment
          */
          ln.P1.x = mouseX;
          ln.P1.y = mouseY;
        }else if (ln.drawn && ln.dragging && ln.dragP2){
          /*
          change position of another line segment
          */
          ln.P2.x = mouseX;
          ln.P2.y = mouseY;
        }else if (circle.drawn && circle.hovered && !circle.resizing) {
          /*
          move the circle
          */  
          Vect2 DragDiff = new Vect2(mousePress.x - mouseX, mousePress.y - mouseY);
          
          circle.center.subtract(DragDiff);
          mousePress.x=mouseX;
          mousePress.y=mouseY;
          
        }else if (circle.drawn && circle.resizing){
          circle.radius = dist (circle.center.x, circle.center.y, mouseX, mouseY);
        }
      }
      //line is drawing
      else if(mouseButton == RIGHT) {
        if(!ln.drawn){
          //draw the line
          ln.P2.x = mouseX;
          ln.P2.y = mouseY;
        }else if (ln.drawn && ln.hovered) {
          //move the line
        }
      }
    }
    
    void mouseReleased() {
      if(mouseButton == LEFT) {
        circle.drawn = true;
        //P.dragging = false;
        circleMsg = "CIRCLE    Center: x: " + circle.center.x + "; y: " + circle.center.y + ";     Radius: " + circle.radius;
        circleTL.setValue(circleMsg);
        ln.dragging = false;
        ln.dragP1 = false;
        ln.dragP2 = false;
        ln.dragWhole = false;
        circle.resizing = false;
      } 
      else if(mouseButton == RIGHT) {
        ln.drawn = true;
        lineMsg = "LINE      A (" + ln.P1.x + ", " + ln.P2.y + "), B (" + ln.P2.x + ", " + ln.P2.y + ")";
        lineTL.setValue(lineMsg);
      }
      
    }
    
    static class Geometry {
      
      static private final float accuracy = 2;
      
      public Geometry() {
        
      }
    
    /*returns unit circle quarter position of one point to another, 
    considering first point a cnter of a unit cicle.
    @param   center - center of imaginery unit circle
    @param   checkPoint - relative point
    
    @return 1 - 1st quarter, e.g. right top quarter
    @return 2 - 2nd quarter, e.g. left top quarter
    @return 3 - 3nd quarter, e.g  left bottom quarter
    @return 4 - 4th quarter, e.g  right bottom quarter
    @return 0 - checkPoint is on the border of the quarters
    */
    static int relativePosition(Vect2 center, Vect2 checkPoint){
      //in the first quarter. Note, in screen coordinates posive Y goes down,
      //and opposite to casual cartesian coordinates. That is why quarters appear to be 
      //vertically reversed.
      if (center.x < checkPoint.x && center.y > checkPoint.y){
        return 4;
      }else if (center.x > checkPoint.x && center.y > checkPoint.y) {
        return 3;
      } else if (center.x > checkPoint.x && center.y < checkPoint.y){
        return 2;
      } else if (center.x < checkPoint.x && center.y < checkPoint.y){
        return 1;
      } else {
        return 0;
      }
    }
    
    
    
      /*
      @input cCen - input point
       @input 
       @returns point of line, closest to given point
       method calculates what end of the line is the closest to the point
       */
      static Vect2 closestLineEndToPoint(Vect2 cCen, Vect2 vect1, Vect2 vect2) {
        Vect2 closestPoint = new Vect2();
    
        if (dist(vect1.x,vect1.y,cCen.x, cCen.y) <= dist(vect2.x,vect2.y, cCen.x, cCen.y)) {
          closestPoint = vect1;
        }
        else {
          closestPoint = vect2;
        }   
        return closestPoint;
      }
      /*
      @returns true if point is inside the circle. 
       @returns false if point is outside the circle.
       */
      static boolean pointInsideCircle( Circle cir, Vect2 pnt) {
        if(dist(cir.center.x, cir.center.y, pnt.x, pnt.y) <= cir.radius - accuracy) {
          return true;
        }
        else {
          return false;
        }
      }
      
      static boolean pointInsideCircle(int cenX, int cenY, float radius, Vect2 pnt){
       if(dist( cenX, cenY, pnt.x, pnt.y ) <= radius - accuracy){
         return true;
       } else {
         return false;
       }
      }
      
      static boolean pointInsideCircle(Vect2 center, float radius, Vect2 pnt){
        if(dist(center.x, center.y, pnt.x, pnt.y) <= radius - accuracy) {
         return true;
       } else {
         return false;
       }
      }
      
      static boolean pointOnCircleBorder(Circle cir, Vect2 pnt){
        float dst = dist(cir.center.x, cir.center.y, pnt.x, pnt.y);
        if (dst <= cir.radius + accuracy && dst >= cir.radius - accuracy) {
              return true;
            }else
              return false;
      }
      
     /*
     @returns true if point belongs to line  
       @return false if not. 
       *
       the function is not mathematically correct and shall be applied only on user interfaces. 
       It's intended to rougly determine if mouse hovers the line
       *
       Point is considered to belong to the line if a distance between 
       point and line is less than 1. The number can be increased due to usability 
       */
      static boolean pointOnLine(Line ln, Vect2 pnt) {
        Vect2 perpIntersection = Space2.closestPointOnLineSegment( pnt, ln.P1, ln.P2 );
        float distance = dist(pnt.x, pnt.y, perpIntersection.x, perpIntersection.y);
        if (distance < accuracy  ) {
          return true;
        } 
        else {
          return false;
        }
      }
    
    
    
      
      static boolean pointOnEndOfLineSegment(Line ln, Vect2 pnt){
        if (Vect2.distance(ln.P1, pnt) < accuracy||  Vect2.distance(ln.P2, pnt) < accuracy){
          return true;
        } else {
          return false;
        }
      }
      /*
      @input Vect2 main - subject of comparison
      @input Vect2[] points
      
      chooses closest point from array of point to the point
      *
      @returns Vect2, 
      *
      static void  Vect2 closesPoint(Vect2 main, Vect2 ppl[]) {
        Vect2 closest = new vect2();
        return closest; 
      }
      */
    
    
      /*
       @returns true if one point is rougly close to another point
       @returns false if far
       * 
       this function is designed to be used in mouse-driven UI and checks if mouse hovers point. 
       */
      static boolean pointOnPoint(Point pnt, Vect2 mPos) {
        if (dist(pnt.pos.x, pnt.pos.y, mPos.x, mPos.y ) <  2) {
          return true;
        } 
        else 
          return false;
      }
    
    
    
    
    
      static Line parallelLineThhroughPoint(Line ln, Vect2 towards) {
        //   Line newLine = new Line();
    
        return ln;
      }
    
      /*
      @returns true if circle and line are intersecting
       false if not intersecting
       */
      static boolean circleRayIntersect(Line ln, Circle circle) {
        //line point A
        float x1 = ln.P1.x;
        float y1 = ln.P1.y;
    
        //line point B
        float x2 = ln.P2.x;
        float y2 = ln.P2.y;
    
        //circle center and radius
        float cx = circle.center.x;
        float cy = circle.center.y;
        float cr = circle.radius;
    
        //intersection points
        Vect2[] intersections;
        intersections = new Vect2[2];
    
        float dx = x2 - x1;
        float dy = y2 - y1;
        float a = dx * dx + dy * dy;
        float b = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
        float c = cx * cx + cy * cy;
        c += x1 * x1 + y1 * y1;
        c -= 2 * (cx * x1 + cy * y1);
        c -= cr * cr;
        float bb4ac = b * b - 4 * a * c;
    
        //println(bb4ac);
    
        if (bb4ac < 0) {  // Not intersecting
          return false;
        }
        else {
          return true;
        }
      }
      /*
      @returns points of circle and ray intersection
       
       CAUTION: method does not check whether circle and rey intersect. If they do not intersect, method won't work.
       */
      static Vect2[] circleRayIntersectPoints(Line ln, Circle circle) {
        //line point A
        float x1 = ln.P1.x;
        float y1 = ln.P1.y;
    
        //line point B
        float x2 = ln.P2.x;
        float y2 = ln.P2.y;
    
        //circle center and radius
        float cx = circle.center.x;
        float cy = circle.center.y;
        float cr = circle.radius;
    
        //intersection points
        Vect2[] intersections;
        intersections = new Vect2[2];
    
        float dx = x2 - x1;
        float dy = y2 - y1;
        float a = dx * dx + dy * dy;
        float b = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
        float c = cx * cx + cy * cy;
        c += x1 * x1 + y1 * y1;
        c -= 2 * (cx * x1 + cy * y1);
        c -= cr * cr;
        float bb4ac = b * b - 4 * a * c;
    
        float mu = (-b + sqrt( b*b - 4*a*c )) / (2*a);
        float ix1 = x1 + mu*(dx);
        float iy1 = y1 + mu*(dy);
        mu = (-b - sqrt(b*b - 4*a*c )) / (2*a);
        float ix2 = x1 + mu*(dx);
        float iy2 = y1 + mu*(dy);
    
        // The intersection points
        intersections[0] = new Vect2(ix1, iy1);
        intersections[1] = new Vect2(ix2, iy2);
        return intersections;
      }
    }
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    Svyatoslav Evzhenkov

    Circle and Line Coupling

    Add to Faves Me Likey@! 1
    You must login/register to add this sketch to your favorites.

    The application draws coupling between a circle and a line.

    Usage:
    - press LMB and drag to draw a circle
    - press RMB and drag to draw a line
    - drag an items by hovering an item and rdagging
    - resize a circle by dragging the circle's border
    - resize a line by dragging the line's ends

    Features:
    - mouse UI
    - a radius of the coupling can be set
    - the algorithm of rendering is not the most efficient one

    You need to login/register to comment.