No Description

AI_PROJ1.java~ 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. import javafx.scene.Scene;
  2. import java.util.*;
  3. import javafx.application.Application;
  4. import javafx.beans.property.*;
  5. import javafx.beans.value.*;
  6. import javafx.collections.*;
  7. import javafx.event.EventHandler;
  8. import javafx.event.ActionEvent;
  9. import javafx.scene.*;
  10. import javafx.scene.input.*;
  11. import javafx.scene.paint.Color;
  12. import javafx.scene.shape.*;
  13. import javafx.stage.Stage;
  14. import javafx.geometry.Point2D;
  15. import javafx.scene.control.*;
  16. import javafx.scene.control.Button;
  17. import javafx.scene.layout.*;
  18. import javafx.animation.*;
  19. import javafx.util.*;
  20. import javafx.scene.shape.Path;
  21. /** Drag the anchors around to change a polygon's points. */
  22. public class AI_PROJ1 extends Application {
  23. public static void main(String[] args) throws Exception { launch(args); }
  24. static Polygon vpoly1 = new Polygon();
  25. static Polygon vpoly2 = new Polygon();
  26. static Polygon vpoly3 = new Polygon();
  27. static Polygon poly1 = createFirstPolygon();
  28. static Polygon poly2 = createSecondPolygon();
  29. static Polygon poly3 = createThirdPolygon();
  30. static Polygon error1 = new Polygon();
  31. static Polygon error2 = new Polygon();
  32. static Polygon error3 = new Polygon();
  33. static double a = 30.0;
  34. static Polygon robit = drawRobit(a);
  35. static Polygon goal = new Polygon();
  36. static ArrayList<Polyline> visibles = new ArrayList<>();
  37. static Group root = new Group();
  38. static Pane possiblepaths = new Pane();
  39. static PriorityQueue<Node> openList;
  40. static HashSet<Node> closedList;
  41. HashMap<Node, Double> gVals = new HashMap<>();
  42. HashMap<Node, Double> fVals = new HashMap<>();
  43. static ArrayList<Node> allnodes = new ArrayList<>();
  44. static Polyline sline = new Polyline();
  45. Button calculatebutton = new Button("CALCULATE");
  46. Button plusbutton = new Button("+");
  47. Button minusbutton = new Button("-");
  48. Button resetbutton = new Button("RESET");
  49. HBox hb = new HBox();
  50. VBox vb = new VBox();
  51. Pane box = new Pane();
  52. static Path path = new Path();
  53. static PathTransition pt = new PathTransition();
  54. @Override public void start(final Stage stage) throws Exception {
  55. goal.getPoints().setAll(700d, 700d, 700d, 670d, 670d, 670d, 670d, 700d);
  56. goal.setFill(Color.RED);
  57. goal.setStroke(Color.BLACK);
  58. box.setPrefSize(700,700);
  59. plusButton handler1 = new plusButton();
  60. plusbutton.setOnAction(handler1);
  61. minusButton handler2 = new minusButton();
  62. minusbutton.setOnAction(handler2);
  63. resetButton handler3 = new resetButton();
  64. resetbutton.setOnAction(handler3);
  65. calculateButton handler4 = new calculateButton();
  66. calculatebutton.setOnAction(handler4);
  67. hb.setHgrow(plusbutton, Priority.ALWAYS);
  68. hb.setHgrow(minusbutton, Priority.ALWAYS);
  69. hb.setHgrow(calculatebutton, Priority.ALWAYS);
  70. hb.setHgrow(resetbutton, Priority.ALWAYS);
  71. plusbutton.setMaxWidth(Double.MAX_VALUE);
  72. minusbutton.setMaxWidth(Double.MAX_VALUE);
  73. resetbutton.setMaxWidth(Double.MAX_VALUE);
  74. calculatebutton.setMaxWidth(Double.MAX_VALUE);
  75. hb.getChildren().addAll(plusbutton,minusbutton,resetbutton,calculatebutton);
  76. vpoly1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a))));
  77. vpoly1.setStroke(Color.BLACK);
  78. vpoly1.setStrokeWidth(1);
  79. vpoly1.setFill(Color.TRANSPARENT);
  80. vpoly2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a))));
  81. vpoly2.setStroke(Color.BLACK);
  82. vpoly2.setStrokeWidth(1);
  83. vpoly2.setFill(Color.TRANSPARENT);
  84. vpoly3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a))));
  85. vpoly3.setStroke(Color.BLACK);
  86. vpoly3.setStrokeWidth(1);
  87. vpoly3.setFill(Color.TRANSPARENT);
  88. error1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a*0.99))));
  89. error2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a*0.99))));
  90. error3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a*0.99))));
  91. box.getChildren().addAll(vpoly1,vpoly2,vpoly3);
  92. box.getChildren().addAll(poly1,poly2,poly3);
  93. box.getChildren().addAll(robit,goal);
  94. box.getChildren().addAll(createControlAnchorsFor(poly1.getPoints()));
  95. box.getChildren().addAll(createControlAnchorsFor(poly2.getPoints()));
  96. box.getChildren().addAll(createControlAnchorsFor(poly3.getPoints()));
  97. box.getChildren().addAll(possiblepaths);
  98. vb.getChildren().addAll(box, hb);
  99. root.getChildren().addAll(vb);
  100. Scene scene1 = new Scene(root, 700, 725, Color.ALICEBLUE);
  101. scene1.setOnMouseDragged(new EventHandler<MouseEvent>() {
  102. @Override public void handle(MouseEvent mouseEvent) {
  103. vpoly1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a))));
  104. vpoly2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a))));
  105. vpoly3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a))));
  106. error1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a*0.99))));
  107. error2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a*0.99))));
  108. error3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a*0.99))));
  109. }
  110. });
  111. stage.setTitle("AI_PROJ1");
  112. stage.setScene(
  113. scene1
  114. );
  115. stage.show();
  116. }
  117. //plusbutton handler
  118. class plusButton implements EventHandler<ActionEvent> {
  119. @Override
  120. public void handle(ActionEvent e){
  121. if(a < 75.0){
  122. a += 1.0;
  123. vpoly1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a))));
  124. vpoly2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a))));
  125. vpoly3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a))));
  126. error1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a*0.99))));
  127. error2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a*0.99))));
  128. error3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a*0.99))));
  129. robit.getPoints().setAll(drawRobit(a).getPoints());
  130. }
  131. }
  132. }
  133. //minusbutton handler
  134. class minusButton implements EventHandler<ActionEvent> {
  135. @Override
  136. public void handle(ActionEvent e){
  137. if(a > 1.1){
  138. a -= 1.0;
  139. vpoly1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a))));
  140. vpoly2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a))));
  141. vpoly3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a))));
  142. error1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a*0.99))));
  143. error2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a*0.99))));
  144. error3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a*0.99))));
  145. robit.getPoints().setAll(drawRobit(a).getPoints());
  146. }
  147. }
  148. }
  149. //resetbutton handler
  150. class resetButton implements EventHandler<ActionEvent> {
  151. @Override
  152. public void handle(ActionEvent e){
  153. visibles.clear();
  154. calculatebutton.setDisable(false);
  155. Pane pnew = new Pane();
  156. box = new VBox();
  157. a = 30.0;
  158. robit = drawRobit(a);
  159. poly1 = createFirstPolygon();
  160. poly2 = createSecondPolygon();
  161. poly3 = createThirdPolygon();
  162. box.getChildren().clear();
  163. root.getChildren().clear();
  164. hb.getChildren().clear();
  165. sline.getPoints().clear();
  166. possiblepaths.getChildren().clear();
  167. hb.getChildren().addAll(plusbutton,minusbutton,resetbutton,calculatebutton);
  168. pnew.getChildren().addAll(poly1,poly2,poly3,robit,goal);
  169. vpoly1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a))));
  170. vpoly2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a))));
  171. vpoly3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a))));
  172. error1.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly1.getPoints(),a*0.99))));
  173. error2.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly2.getPoints(),a*0.99))));
  174. error3.getPoints().setAll(getConvexHull(pointSorter(virtualToRealPolygon(poly3.getPoints(),a*0.99))));
  175. pnew.getChildren().addAll(vpoly1,vpoly2);
  176. pnew.getChildren().addAll(vpoly3);
  177. pnew.getChildren().addAll(createControlAnchorsFor(poly1.getPoints()));
  178. pnew.getChildren().addAll(createControlAnchorsFor(poly2.getPoints()));
  179. pnew.getChildren().addAll(createControlAnchorsFor(poly3.getPoints()));
  180. box.getChildren().addAll(pnew,hb);
  181. root.getChildren().addAll(box);
  182. }
  183. }
  184. //calculatebutton handler
  185. class calculateButton implements EventHandler<ActionEvent> {
  186. @Override
  187. public void handle(ActionEvent e){
  188. possiblepaths.getChildren().clear();
  189. calculatebutton.setDisable(true);
  190. for(int i = 0; i < vpoly2.getPoints().size(); i+=2){
  191. setVis(vpoly2.getPoints().get(i),vpoly2.getPoints().get(i+1),vpoly1);
  192. int size2 = vpoly2.getPoints().size();
  193. Node n = new Node(vpoly2.getPoints().get(i),vpoly2.getPoints().get(i+1));
  194. Node next = new Node(vpoly2.getPoints().get((i+2)%size2),vpoly2.getPoints().get((i+3)%size2));
  195. Node prev = new Node(vpoly2.getPoints().get((i+size2 -2)%size2),vpoly2.getPoints().get((i-1 + size2)%size2));
  196. if(!n.getNeighbors().contains(next))
  197. n.addNeighbor(next);
  198. if(!n.getNeighbors().contains(prev))
  199. n.addNeighbor(prev);
  200. allnodes.add(n);
  201. }
  202. for(int j = 0; j < vpoly3.getPoints().size(); j+=2){
  203. setVis(vpoly3.getPoints().get(j),vpoly3.getPoints().get(j+1),vpoly2);
  204. int size3 = vpoly3.getPoints().size();
  205. Node n = new Node(vpoly3.getPoints().get(j),vpoly3.getPoints().get(j+1));
  206. Node next = new Node(vpoly3.getPoints().get((j+2)%size3),vpoly3.getPoints().get((j+3)%size3));
  207. Node prev = new Node(vpoly3.getPoints().get((j+size3-2)%size3),vpoly3.getPoints().get((j+size3-1)%size3));
  208. if(!n.getNeighbors().contains(next))
  209. n.addNeighbor(next);
  210. if(!n.getNeighbors().contains(prev))
  211. n.addNeighbor(prev);
  212. allnodes.add(n);
  213. }
  214. for(int k = 0; k < vpoly1.getPoints().size(); k+=2){
  215. setVis(vpoly1.getPoints().get(k),vpoly1.getPoints().get(k+1),vpoly3);
  216. int size1 = vpoly1.getPoints().size();
  217. Node n = new Node(vpoly1.getPoints().get(k),vpoly1.getPoints().get(k+1));
  218. Node next = new Node(vpoly1.getPoints().get((k+2)%size1),vpoly1.getPoints().get((k+3)%size1));
  219. Node prev = new Node(vpoly1.getPoints().get((k+size1-2)%size1),vpoly1.getPoints().get((k+size1-1)%size1));
  220. if(!n.getNeighbors().contains(next))
  221. n.addNeighbor(next);
  222. if(!n.getNeighbors().contains(prev))
  223. n.addNeighbor(prev);
  224. allnodes.add(n);
  225. }
  226. Node startnode = new Node(robit.getPoints().get(2),robit.getPoints().get(3));
  227. Node endnode = new Node(goal.getPoints().get(4),goal.getPoints().get(5));
  228. startnode.setNeighbors(whatsVisible(startnode));
  229. endnode.setNeighbors(whatsVisible(endnode));
  230. allnodes.add(startnode);
  231. allnodes.add(endnode);
  232. for(int w = 0; w < allnodes.size(); w++){
  233. allnodes.get(w).setNeighbors(whatsVisible(allnodes.get(w)));
  234. }
  235. for(Polyline path : visibles){
  236. path.setStroke(Color.LIGHTGRAY);
  237. root.getChildren().add(path);
  238. }
  239. for(Node tempnode : allnodes)
  240. tempnode.setData(tempnode.getX() + " " + tempnode.getY());
  241. traverse(endnode,startnode);
  242. sline.setStrokeWidth(4);
  243. root.getChildren().addAll(sline);
  244. playAnim();
  245. }
  246. }
  247. //put all the animation stuff in one method
  248. public void playAnim(){
  249. pt = new PathTransition();
  250. path = new Path();
  251. MoveTo mt = new MoveTo(robit.getPoints().get(2),robit.getPoints().get(3));
  252. path.getElements().add(mt);
  253. Polygon balance = new Polygon();
  254. balance.getPoints().addAll(
  255. robit.getPoints().get(2),robit.getPoints().get(3),
  256. robit.getPoints().get(2) - a,robit.getPoints().get(3),
  257. robit.getPoints().get(2) - 0.5*a, robit.getPoints().get(3) + 0.866*a
  258. );
  259. for(int i = 0; i < sline.getPoints().size(); i+=2){
  260. LineTo lt = new LineTo();
  261. lt.setX(sline.getPoints().get(i));
  262. lt.setY(sline.getPoints().get(i+1));
  263. path.getElements().add(lt);
  264. }
  265. pt.setDuration(Duration.seconds(8));
  266. pt.setPath(path);
  267. Group g = new Group();
  268. g.getChildren().addAll(balance,robit);
  269. balance.setFill(Color.TRANSPARENT);
  270. root.getChildren().addAll(g);
  271. pt.setNode(g);
  272. pt.setAutoReverse(true);
  273. robit.toFront();
  274. pt.play();
  275. }
  276. //literally the implementation of A*
  277. public void traverse(Node begin, Node end) {
  278. openList = new PriorityQueue<Node>(1000, new fCompare());
  279. closedList = new HashSet<>();
  280. openList.clear();
  281. HashMap<Node,Node> cameFrom = new HashMap<Node,Node>();
  282. gVals.put(begin,0.0);
  283. openList.add(begin);
  284. while(!openList.isEmpty()) {
  285. Node current = openList.element();
  286. if (current.equals(end)) {
  287. begin.setParent(null);
  288. System.out.println("Goal Reached!");
  289. printPath(current);
  290. return;
  291. }
  292. closedList.add(openList.poll());
  293. HashSet<Node> neighbors = current.getNeighbors();
  294. for (Node neighbor : neighbors) {
  295. double gScore = gVals.get(current);
  296. double fScore = gScore + h(neighbor, end);
  297. if(closedList.contains(neighbor)) {
  298. gVals.put(neighbor, gScore);
  299. fVals.put(neighbor, fScore);
  300. if(fScore >= fVals.get(neighbor)) {
  301. continue;
  302. }
  303. }
  304. if (!openList.contains(neighbor) || fScore < fVals.get(neighbor)){
  305. neighbor.setParent(current);
  306. gVals.put(neighbor, gScore);
  307. fVals.put(neighbor, fScore);
  308. if(!openList.contains(neighbor)) {
  309. openList.add(neighbor);
  310. }
  311. }
  312. }
  313. }
  314. System.out.println("FAIL");
  315. }
  316. public double h(Node node, Node goal) {
  317. double x = node.getX() - goal.getX();
  318. double y = node.getY()- goal.getY();
  319. return Math.sqrt(x*x +y*y);
  320. }
  321. public void printPath(Node node) {
  322. sline.getPoints().clear();
  323. sline.getPoints().add(node.getX());
  324. sline.getPoints().add(node.getY());
  325. while (node.getParent() != null) {
  326. node = node.getParent();
  327. sline.getPoints().add(node.getX());
  328. sline.getPoints().add(node.getY());
  329. System.out.println(node.getData());
  330. }
  331. }
  332. class fCompare implements Comparator<Node> {
  333. public int compare(Node o1, Node o2) {
  334. if(fVals.get(o1) < fVals.get(o2)) {
  335. return -1;
  336. }
  337. else if(fVals.get(o1) > fVals.get(o2)) {
  338. return 1;
  339. }
  340. else
  341. return 0;
  342. }
  343. }
  344. //For some vertex param, returns the hashset of whats visible
  345. private static HashSet<Node> whatsVisible(Node vertex){
  346. HashSet<Node> childs = new HashSet<>();
  347. ArrayList<Polygon> triangles = new ArrayList<>();
  348. for(int i = 0; i < vpoly1.getPoints().size(); i+=2){
  349. Polygon triangle = new Polygon();
  350. triangle.getPoints().setAll(
  351. vertex.getX(),vertex.getY(),
  352. vpoly1.getPoints().get(i),
  353. vpoly1.getPoints().get(i+1),
  354. vpoly1.getPoints().get((i+2)%vpoly1.getPoints().size()),
  355. vpoly1.getPoints().get((i+3)%vpoly1.getPoints().size())
  356. );
  357. triangles.add(triangle);
  358. }
  359. for(int i = 0; i < vpoly2.getPoints().size(); i+=2){
  360. Polygon triangle = new Polygon();
  361. triangle.getPoints().setAll(
  362. vertex.getX(),vertex.getY(),
  363. vpoly2.getPoints().get(i),
  364. vpoly2.getPoints().get(i+1),
  365. vpoly2.getPoints().get((i+2)%vpoly2.getPoints().size()),
  366. vpoly2.getPoints().get((i+3)%vpoly2.getPoints().size())
  367. );
  368. triangles.add(triangle);
  369. }
  370. for(int i = 0; i < vpoly3.getPoints().size(); i+=2){
  371. Polygon triangle = new Polygon();
  372. triangle.getPoints().setAll(
  373. vertex.getX(),vertex.getY(),
  374. vpoly3.getPoints().get(i),
  375. vpoly3.getPoints().get(i+1),
  376. vpoly3.getPoints().get((i+2)%vpoly3.getPoints().size()),
  377. vpoly3.getPoints().get((i+3)%vpoly3.getPoints().size())
  378. );
  379. triangles.add(triangle);
  380. }
  381. Polygon triangle = new Polygon();
  382. triangle.getPoints().setAll(
  383. vertex.getX(),vertex.getY(),
  384. 670d, 670d,
  385. 670.0000001,670.0000001
  386. );
  387. triangles.add(triangle);
  388. triangle = new Polygon();
  389. triangle.getPoints().setAll(
  390. vertex.getX(),vertex.getY(),
  391. robit.getPoints().get(2),
  392. robit.getPoints().get(3),
  393. robit.getPoints().get(2) +0.0000001,
  394. robit.getPoints().get(3) + 0.0000001
  395. );
  396. triangles.add(triangle);
  397. Shape totalError = Shape.union(error1,error2);
  398. totalError = Shape.union(totalError,error3);
  399. for(Polygon tri : triangles){
  400. Shape inter = Shape.intersect(totalError,tri);
  401. if(inter.getLayoutBounds().getHeight() < 0 || inter.getLayoutBounds().getWidth() < 0){
  402. Node one = new Node(tri.getPoints().get(2),tri.getPoints().get(3));
  403. Node two = new Node(tri.getPoints().get(4),tri.getPoints().get(5));
  404. int dex1 = allnodes.indexOf(one);
  405. int dex2 = allnodes.indexOf(two);
  406. for(Node node : allnodes){
  407. if(one.equals(node)){
  408. if(!childs.contains(node))
  409. childs.add(node);
  410. }
  411. if(two.equals(node)){
  412. if(!childs.contains(node))
  413. childs.add(node);
  414. }
  415. }
  416. }
  417. }
  418. return childs;
  419. }
  420. //adds cools lines to draw to visibles based on what doesnt intersect
  421. private static void setVis(double x, double y, Polygon poly){
  422. for(int i = 0; i < poly.getPoints().size(); i+=2){
  423. Polygon triangle = new Polygon();
  424. triangle.getPoints().setAll(
  425. x,y,
  426. poly.getPoints().get(i),
  427. poly.getPoints().get(i+1),
  428. poly.getPoints().get((i+2)%poly.getPoints().size()),
  429. poly.getPoints().get((i+3)%poly.getPoints().size())
  430. );
  431. Shape totalError = Shape.union(error1,error2);
  432. totalError = Shape.union(error3,totalError);
  433. Shape inter = Shape.intersect(totalError,triangle);
  434. if(inter.getLayoutBounds().getHeight() <= 0 || inter.getLayoutBounds().getWidth() <= 0){
  435. Polyline one = new Polyline();
  436. Polyline two = new Polyline();
  437. one.getPoints().setAll(x,y,poly.getPoints().get(i),poly.getPoints().get(i+1));
  438. two.getPoints().setAll(x,y,poly.getPoints().get((i+2)%poly.getPoints().size()),
  439. poly.getPoints().get((i+3)%poly.getPoints().size()));
  440. visibles.add(one);
  441. visibles.add(two);
  442. }
  443. }
  444. }
  445. //allows robit to change with the double value of a
  446. private static Polygon drawRobit(double a) {
  447. double corner = 1.0;
  448. Polygon robit = new Polygon();
  449. robit.getPoints().setAll(
  450. (double)(corner + 0.5*a), corner,
  451. corner,(double)(corner + .866*a),
  452. (double)(corner + a), (double)(corner + .866*a)
  453. );
  454. robit.setStroke(Color.RED);
  455. robit.setFill(Color.YELLOW);
  456. return robit;
  457. }
  458. //creates first polygon
  459. private static Polygon createFirstPolygon() {
  460. Polygon triangle = new Polygon();
  461. triangle.getPoints().setAll(
  462. 280d, 110d,
  463. 350d, 150d,
  464. 330d, 210d,
  465. 300d, 280d,
  466. 180d, 270d,
  467. 170d, 220d,
  468. 200d, 160d
  469. );
  470. triangle.setStroke(Color.BLUE);
  471. triangle.setStrokeWidth(4);
  472. triangle.setStrokeLineCap(StrokeLineCap.ROUND);
  473. triangle.setFill(Color.BLUE);
  474. return triangle;
  475. }
  476. //creates second polygon
  477. private static Polygon createSecondPolygon() {
  478. Polygon triangle = new Polygon();
  479. triangle.getPoints().setAll(
  480. 320d, 410d,
  481. 390d, 440d,
  482. 420d, 480d,
  483. 400d, 540d,
  484. 360d, 590d,
  485. 280d, 580d,
  486. 250d, 520d,
  487. 270d, 460d
  488. );
  489. triangle.setStroke(Color.BLUE);
  490. triangle.setStrokeWidth(4);
  491. triangle.setStrokeLineCap(StrokeLineCap.ROUND);
  492. triangle.setFill(Color.BLUE);
  493. return triangle;
  494. }
  495. //creates third polygon
  496. private static Polygon createThirdPolygon() {
  497. Polygon triangle = new Polygon();
  498. triangle.getPoints().setAll(
  499. 560d, 200d,
  500. 630d, 220d,
  501. 650d, 300d,
  502. 610d, 370d,
  503. 580d, 400d,
  504. 510d, 380d,
  505. 460d, 340d,
  506. 430d, 270d,
  507. 490d, 210d
  508. );
  509. triangle.setStroke(Color.BLUE);
  510. triangle.setStrokeWidth(4);
  511. triangle.setStrokeLineCap(StrokeLineCap.ROUND);
  512. triangle.setFill(Color.BLUE);
  513. return triangle;
  514. }
  515. //sorts points to comply with javafxs polygon renderer
  516. private ObservableList<Double> pointSorter(ObservableList<Double> s){
  517. double centerX = 0, centerY = 0;
  518. for(int i = 0; i < s.size(); i+=2){
  519. centerX += s.get(i);
  520. centerY += s.get(i+1);
  521. }
  522. centerX /= (s.size()/2);
  523. centerY /= (s.size()/2);
  524. ArrayList<Double> angles = new ArrayList<>();
  525. for (int j = 0; j < s.size(); j+=2){
  526. angles.add(Math.atan2(s.get(j+1) - centerY , s.get(j) - centerX));
  527. }
  528. for(int k = angles.size() - 1; k >= 0; k--){
  529. for(int w = 1; w < k; w++){
  530. if(angles.get(w-1) > angles.get(w)){
  531. double temp = angles.get(w-1);
  532. angles.set(w-1,angles.get(w));
  533. angles.set(w, temp);
  534. double tempx = s.get(2*(w-1));
  535. double tempy = s.get(2*(w-1) + 1);
  536. s.set(2*(w-1), s.get(2*w));
  537. s.set(2*(w-1)+1, s.get((2*w) + 1));
  538. s.set(2*w, tempx);
  539. s.set((2*w)+1, tempy);
  540. }
  541. }
  542. }
  543. return s;
  544. }
  545. //convex implementation modified slightly from liangs book
  546. private ObservableList<Double> getConvexHull(ObservableList<Double> s){
  547. Point2D[] myPoints = new Point2D[s.size()/2];
  548. for(int i = 0; i < myPoints.length; i++)
  549. myPoints[i] = new Point2D(s.get(2*i),s.get((2*i)+1));
  550. Point2D h0 = getRightMostLowestPoint(myPoints);
  551. ArrayList<Point2D> H = new ArrayList<Point2D>();
  552. H.add(h0);
  553. Point2D t0 = h0;
  554. while (true) {
  555. Point2D t1 = myPoints[0];
  556. for(int i = 1; i < myPoints.length; i++){
  557. double status = whichSide(t0.getX(), t0.getY(), t1.getX(), t1.getY(), myPoints[i].getX(), myPoints[i].getY());
  558. if(status > 0)
  559. t1 = myPoints[i];
  560. else if (status == 0){
  561. if(distance(myPoints[i].getX(), myPoints[i].getY(), t0.getX(), t0.getY()) > distance(t1.getX(), t1.getY(), t0.getX(), t0.getY()))
  562. t1 = myPoints[i];
  563. }
  564. }
  565. if(t1.getX() == h0.getX() && t1.getY() == h0.getY())
  566. break;
  567. else {
  568. H.add(t1);
  569. t0 = t1;
  570. }
  571. }
  572. ObservableList<Double> pnts = FXCollections.observableArrayList();
  573. for(int j = 0; j < H.size(); j++){
  574. pnts.add(H.get(j).getX());
  575. pnts.add(H.get(j).getY());
  576. }
  577. return pnts;
  578. }
  579. public double whichSide(double x0, double y0, double x1, double y1, double x2, double y2){
  580. return (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0);
  581. }
  582. public double distance(double x1, double y1, double x2, double y2) {
  583. return Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
  584. }
  585. static Point2D getRightMostLowestPoint(Point2D[] p){
  586. int rightMostIndex = 0;
  587. double rightMostX = p[0].getX();
  588. double rightMostY = p[0].getY();
  589. for(int i = 0; i < p.length; i++){
  590. if(rightMostY < p[i].getY()) {
  591. rightMostY = p[i].getY();
  592. rightMostX = p[i].getX();
  593. rightMostIndex = i;
  594. }
  595. else if (rightMostY == p[i].getY() && rightMostX < p[i].getX()){
  596. rightMostX = p[i].getX();
  597. rightMostIndex = i;
  598. }
  599. }
  600. return p[rightMostIndex];
  601. }
  602. //creates virtual polygon per a value and polygons observable list values. used with convex hull
  603. private ObservableList<Double> virtualToRealPolygon(final ObservableList<Double> rpoints, double a){
  604. ObservableList<Double> vpoints = FXCollections.observableArrayList();
  605. for(int i = 0; i < rpoints.size(); i+= 2){
  606. vpoints.add(rpoints.get(i));
  607. vpoints.add(rpoints.get(i+1));
  608. }
  609. for(int j = 0; j < rpoints.size(); j+= 2){
  610. vpoints.add(rpoints.get(j)-(a/2));
  611. vpoints.add(rpoints.get(j+1)+(.866*a));
  612. vpoints.add(rpoints.get(j) - a);
  613. vpoints.add(rpoints.get(j+1));
  614. }
  615. return vpoints;
  616. }
  617. //returns a list of draggable anchors for polygon specified at each vertice
  618. private ObservableList<Anchor> createControlAnchorsFor(final ObservableList<Double> points) {
  619. ObservableList<Anchor> anchors = FXCollections.observableArrayList();
  620. for (int i = 0; i < points.size(); i+=2) {
  621. final int idx = i;
  622. DoubleProperty xProperty = new SimpleDoubleProperty(points.get(i));
  623. DoubleProperty yProperty = new SimpleDoubleProperty(points.get(i + 1));
  624. xProperty.addListener(new ChangeListener<Number>() {
  625. @Override public void changed(ObservableValue<? extends Number> ov, Number oldX, Number x) {
  626. points.set(idx, (double) x);
  627. }
  628. });
  629. yProperty.addListener(new ChangeListener<Number>() {
  630. @Override public void changed(ObservableValue<? extends Number> ov, Number oldY, Number y) {
  631. points.set(idx + 1, (double) y);
  632. }
  633. });
  634. anchors.add(new Anchor(Color.BLUE, xProperty, yProperty));
  635. }
  636. return anchors;
  637. }
  638. }