Advertisement
bekovski

algovi_sat_v1

Jun 24th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 28.59 KB | None | 0 0
  1. import java.awt.Color;
  2. import java.awt.Font;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import algoanim.animalscript.AnimalCircleGenerator;
  7. import algoanim.animalscript.AnimalPointGenerator;
  8. import algoanim.animalscript.AnimalPolylineGenerator;
  9. import algoanim.animalscript.AnimalRectGenerator;
  10. import algoanim.animalscript.AnimalScript;
  11. import algoanim.animalscript.AnimalTextGenerator;
  12. import algoanim.animalscript.AnimalTriangleGenerator;
  13. import algoanim.primitives.Circle;
  14. import algoanim.primitives.Point;
  15. import algoanim.primitives.Polyline;
  16. import algoanim.primitives.Rect;
  17. import algoanim.primitives.SourceCode;
  18. import algoanim.primitives.Text;
  19. import algoanim.primitives.Triangle;
  20. import algoanim.primitives.generators.Language;
  21. import algoanim.properties.AnimationPropertiesKeys;
  22. import algoanim.properties.CircleProperties;
  23. import algoanim.properties.PointProperties;
  24. import algoanim.properties.PolylineProperties;
  25. import algoanim.properties.RectProperties;
  26. import algoanim.properties.SourceCodeProperties;
  27. import algoanim.properties.TextProperties;
  28. import algoanim.properties.TriangleProperties;
  29. import algoanim.util.Coordinates;
  30. import algoanim.util.Node;
  31. import algoanim.util.TicksTiming;
  32. import algoanim.util.Timing;
  33. import auxiliary.Vector2f;
  34.  
  35. public class SAT {
  36.    
  37.     public static final Color LINE_DEFAULT_COLOR    = Color.BLACK;
  38.     public static final Color VECTOR_DEFAULT_COLOR  = Color.RED;
  39.    
  40.     Language lang;
  41.    
  42.     Text text;
  43.     Point point;
  44.     Circle circle;
  45.     Polyline line;
  46.     Polyline edge;
  47.     Polyline vector;
  48.     Polyline separatingAxis;
  49.     Triangle triangle;
  50.    
  51.     // temp
  52.     Polyline[] vectors = new Polyline[3];
  53.    
  54.     SourceCode sc;
  55.     Timing timing;
  56.    
  57.     // might need these properties
  58.     TextProperties textProps;
  59.     RectProperties rectProps;
  60.     PointProperties pointProps;
  61.     CircleProperties circleProps;
  62.     PolylineProperties lineProps;
  63.     PolylineProperties vectorProps;
  64.     TriangleProperties triangleProps;
  65.    
  66.    
  67.     int x = 40;
  68.     int y = 140;
  69.     int startY;
  70.     int offsetY = 20;
  71.     String vertexName;
  72.     String neighbor1Name;
  73.     String neighbor2Name;
  74.    
  75.     List<Text> textList = new ArrayList<>();
  76.    
  77.     public void init() {
  78.         lang = new AnimalScript("Separating Axis Theorem (Circle-Triangle)", "Bekir Oezkara", 640, 480);
  79.         lang.setStepMode(true);
  80.        
  81.         timing = new TicksTiming(200);
  82.        
  83.         textProps = new TextProperties();
  84.         textProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLACK);
  85.         textProps.set(AnimationPropertiesKeys.FONT_PROPERTY, new Font("Monospaced", Font.PLAIN, 12));
  86.        
  87.         rectProps = new RectProperties();
  88.         rectProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.DARK_GRAY);
  89.         rectProps.set(AnimationPropertiesKeys.FILLED_PROPERTY, true);
  90.         rectProps.set(AnimationPropertiesKeys.FILL_PROPERTY, Color.LIGHT_GRAY);
  91.         rectProps.set(AnimationPropertiesKeys.DEPTH_PROPERTY, 2);
  92.        
  93.         pointProps = new PointProperties();
  94.         pointProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.CYAN);
  95.        
  96.         circleProps = new CircleProperties();
  97. //      circleProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.RED);
  98.         circleProps.set(AnimationPropertiesKeys.FILL_PROPERTY, Color.WHITE);
  99.        
  100.         lineProps = new PolylineProperties();
  101.         lineProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, LINE_DEFAULT_COLOR);
  102.        
  103.         vectorProps = new PolylineProperties();
  104.         vectorProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, VECTOR_DEFAULT_COLOR);
  105.         vectorProps.set(AnimationPropertiesKeys.FWARROW_PROPERTY, true);
  106.        
  107.         triangleProps = new TriangleProperties();
  108. //      triangleProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.GREEN);
  109.         triangleProps.set(AnimationPropertiesKeys.FILL_PROPERTY, Color.WHITE);
  110.        
  111.         makeHeader();
  112.         makeSideBox();
  113.         drawCoordSystem();
  114.        
  115.     }
  116.    
  117.    
  118.     public boolean hasSA(auxiliary.Circle circle, auxiliary.Triangle triangle) {
  119.        
  120.         makeCircle(circle.center.x, circle.center.y, circle.radius);
  121.         makeTriangle(triangle.A, triangle.B, triangle.C);
  122.         lang.nextStep();
  123.        
  124.         x = 910;
  125.         startY = 160;
  126.         y = startY;
  127.        
  128.         // vertices
  129.         showSourceCodeVertexSA();
  130.         Circle vertexHighlightCircle;
  131.         boolean isFilled = true;
  132.        
  133.         vertexName = "A";
  134.         neighbor1Name = "B";
  135.         neighbor2Name = "C";
  136.         vertexHighlightCircle = makeCircle(triangle.A.x, triangle.A.y, 0.1f, Color.PINK, isFilled);
  137.         textAndStep("Vertex A");
  138.         vertexHighlightCircle.hide();
  139.         boolean separatedByVertexA = isVertexSA(circle, triangle, triangle.A);
  140.        
  141.         clearText();
  142.         y = startY;
  143.        
  144.         vertexName = "B";
  145.         neighbor1Name = "A";
  146.         neighbor2Name = "C";
  147.         vertexHighlightCircle = makeCircle(triangle.B.x, triangle.B.y, 0.1f, Color.PINK, isFilled);
  148.         textAndStep("Vertex B");
  149.         vertexHighlightCircle.hide();
  150.         boolean separatedByVertexB = isVertexSA(circle, triangle, triangle.B);
  151.        
  152.         clearText();
  153.         y = startY;
  154.        
  155.         vertexName = "C";
  156.         neighbor1Name = "A";
  157.         neighbor2Name = "B";
  158.         vertexHighlightCircle = makeCircle(triangle.C.x, triangle.C.y, 0.1f, Color.PINK, isFilled);
  159.         textAndStep("Vertex C");
  160.         vertexHighlightCircle.hide();
  161.         boolean separatedByVertexC = isVertexSA(circle, triangle, triangle.C);
  162.        
  163.         clearText();
  164.         y = startY;
  165.        
  166.         // edges
  167.         sc.changeColor("", Color.WHITE, null, null);
  168.         showSourceCodeEdgeSA();
  169.        
  170.         edge = makeLine(triangle.A, triangle.B, false, true);
  171.         edge.changeColor("", Color.PINK, null, null);
  172.         textAndStep("Edge from A to B");
  173.         boolean separatedByEdgeAB = isEdgeSA(circle, triangle, triangle.edgeAB, triangle.A, triangle.B, triangle.C);
  174.         edge.hide();
  175.        
  176.         clearText();
  177.         y = startY;
  178.        
  179.         edge = makeLine(triangle.A, triangle.C, false, true);
  180.         edge.changeColor("", Color.PINK, null, null);
  181.         textAndStep("Edge from A to C");
  182.         boolean separatedByEdgeAC = isEdgeSA(circle, triangle, triangle.edgeAC, triangle.A, triangle.C, triangle.B);
  183.         edge.changeColor("", Color.BLACK, null, null);
  184.        
  185.         clearText();
  186.         y = startY;
  187.        
  188.         edge = makeLine(triangle.B, triangle.C, false, true);
  189.         edge.changeColor("", Color.PINK, null, null);
  190.         textAndStep("Edge from B to C");
  191.         boolean separatedByEdgeBC = isEdgeSA(circle, triangle, triangle.edgeBC, triangle.B, triangle.C, triangle.A);
  192.         edge.hide();
  193.        
  194.         clearText();
  195.         y = startY;
  196.        
  197.         boolean result = separatedByVertexA || separatedByVertexB || separatedByVertexC || separatedByEdgeAB || separatedByEdgeAC || separatedByEdgeBC;
  198.         if(result) {
  199.             separatingAxis.changeColor("", Color.GREEN, null, null);
  200.             separatingAxis.show();
  201.         }
  202.         textAndStep("we found separating axis = " + result);
  203.         return result;
  204.     }
  205.    
  206.    
  207.     /**
  208.      *
  209.      * @param circle
  210.      * @param triangle
  211.      * @param vertex
  212.      * @return
  213.      */
  214.     private boolean isVertexSA(auxiliary.Circle circle, auxiliary.Triangle triangle, Vector2f vertex) {
  215.         line = makeLine(circle.center.x, circle.center.y, circle.center.x + circle.radius, circle.center.y, false, true);
  216.         textAndStep("radius = " + circle.radius);
  217.         line.hide();
  218.        
  219.         sc.highlight(1);
  220.         float distToCenter = vertex.dist(circle.center);
  221.         line = makeLine(vertex, circle.center, false, true);
  222.         textAndStep("distance to center = " + distToCenter);
  223.         line.hide();
  224.         sc.unhighlight(1);
  225.        
  226.        
  227.         sc.highlight(2);
  228.         Vector2f vertexToCenter = circle.center.sub(vertex);
  229.         vectors[0] = makeLine(vertex, circle.center, true, true);
  230.         textAndStep("vector from vertex to center = " + vertexToCenter);
  231.         sc.unhighlight(2);
  232.        
  233.         Vector2f vertexToNeighbor1;
  234.         Vector2f vertexToNeighbor2;
  235.        
  236.         if(vertex == triangle.A) {
  237.             sc.highlight(6);
  238.             sc.highlight(7);
  239.             sc.highlight(9);
  240.             vertexToNeighbor1 = triangle.B.sub(vertex); // AB
  241.             vertexToNeighbor2 = triangle.C.sub(vertex); // AC
  242.             neighbor1Name = "B";
  243.             neighbor2Name = "C";
  244.             vectors[1] = makeLine(vertex, triangle.B, true, true);
  245.             textAndStep("vector from " + vertexName + " to " + neighbor1Name + " = " + vertexToNeighbor1);
  246.             sc.unhighlight(7);
  247.            
  248.             sc.highlight(8);
  249.             vectors[2] = makeLine(vertex, triangle.C, true, true);
  250.             textAndStep("vector from " + vertexName + " to " + neighbor2Name + " = " + vertexToNeighbor2);
  251.             sc.unhighlight(6);
  252.             sc.unhighlight(8);
  253.             sc.unhighlight(9);
  254.         }
  255.         else if(vertex == triangle.B) {
  256.             sc.highlight(10);
  257.             sc.highlight(11);
  258.             sc.highlight(13);
  259.             vertexToNeighbor1 = triangle.A.sub(vertex); // BA
  260.             vertexToNeighbor2 = triangle.C.sub(vertex); // BC
  261.             neighbor1Name = "A";
  262.             neighbor2Name = "C";
  263.             vectors[1] = makeLine(vertex, triangle.A, true, true);
  264.             textAndStep("vector from " + vertexName + " to " + neighbor1Name + " = " + vertexToNeighbor1);
  265.             sc.unhighlight(11);
  266.            
  267.             sc.highlight(12);
  268.             vectors[2] = makeLine(vertex, triangle.C, true, true);
  269.             textAndStep("vector from " + vertexName + " to " + neighbor2Name + " = " + vertexToNeighbor2);
  270.             sc.unhighlight(10);
  271.             sc.unhighlight(12);
  272.             sc.unhighlight(13);
  273.         }
  274.         else if(vertex == triangle.C) {
  275.             sc.highlight(14);
  276.             sc.highlight(15);
  277.             sc.highlight(17);
  278.             vertexToNeighbor1 = triangle.A.sub(vertex); // CA
  279.             vertexToNeighbor2 = triangle.B.sub(vertex); // CB
  280.             neighbor1Name = "A";
  281.             neighbor2Name = "B";
  282.             vectors[1] = makeLine(vertex, triangle.A, true, true);
  283.             textAndStep("vector from " + vertexName + " to " + neighbor1Name + " = " + vertexToNeighbor1);
  284.             sc.unhighlight(15);
  285.            
  286.             sc.highlight(16);
  287.             vectors[2] = makeLine(vertex, triangle.B, true, true);
  288.             textAndStep("vector from " + vertexName + " to " + neighbor2Name + " = " + vertexToNeighbor2);
  289.             sc.unhighlight(14);
  290.             sc.unhighlight(16);
  291.             sc.unhighlight(17);
  292.         }
  293.         else {
  294.             throw new IllegalArgumentException("The provided vertex: " + vertex + " does not match with any of the triangle's vertices.");
  295.         }
  296.        
  297. //      textAndStep("vector from " + vertexName + " to " + neighbor1Name + " = " + vertexToNeighbor1);
  298. //      textAndStep("vector from " + vertexName + " to " + neighbor2Name + " = " + vertexToNeighbor2);
  299.  
  300.         // they are on opposite sides if the dot product is less than zero
  301.         vectors[0].changeColor("", Color.LIGHT_GRAY, null, null);
  302.        
  303.         sc.highlight(21);
  304.         sc.highlight(22);
  305.         boolean isOppositeNeighbor1 = vertexToCenter.dot(vertexToNeighbor1) < 0;
  306.         vectors[1].changeColor("", Color.ORANGE, null, null);
  307.         textAndStep(neighbor1Name + " is on opposite side = " + isOppositeNeighbor1);
  308.         vectors[1].changeColor("", VECTOR_DEFAULT_COLOR, null, null);
  309.         sc.unhighlight(21);
  310.         sc.unhighlight(22);
  311.        
  312.         sc.highlight(23);
  313.         sc.highlight(24);
  314.         boolean isOppositeNeighbor2 = vertexToCenter.dot(vertexToNeighbor2) < 0;
  315.         vectors[2].changeColor("", Color.ORANGE, null, null);
  316.         textAndStep(neighbor2Name + " is on opposite side = " + isOppositeNeighbor2);
  317.         sc.unhighlight(23);
  318.         sc.unhighlight(24);
  319.        
  320.         vectors[0].hide();
  321.         vectors[1].hide();
  322.         vectors[2].hide();
  323.        
  324.         sc.highlight(26);
  325.         boolean radius_less_than_dist = circle.radius < distToCenter;
  326.         textAndStep("radius smaller than distance = " + radius_less_than_dist);
  327.        
  328.         boolean result = radius_less_than_dist && isOppositeNeighbor1 && isOppositeNeighbor2;
  329.         line = makeLine(vertex, circle.center, false, true);
  330.         line.changeColor("", result ? Color.GREEN : Color.RED, null, null);
  331.         if(result) {
  332.             separatingAxis =  makeLine(vertex, circle.center, false, true);
  333.         }
  334.         sc.highlight(27);
  335.         textAndStep("vertex is separating axis = " + result);
  336.         line.hide();
  337.         sc.unhighlight(26);
  338.         sc.unhighlight(27);
  339.         if(separatingAxis != null) {
  340.             separatingAxis.hide(); 
  341.         }
  342.         return result;
  343.     }
  344.    
  345.    
  346.     /**
  347.      *
  348.      * @param circle
  349.      * @param triangle
  350.      * @param edge
  351.      * @param start
  352.      * @param end
  353.      * @param other
  354.      * @return
  355.      */
  356.     private boolean isEdgeSA(auxiliary.Circle circle, auxiliary.Triangle triangle, Vector2f edge, Vector2f start, Vector2f end, Vector2f other) {
  357.         line = makeLine(circle.center.x, circle.center.y, circle.center.x + circle.radius, circle.center.y, false, true);
  358.         textAndStep("radius = " + circle.radius);
  359.         line.hide();
  360.        
  361.         sc.highlight(1);
  362.         Vector2f normalizedEdge = edge.normalize();
  363.         vector = makeLine(start.x, start.y, start.x + normalizedEdge.x, start.y + normalizedEdge.y, true, true);
  364.         vector.changeColor("", VECTOR_DEFAULT_COLOR, null, null);
  365.         textAndStep("normalized edge = " + normalizedEdge);
  366.         vector.hide();
  367.         sc.unhighlight(1);
  368.        
  369.         Vector2f vecToCircle;
  370.         if(edge == triangle.edgeAB) {
  371.             sc.highlight(4);
  372.             sc.highlight(5);
  373.             sc.highlight(6);
  374.             vecToCircle = circle.center.sub(triangle.A);
  375.             vector = makeLine(triangle.A, circle.center, true, true);
  376.             textAndStep("vector to circle = " + vecToCircle);
  377.             vector.hide();
  378.             sc.unhighlight(4);
  379.             sc.unhighlight(5);
  380.             sc.unhighlight(6);
  381.         }
  382.         else if(edge == triangle.edgeAC) {
  383.             sc.highlight(7);
  384.             sc.highlight(8);
  385.             sc.highlight(9);
  386.             // TODO: why not C, or: when A, when C ?
  387.             vecToCircle = circle.center.sub(triangle.A);
  388.             vector = makeLine(triangle.A, circle.center, true, true);
  389.             textAndStep("vector to circle = " + vecToCircle);
  390.             vector.hide();
  391.             sc.unhighlight(7);
  392.             sc.unhighlight(8);
  393.             sc.unhighlight(9);
  394.         }
  395.         else if(edge == triangle.edgeBC) {
  396.             sc.highlight(10);
  397.             sc.highlight(11);
  398.             sc.highlight(12);
  399.             vecToCircle = circle.center.sub(triangle.B);
  400.             vector = makeLine(triangle.B, circle.center, true, true);
  401.             textAndStep("vector to circle = " + vecToCircle);
  402.             vector.hide();
  403.             sc.unhighlight(10);
  404.             sc.unhighlight(11);
  405.             sc.unhighlight(12);
  406.         }
  407.         else {
  408.             throw new IllegalArgumentException("The provided edge: " + edge + " does not match with any of the triangle's edges.");
  409.         }
  410.        
  411.         sc.highlight(13);
  412.         float dot = normalizedEdge.dot(vecToCircle);
  413.         line = makeLine(start.x, start.y, start.x + dot, start.y + dot, false, true);
  414.         // TODO: fix dot product (get direction right!)
  415.         textAndStep("dot product of normalizedEdge and vectorToCircle = " + dot);
  416.         line.hide();
  417.         sc.unhighlight(13);
  418.        
  419.         Vector2f closestPointToCircle;
  420.         int codeLine1 = 0;
  421.         int codeLine2 = 0;
  422.         if(dot <= 0) {
  423.             codeLine1 = 16;
  424.             sc.highlight(codeLine1);
  425.             closestPointToCircle = start;
  426.         }
  427.         else if(dot >= edge.length()) {
  428.             codeLine1 = 19;
  429.             sc.highlight(codeLine1);
  430.             closestPointToCircle = end;
  431.         }
  432.         else {
  433.             codeLine1 = 22;
  434.             codeLine2 = 23;
  435.             sc.highlight(codeLine1);
  436.             sc.highlight(codeLine2);
  437.             closestPointToCircle = normalizedEdge.mul(dot).add(start);
  438.         }
  439.        
  440.         Circle pointToHighlight;
  441.         boolean isFilled = true;
  442.        
  443.         line = makeLine(start, closestPointToCircle, false, true);
  444.         pointToHighlight = makeCircle(closestPointToCircle.x, closestPointToCircle.y, 0.1f, Color.PINK, isFilled);
  445.         textAndStep("closest point to circle = " + closestPointToCircle);
  446.         pointToHighlight.hide();
  447.         line.hide();
  448.         sc.unhighlight(codeLine1);
  449.         sc.unhighlight(codeLine2);
  450.        
  451.         // check if the other vertex (the one that is not part of the current edge) and the circle-center lie on opposite sides of the edge
  452.         sc.highlight(29);
  453.         sc.highlight(30);
  454.         Vector2f vecFromClosestPointToCircle        = circle.center.sub(closestPointToCircle);
  455.         vectors[0] = makeLine(closestPointToCircle, circle.center, true, true);
  456.         textAndStep("vector from closest point to circle = " + vecFromClosestPointToCircle);
  457.         sc.unhighlight(29);
  458.         sc.unhighlight(30);
  459.        
  460.         sc.highlight(31);
  461.         sc.highlight(32);
  462.         Vector2f vecFromClosestPointToOtherVertex   = other.sub(closestPointToCircle);
  463.         vectors[1] = makeLine(closestPointToCircle, other, true, true);
  464.         textAndStep("vector from closest point to other vertex = " + vecFromClosestPointToOtherVertex);
  465.         sc.unhighlight(31);
  466.         sc.unhighlight(32);
  467.        
  468.         sc.highlight(33);
  469.         boolean isOppositeOtherVertex               = vecFromClosestPointToCircle.dot(vecFromClosestPointToOtherVertex) < 0;
  470.         vectors[0].changeColor("", Color.BLUE, null, null);
  471.         vectors[1].changeColor("", Color.BLUE, null, null);
  472.         textAndStep("other vertex on opposite side of circle = " + isOppositeOtherVertex);
  473.         sc.unhighlight(33);
  474.        
  475.         vectors[0].hide();
  476.         vectors[1].hide();
  477.        
  478.         sc.highlight(35);
  479.         boolean radius_less_than_dist_to_closest_point = circle.radius < vecFromClosestPointToCircle.length();
  480.         textAndStep("radius less than distance to closest point = " + radius_less_than_dist_to_closest_point);
  481.        
  482.         boolean result = radius_less_than_dist_to_closest_point && isOppositeOtherVertex;
  483.         line = makeLine(closestPointToCircle, circle.center, false, true);
  484.         line.changeColor("", result ? Color.GREEN : Color.RED, null, null);
  485.         if(result) {
  486.             separatingAxis = makeLine(closestPointToCircle, circle.center, false, true);
  487.         }
  488.         textAndStep("is separating axis = " + result);
  489.         line.hide();
  490.         sc.unhighlight(35);
  491.         if(separatingAxis != null) {
  492.             separatingAxis.hide(); 
  493.         }
  494.         return result;
  495.     }
  496.    
  497.    
  498.     // ====================================================================================================================================
  499.     // ====================================================================================================================================
  500.    
  501.     private Circle makeCircle(float x, float y, float radius) {
  502.         return new Circle(new AnimalCircleGenerator(lang), transformCoords(x, y), transformRadius(radius), "circle", null, circleProps);
  503.     }
  504.    
  505.     private Circle makeCircle(float x, float y, float radius, Color color, boolean isFilled) {
  506.         CircleProperties props = new CircleProperties();
  507.         props.set(AnimationPropertiesKeys.FILL_PROPERTY, color);
  508.         props.set(AnimationPropertiesKeys.FILLED_PROPERTY, isFilled);
  509.         return new Circle(new AnimalCircleGenerator(lang), transformCoords(x, y), transformRadius(radius), "circle", null, props);
  510.     }
  511.    
  512.     private Triangle makeTriangle(Vector2f A, Vector2f B, Vector2f C) {
  513.         return makeTriangle(A.x, A.y, B.x, B.y, C.x, C.y);
  514.     }
  515.    
  516.     private Triangle makeTriangle(float Ax, float Ay, float Bx, float By, float Cx, float Cy) {
  517.         return new Triangle(new AnimalTriangleGenerator(lang),
  518.                 transformCoords(Ax, Ay),
  519.                 transformCoords(Bx, By),
  520.                 transformCoords(Cx, Cy),
  521.                 "triangle",
  522.                 null,
  523.                 triangleProps);
  524.     }
  525.    
  526.     private Coordinates transformCoords(float x, float y) {
  527.         float newX = 600 + 40 * x;
  528.         float newY = 300 - 40 * y;
  529.         return new Coordinates((int)newX, (int)newY);
  530.     }
  531.    
  532.     private int transformRadius(float radius) {
  533.         float newRadius = 40 * radius;
  534.         return (int)newRadius;
  535.     }
  536.    
  537.     private Rect makeRect(int upperLeftX, int upperLeftY, int lowerRightX, int lowerRightY) {
  538.         return new Rect(new AnimalRectGenerator(lang), new Coordinates(upperLeftX, upperLeftY), new Coordinates(lowerRightX, lowerRightY), "rect", null, rectProps);
  539.     }
  540.    
  541.     private Text makeText(String text, int x, int y) {
  542.         return new Text(new AnimalTextGenerator(lang), new Coordinates(x, y), text, "text", null, textProps);
  543.     }
  544.    
  545.     private void textAndStep(String text) {
  546.         textAndStep(text, this.x, this.y);
  547.     }
  548.    
  549.     private void textAndStep(String text, int x, int y) {
  550.         textList.add(makeText(text, x, y));
  551.         this.y += offsetY;
  552.         lang.nextStep();
  553.     }
  554.    
  555.     private void clearText() {
  556.         for(Text text : textList) {
  557.             text.setText("", null, null);
  558.         }
  559.        
  560.         textList = new ArrayList<>();
  561.     }
  562.    
  563.    
  564.     private Polyline makeLine(Vector2f from, Vector2f to, boolean isVector, boolean needsTransform) {
  565.         return makeLine(from.x, from.y, to.x, to.y, isVector, needsTransform);
  566.     }
  567.    
  568.     private Polyline makeLine(float startX, float startY, float endX, float endY, boolean isVector, boolean needsTransform) {
  569.         Node[] nodeArray;
  570.         if(needsTransform) {
  571.             nodeArray = new Node[] {
  572.                     transformCoords(startX, startY),
  573.                     transformCoords(endX, endY)
  574.             };
  575.         }
  576.         else {
  577.             nodeArray = new Node[] {
  578.                     new Coordinates((int)startX, (int)startY),
  579.                     new Coordinates((int)endX, (int)endY)
  580.             };
  581.         }
  582.        
  583.         return new Polyline(new AnimalPolylineGenerator(lang), nodeArray, "line", null, isVector ? vectorProps : lineProps);
  584.     }
  585.    
  586. //  private Polyline makeLine(Vector2f from, Vector2f to, boolean isVector, boolean needsTransform, Color color) {
  587. //      return makeLine(from.x, from.y, to.x, to.y, isVector, needsTransform, color);
  588. //  }
  589.    
  590. //  private Polyline makeLine(float startX, float startY, float endX, float endY, boolean isVector, boolean needsTransform, Color color) {
  591. //      Node[] nodeArray;
  592. //      if(needsTransform) {
  593. //          nodeArray = new Node[] {
  594. //                  transformCoords(startX, startY),
  595. //                  transformCoords(endX, endY)
  596. //          };
  597. //      }
  598. //      else {
  599. //          nodeArray = new Node[] {
  600. //                  new Coordinates((int)startX, (int)startY),
  601. //                  new Coordinates((int)endX, (int)endY)
  602. //          };
  603. //      }
  604. //     
  605. //      Polyline result = new Polyline(new AnimalPolylineGenerator(lang), nodeArray, "line", null, isVector ? vectorProps : lineProps);
  606. //      result.getProperties().set(AnimationPropertiesKeys.COLOR_PROPERTY, color);
  607. //     
  608. //      return result;
  609. //  }
  610.    
  611.     private void makeHeader() {
  612.         makeRect(430, 25, 790, 50);
  613.        
  614.         TextProperties titleProps = new TextProperties();
  615.         titleProps.set(AnimationPropertiesKeys.FONT_PROPERTY, new Font("Arial", Font.BOLD, 16));
  616.         new Text(new AnimalTextGenerator(lang), new Coordinates(450, 27), "Separating Axis Theorem (Circle-Triangle)", "title", null, titleProps);
  617.     }
  618.    
  619.     private void makeSideBox() {
  620.         makeRect(900, 150, 1300, 380);
  621.     }
  622.    
  623.     private void drawCoordSystem() {
  624.         int xAxis       = 300;
  625.         int xAxisStart  = 400;
  626.         int xAxisEnd    = 800;
  627.        
  628.         int yAxis       = 600;
  629.         int yAxisStart  = 500;
  630.         int yAxisEnd    = 100;
  631.        
  632.         makeLine(xAxisStart, xAxis, xAxisEnd, xAxis, false, false); // x-axis (600px)
  633.         makeLine(yAxis, yAxisStart, yAxis, yAxisEnd, false, false); // y-axis (400px)
  634.        
  635.         int offset = 40;    // 60px = 1cm
  636.        
  637.         // x-axis
  638.         for(int i=xAxisStart; i <= xAxisEnd; i+=offset) {
  639.             makeLine(i, xAxis-5, i, xAxis+5, false, false);
  640.         }
  641.        
  642.         // y-axis
  643.         for(int i=yAxisStart; i >= yAxisEnd; i-=offset) {
  644.             makeLine(yAxis-5, i, yAxis+5, i, false, false);
  645.         }
  646.     }
  647.    
  648.     // ====================================================================================================================================
  649.     // ====================================================================================================================================
  650.     // ====================================================================================================================================
  651.     // ====================================================================================================================================
  652.     // ====================================================================================================================================
  653.     // ====================================================================================================================================
  654.    
  655.     public static void main(String[] args) {
  656.         // careful: animalscript y-coord goes downwards (i.e. 110 is below 100)
  657.         SAT sat = new SAT();
  658.         sat.init();
  659.        
  660.         auxiliary.Circle C = new auxiliary.Circle(new Vector2f(-2, 1), 2);
  661.         // auxiliary.Triangle T = new auxiliary.Triangle(new Vector2f(1, 1), new Vector2f(3, 1), new Vector2f(2, 4));
  662.         auxiliary.Triangle T = new auxiliary.Triangle(new Vector2f(-1, -2), new Vector2f(3, 1), new Vector2f(2, 4));
  663.         sat.hasSA(C, T);
  664.        
  665.         System.out.println(sat.lang);
  666.     }
  667.    
  668.    
  669.     public void showSourceCodeVertexSA() {
  670.         // first set the visual properties for the source code
  671.         SourceCodeProperties scProps = new SourceCodeProperties();
  672.         scProps.set(AnimationPropertiesKeys.CONTEXTCOLOR_PROPERTY, Color.BLUE);
  673.         scProps.set(AnimationPropertiesKeys.FONT_PROPERTY, new Font("Monospaced", Font.PLAIN, 12));
  674.         scProps.set(AnimationPropertiesKeys.HIGHLIGHTCOLOR_PROPERTY, Color.RED);
  675.         scProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLACK);
  676.        
  677.         // now create the source code entity
  678.         sc = lang.newSourceCode(new Coordinates(10, 50), "sourceCode", null, scProps);
  679.        
  680.         // add code lines (the actual sorting algo)
  681.         // parameters: code itself, name (can be null), indention level, display options
  682.         sc.addCodeLine("boolean isVertexSA(Circle circle, Triangle triangle, Vector2f vertex) {", null, 0, null);
  683.         sc.addCodeLine("float distToCenter = vertex.dist(circle.center);", null, 1, null);
  684.         sc.addCodeLine("Vector2f vertexToCenter = circle.center.sub(vertex);", null, 1, null);
  685.         sc.addCodeLine("Vector2f vertexToNeighbor1;", null, 1, null);
  686.         sc.addCodeLine("Vector2f vertexToNeighbor2;", null, 1, null);
  687.         sc.addCodeLine("", null, 0, null);
  688.         sc.addCodeLine("if(vertex == triangle.A) {", null, 1, null);
  689.         sc.addCodeLine("vertexToNeighbor1 = triangle.B.sub(vertex); // AB", null, 2, null);
  690.         sc.addCodeLine("vertexToNeighbor2 = triangle.C.sub(vertex); // AC", null, 2, null);
  691.         sc.addCodeLine("}", null, 1, null);
  692.         sc.addCodeLine("else if(vertex == triangle.B) {", null, 1, null);
  693.         sc.addCodeLine("vertexToNeighbor1 = triangle.A.sub(vertex); // BA", null, 2, null);
  694.         sc.addCodeLine("vertexToNeighbor2 = triangle.C.sub(vertex); // BC", null, 2, null);
  695.         sc.addCodeLine("}", null, 1, null);
  696.         sc.addCodeLine("else if(vertex == triangle.C) {", null, 1, null);
  697.         sc.addCodeLine("vertexToNeighbor1 = triangle.A.sub(vertex); // CA", null, 2, null);
  698.         sc.addCodeLine("vertexToNeighbor2 = triangle.B.sub(vertex); // CB", null, 2, null);
  699.         sc.addCodeLine("}", null, 1, null);
  700.         sc.addCodeLine("", null, 0, null);
  701.         sc.addCodeLine("// they are on opposite sides", null, 1, null);
  702.         sc.addCodeLine("// if the dot product is less than zero", null, 1, null);
  703.         sc.addCodeLine("boolean isOppositeNeighbor1 = ", null, 1, null);
  704.         sc.addCodeLine("vertexToCenter.dot(vertexToNeighbor1) < 0;", null, 2, null);
  705.         sc.addCodeLine("boolean isOppositeNeighbor2 = ", null, 1, null);
  706.         sc.addCodeLine("vertexToCenter.dot(vertexToNeighbor2) < 0;", null, 2, null);
  707.         sc.addCodeLine("", null, 0, null);
  708.         sc.addCodeLine("return circle.radius < distToCenter", null, 1, null);
  709.         sc.addCodeLine("&& isOppositeNeighbor1 && isOppositeNeighbor2;", null, 2, null);
  710.     } // showSourceCodeVertexSA()
  711.    
  712.    
  713.     public void showSourceCodeEdgeSA() {
  714.         // first set the visual properties for the source code
  715.         SourceCodeProperties scProps = new SourceCodeProperties();
  716.         scProps.set(AnimationPropertiesKeys.CONTEXTCOLOR_PROPERTY, Color.BLUE);
  717.         scProps.set(AnimationPropertiesKeys.FONT_PROPERTY, new Font("Monospaced", Font.PLAIN, 12));
  718.         scProps.set(AnimationPropertiesKeys.HIGHLIGHTCOLOR_PROPERTY, Color.RED);
  719.         scProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLACK);
  720.        
  721.         // now create the source code entity
  722.         sc = lang.newSourceCode(new Coordinates(10, 50), "sourceCode", null, scProps);
  723.        
  724.         // add code lines (the actual sorting algo)
  725.         // parameters: code itself, name (can be null), indention level, display options
  726.         sc.addCodeLine("boolean isEdgeSA(Circle circle, Triangle triangle, Vector2f edge, Vector2f start, Vector2f end, Vector2f other) {", null, 0, null);
  727.         sc.addCodeLine("Vector2f normalizedEdge = edge.normalize();", null, 1, null);
  728.         sc.addCodeLine("Vector2f vecToCircle;", null, 1, null);
  729.         sc.addCodeLine("", null, 0, null);
  730.         sc.addCodeLine("if(edge == triangle.edgeAB) {", null, 1, null);
  731.         sc.addCodeLine("vecToCircle = circle.center.sub(triangle.A);", null, 2, null);
  732.         sc.addCodeLine("}", null, 1, null);
  733.         sc.addCodeLine("else if(edge == triangle.edgeAC) {", null, 1, null);
  734.         sc.addCodeLine("vecToCircle = circle.center.sub(triangle.A);", null, 2, null);
  735.         sc.addCodeLine("}", null, 1, null);
  736.         sc.addCodeLine("else if(edge == triangle.edgeBC) {", null, 1, null);
  737.         sc.addCodeLine("vecToCircle = circle.center.sub(triangle.B);", null, 2, null);
  738.         sc.addCodeLine("}", null, 1, null);
  739.         sc.addCodeLine("float dot = normalizedEdge.dot(vecToCircle);", null, 1, null);
  740.         sc.addCodeLine("Vector2f closestPointToCircle;", null, 1, null);
  741.         sc.addCodeLine("if(dot <= 0) {", null, 1, null);
  742.         sc.addCodeLine("closestPointToCircle = start;", null, 2, null);
  743.         sc.addCodeLine("}", null, 1, null);
  744.         sc.addCodeLine("else if(dot >= edge.length()) {", null, 1, null);
  745.         sc.addCodeLine("closestPointToCircle = end;", null, 2, null);
  746.         sc.addCodeLine("}", null, 1, null);
  747.         sc.addCodeLine("else {", null, 1, null);
  748.         sc.addCodeLine("closestPointToCircle = ", null, 2, null);
  749.         sc.addCodeLine("normalizedEdge.mul(dot).add(start);", null, 3, null);
  750.         sc.addCodeLine("}", null, 1, null);
  751.         sc.addCodeLine("", null, 0, null);
  752.         sc.addCodeLine("// check if the other vertex", null, 1, null);
  753.         sc.addCodeLine("// (the one that is not part of the current edge)", null, 1, null);
  754.         sc.addCodeLine("// and the circle-center lie on opposite sides of the edge", null, 1, null);
  755.         sc.addCodeLine("Vector2f vecFromClosestPointToCircle        = ", null, 1, null);
  756.         sc.addCodeLine("circle.center.sub(closestPointToCircle);", null, 2, null);
  757.         sc.addCodeLine("Vector2f vecFromClosestPointToOtherVertex   = ", null, 1, null);
  758.         sc.addCodeLine("other.sub(closestPointToCircle); ", null, 2, null);
  759.         sc.addCodeLine("boolean isOppositeOtherVertex               = vecFromClosestPointToCircle.dot(vecFromClosestPointToOtherVertex) < 0;", null, 1, null);
  760.         sc.addCodeLine("", null, 0, null);
  761.         sc.addCodeLine("return circle.radius < vecFromClosestPointToCircle.length() && isOppositeOtherVertex;", null, 1, null);
  762.     } // showSourceCodeEdgeSA()
  763. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement