Advertisement
bekovski

algovi_sat_v2

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