Guest User

Untitled

a guest
Jul 20th, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.39 KB | None | 0 0
  1. import java.awt.*;
  2. import java.awt.event.ComponentEvent;
  3. import java.awt.event.ComponentListener;
  4. import java.awt.geom.*;
  5. import java.awt.image.BufferedImage;
  6. import java.util.ArrayList;
  7. import javax.swing.*;
  8.  
  9. @SuppressWarnings("serial")
  10. public class RobotRouteWorld extends JPanel implements ComponentListener
  11. {
  12. private final int GRID_BORDER = 50; // Border between frame and grid.
  13. private Robot m_objRobot = null; // Robot object.
  14. private ArrayList<Landmark> m_arrLM = null; // Landmarks.
  15. public ArrayList<Landmark> m_arrSeenLM = null; // Seen landmarks (when using trig).
  16. private ArrayList<int[]> m_arrWP = null; // Route.
  17. private ArrayList<double[]> m_arrMapping = null; // Mapping of coordinates to corresponding GUI position.
  18. private BufferedImage m_objImgBuff = null; // Image buffer.
  19. private double m_dBoxSize = 0; // Grid box size.
  20. private boolean m_bCheckedLM = false; // Check intersected landmarks.
  21. private boolean m_bUseTrig = false; // Draw using trig?
  22. private boolean m_bDrawLM = false; // Draw landmarks?
  23. private boolean m_bDrawWP = false; // Draw route?
  24.  
  25. /**
  26. * Constructor.
  27. */
  28. public RobotRouteWorld()
  29. {
  30. super();
  31. m_arrMapping = new ArrayList<double[]>();
  32. m_arrSeenLM = new ArrayList<Landmark>();
  33. addComponentListener(this);
  34. }
  35.  
  36. /**
  37. * Box width.
  38. */
  39. public double getBoxWidth()
  40. {
  41. return m_dBoxSize;
  42. }
  43.  
  44. /**
  45. * Sets the robot.
  46. * @param objRobot Robot object.
  47. */
  48. public void setRobot(Robot objRobot)
  49. {
  50. m_objRobot = objRobot;
  51. }
  52.  
  53. /**
  54. * Gets seen landmarks when using trig.
  55. * @return ArrayList of Landmarks.
  56. */
  57. public ArrayList<Landmark> getSeenLandmarks()
  58. {
  59. return m_arrSeenLM;
  60. }
  61.  
  62. /**
  63. * Draw landmarks.
  64. * @param arrLM Array of landmarks.
  65. */
  66. public void drawLandmarks(ArrayList<Landmark> arrLM)
  67. {
  68. // Set landmarks and a flag.
  69. m_arrLM = arrLM;
  70. m_bDrawLM = true;
  71.  
  72. // Redraw.
  73. repaint();
  74. }
  75.  
  76. /**
  77. * Draw the robot's route.
  78. * @param arrLM Array of waypoints.
  79. */
  80. public void drawRoute(ArrayList<int[]> arrWP, boolean bUseTrig)
  81. {
  82. // Set waypoints and a few other bits.
  83. m_arrWP = arrWP;
  84. m_bDrawWP = true;
  85. m_bUseTrig = bUseTrig;
  86. m_bCheckedLM = false;
  87. m_arrSeenLM.clear();
  88.  
  89. // Redraw.
  90. repaint();
  91. }
  92.  
  93. /**
  94. * Draw landmarks on the grid.
  95. */
  96. public void _drawLandmarks(Graphics2D g2)
  97. {
  98. // Owt to do?
  99. if (m_arrLM == null || m_arrLM.size() == 0)
  100. return;
  101.  
  102. RoundRectangle2D.Double gRect;
  103.  
  104. // Iterate over landmarks and draw them.
  105. for (Landmark objLM : m_arrLM)
  106. {
  107. double[] dPos = getPosFromCoords(objLM.getX(), objLM.getY());
  108. if (dPos != null)
  109. {
  110. gRect = new RoundRectangle2D.Double(dPos[0], dPos[1], m_dBoxSize, m_dBoxSize, 10, 10);
  111. g2.fill(gRect);
  112. }
  113. }
  114. }
  115.  
  116. /**
  117. * Draw the route using trigonometry.
  118. * @param g Graphics2D object.
  119. */
  120. private void _drawRouteTrig(Graphics2D g2)
  121. {
  122. // Owt to do?
  123. if (m_objRobot == null || m_arrMapping == null || m_arrMapping.size() == 0 || m_arrWP == null || m_arrWP.size() == 0)
  124. return;
  125.  
  126. // Line width.
  127. g2.setStroke(new BasicStroke(2));
  128. g2.setColor(new Color(255, 0, 0));
  129.  
  130. // Starting coordinates.
  131. int iPrevX = 0;
  132. int iPrevY = 0;
  133.  
  134. // Half grid box size.
  135. double dHalf = m_dBoxSize >> 1;
  136. double dQtr = dHalf >> 1;
  137. double dEighth = dQtr >> 1;
  138.  
  139. // Iterate over route.
  140. for (int[] arrWP : m_arrWP)
  141. {
  142. // Coordinate.
  143. int iThisX = arrWP[0];
  144. int iThisY = arrWP[1];
  145.  
  146. double[] arrGUIPrev = getPosFromCoords(iPrevX, iPrevY);
  147. double[] arrGUIThis = getPosFromCoords(iThisX, iThisY);
  148.  
  149. // Draw a line from the previous coordinate to this one.
  150. if (arrGUIPrev != null && arrGUIThis != null)
  151. {
  152. g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  153.  
  154. // Draw the start.
  155. if (iPrevX == 0 && iPrevX == 0)
  156. {
  157. g2.fill(new Ellipse2D.Double(
  158. arrGUIPrev[0] + dHalf - dEighth,
  159. arrGUIPrev[1] + dHalf - dEighth,
  160. dQtr,
  161. dQtr
  162. ));
  163. }
  164.  
  165. // Current coordinates.
  166. g2.fill(new Ellipse2D.Double(
  167. arrGUIThis[0] + dHalf - dEighth,
  168. arrGUIThis[1] + dHalf - dEighth,
  169. dQtr,
  170. dQtr
  171. ));
  172.  
  173. // No anti-aliasing for the line.
  174. g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
  175. g2.draw(new Line2D.Double(
  176. arrGUIPrev[0] + dHalf,
  177. arrGUIPrev[1] + dHalf,
  178. arrGUIThis[0] + dHalf,
  179. arrGUIThis[1] + dHalf
  180. ));
  181. }
  182.  
  183. iPrevX = iThisX;
  184. iPrevY = iThisY;
  185. }
  186. }
  187.  
  188. /**
  189. * Find which landmarks have been intersected by lines when using trigonometry.
  190. * @param g Graphics object.
  191. */
  192. private void updateSeenLandmarks()
  193. {
  194. // Already checked.
  195. if (m_bCheckedLM == true)
  196. return;
  197.  
  198. // Make sure we have something to check.
  199. if (m_objRobot != null && m_arrLM != null && m_arrLM.size() > 0 && m_objImgBuff != null)
  200. {
  201. LM: for (Landmark objLM : m_arrLM)
  202. {
  203. int iX = objLM.getX();
  204. int iY = objLM.getY();
  205.  
  206. // Get GUI pos.
  207. double dPos[] = getPosFromCoords(iX, iY);
  208. if (dPos != null)
  209. {
  210. // [*]-----[*]
  211. // * *
  212. // [*]-----[*]
  213. int iXR = (int)(dPos[0] + m_dBoxSize);
  214. int iYB = (int)(dPos[1] + m_dBoxSize);
  215. int iXL = (int)dPos[0];
  216. int iYT = (int)dPos[1];
  217.  
  218. // Loop over pixels.
  219. for (int i = iYT; i < iYB; i++)
  220. {
  221. for (int j = iXL; j < iXR; j++)
  222. {
  223. int iClr = m_objImgBuff.getRGB(j, i);
  224. if (iClr == -65536) // aka 11111111 11111111 00000000 aka 255 255 0 aka red.
  225. {
  226. if (!m_arrSeenLM.contains(objLM))
  227. m_arrSeenLM.add(objLM);
  228. continue LM;
  229. }
  230. }
  231. }
  232. }
  233. }
  234. m_bCheckedLM = true;
  235. }
  236. }
  237.  
  238. /**
  239. * Draw the route on the grid without using trigonometry.
  240. */
  241. public void _drawRoute(Graphics2D g2)
  242. {
  243. // Owt to do?
  244. if (m_objRobot == null || m_arrMapping == null || m_arrMapping.size() == 0 || m_arrWP == null || m_arrWP.size() == 0)
  245. return;
  246.  
  247. // Starting coordinates.
  248. int iCurrX = 0;
  249. int iCurrY = 0;
  250.  
  251. // Circle drawing variables.
  252. double[] arrGUI = null;
  253. double dBoxHalf = (m_dBoxSize >> 1) + 1;
  254. double dBoxQtr = (m_dBoxSize >> 2) + 1;
  255.  
  256. // Circle and line.
  257. Ellipse2D.Double gElip;
  258. Arc2D.Double gArc;
  259.  
  260. // Enable anti-aliasing.
  261. g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  262.  
  263. // Indicate starting position.
  264. arrGUI = getPosFromCoords(0, 0);
  265. if (arrGUI != null)
  266. {
  267. gElip = new Ellipse2D.Double(
  268. arrGUI[0] + dBoxHalf - dBoxQtr,
  269. arrGUI[1] + dBoxHalf - dBoxQtr,
  270. dBoxHalf,
  271. dBoxHalf
  272. );
  273. g2.setColor(Color.BLUE);
  274. g2.fill(gElip);
  275. }
  276.  
  277. // Iterate over route.
  278. for (int[] arrWP : m_arrWP)
  279. {
  280. // Coordinate.
  281. int iNextX = arrWP[0];
  282. int iNextY = arrWP[1];
  283.  
  284. // Directional arrow.
  285. double dSeg = 0;
  286. Color cSeg = Color.RED;
  287.  
  288. // Draw the supplied coordinate.
  289. arrGUI = getPosFromCoords(iNextX, iNextY);
  290. if (arrGUI != null)
  291. {
  292. gElip = new Ellipse2D.Double(
  293. arrGUI[0] + dBoxHalf - dBoxQtr,
  294. arrGUI[1] + dBoxHalf - dBoxQtr,
  295. dBoxHalf,
  296. dBoxHalf
  297. );
  298. g2.setColor(Color.BLUE);
  299. g2.fill(gElip);
  300. }
  301.  
  302. // Get the intermediate path between waypoints.
  303. ArrayList<int[]> arrPath = m_objRobot.getPath(iCurrX, iCurrY, iNextX, iNextY);
  304.  
  305. // Draw them.
  306. for (int[] arrCoords : arrPath)
  307. {
  308. // Draw an intermediate coordinate.
  309. arrGUI = getPosFromCoords(arrCoords[0], arrCoords[1]);
  310. if (arrGUI != null)
  311. {
  312. // Work out the direction and set the color/position.
  313. if (arrCoords[0] > iCurrX)
  314. {
  315. dSeg = 135;
  316. cSeg = Color.MAGENTA;
  317. }
  318. else if (arrCoords[0] < iCurrX)
  319. {
  320. dSeg = 315;
  321. cSeg = Color.GRAY;
  322. }
  323. if (arrCoords[1] > iCurrY)
  324. {
  325. dSeg = 225;
  326. cSeg = Color.GREEN;
  327. }
  328. else if (arrCoords[1] < iCurrY)
  329. {
  330. dSeg = 45;
  331. cSeg = Color.RED;
  332. }
  333.  
  334. gElip = new Ellipse2D.Double(
  335. arrGUI[0] + dBoxHalf - dBoxQtr,
  336. arrGUI[1] + dBoxHalf - dBoxQtr,
  337. dBoxHalf,
  338. dBoxHalf
  339. );
  340.  
  341. // Direction.
  342. g2.setColor(cSeg);
  343. gArc = new Arc2D.Double(
  344. arrGUI[0] + dBoxHalf - dBoxQtr,
  345. arrGUI[1] + dBoxHalf - dBoxQtr,
  346. dBoxHalf,
  347. dBoxHalf,
  348. dSeg,
  349. 90,
  350. Arc2D.PIE
  351. );
  352. g2.fill(gArc);
  353. }
  354. }
  355.  
  356. // Update.
  357. iCurrX = iNextX;
  358. iCurrY = iNextY;
  359. }
  360. }
  361.  
  362. /**
  363. * Get the relevant GUI position from x/y coordinates.
  364. * @return GUI position as a double array.
  365. */
  366. public double[] getPosFromCoords(int iX, int iY)
  367. {
  368. // Nothing to do.
  369. if (m_arrMapping == null || m_arrMapping.size() == 0)
  370. return null;
  371.  
  372. // Look for the supplied coordinates.
  373. for (double[] arrPos : m_arrMapping)
  374. {
  375. int iMyX = (int)arrPos[0];
  376. int iMyY = (int)arrPos[1];
  377.  
  378. // We've found the correct position.
  379. if (iX == iMyX && iY == iMyY)
  380. return new double[] { arrPos[2], arrPos[3] };
  381. }
  382. return null;
  383. }
  384.  
  385. /**
  386. * Perform painting operations.
  387. */
  388. protected void paintComponent(Graphics g)
  389. {
  390. Graphics2D g2D = (Graphics2D)g;
  391.  
  392. // Only if null.
  393. if (m_objImgBuff == null)
  394. m_objImgBuff = (BufferedImage)this.createImage(getWidth(), getHeight());
  395.  
  396. Graphics2D g2 = m_objImgBuff.createGraphics();
  397.  
  398. // Reset surface.
  399. g2.setColor(Color.WHITE);
  400. g2.fillRect(0, 0, m_objImgBuff.getWidth(), m_objImgBuff.getHeight());
  401.  
  402. // Get our current dimensions. We need to draw a square.
  403. int iPanelWidth = getWidth();
  404. int iPanelHeight = getHeight();
  405.  
  406. // The square can only be as wide/tall as the shortest dimension.
  407. int iSmallestDim = iPanelWidth > iPanelHeight ? iPanelHeight : iPanelWidth;
  408. double dOffsetX = 0;
  409. double dOffsetY = 0;
  410.  
  411. // Centre the grid by finding out the offsets.
  412. if (iSmallestDim < iPanelWidth) dOffsetX = (iPanelWidth - iSmallestDim) / 2;
  413. if (iSmallestDim < iPanelHeight) dOffsetY = (iPanelHeight - iSmallestDim) / 2;
  414.  
  415. // Add the border.
  416. dOffsetX += GRID_BORDER;
  417. dOffsetY += GRID_BORDER;
  418.  
  419. // Deduct the border.
  420. iSmallestDim -= GRID_BORDER << 1;
  421. if (iSmallestDim < 0)
  422. return;
  423.  
  424. // Get the box size.
  425. double dBoxSize = iSmallestDim / 20;
  426. double dTmpX = dOffsetX;
  427. double dTmpY = dOffsetY;
  428.  
  429. // Set the grid color.
  430. g2.setColor(Color.BLACK);
  431.  
  432. // Clear mapping.
  433. m_arrMapping.clear();
  434. m_dBoxSize = dBoxSize;
  435.  
  436. // Used to draw each box. We could draw lines for better performance but rectangles make it easy to
  437. // associate waypoints with the associated GUI position.
  438. RoundRectangle2D.Double gRect;
  439.  
  440. // Draw the grid.
  441. for (int i = 19; i >= 0; i--)
  442. {
  443. for (int j = 0; j <= 19; j++)
  444. {
  445. gRect = new RoundRectangle2D.Double(dTmpX, dTmpY, dBoxSize, dBoxSize, 10, 10);
  446. g2.draw(gRect);
  447.  
  448. // Save.
  449. m_arrMapping.add(new double[] { j, i, dTmpX, dTmpY });
  450.  
  451. // Draw x coordinates.
  452. if (i == 0)
  453. g2.drawString(j + "", (int)dTmpX, (int)(dTmpY + dBoxSize + GRID_BORDER / 2));
  454.  
  455. // Update x position.
  456. dTmpX += dBoxSize;
  457.  
  458. // New row?
  459. if (j == 19)
  460. {
  461. dTmpX = dOffsetX;
  462. dTmpY += dBoxSize;
  463. }
  464. }
  465.  
  466. // Draw y coordinate numbers.
  467. g2.drawString(i + "", (int)(dTmpX - (GRID_BORDER / 2)), (int)dTmpY);
  468. }
  469.  
  470. // Are we drawing landmarks?
  471. if (m_bDrawLM)
  472. _drawLandmarks(g2);
  473.  
  474. // Are we drawing the route?
  475. if (m_bDrawWP)
  476. {
  477. if (m_bUseTrig)
  478. {
  479. _drawRouteTrig(g2);
  480. if (!m_bCheckedLM)
  481. updateSeenLandmarks();
  482. }
  483. else
  484. _drawRoute(g2);
  485. }
  486. g2D.drawImage(m_objImgBuff, null, 0, 0);
  487. }
  488.  
  489. /**
  490. * Resets GUI.
  491. */
  492. public void resetGUI()
  493. {
  494. // Reset state.
  495. m_bDrawLM = false;
  496. m_bDrawWP = false;
  497. m_bUseTrig = false;
  498. m_bCheckedLM = false;
  499.  
  500. // Clear data.
  501. if (m_arrLM != null)
  502. m_arrLM.clear();
  503. if (m_arrSeenLM != null)
  504. m_arrSeenLM.clear();
  505. if (m_arrWP != null)
  506. m_arrWP.clear();
  507.  
  508. // Repaint.
  509. repaint();
  510. }
  511.  
  512. @Override
  513. public void componentHidden(ComponentEvent arg0) {}
  514.  
  515. @Override
  516. public void componentMoved(ComponentEvent arg0) {}
  517.  
  518. @Override
  519. public void componentResized(ComponentEvent arg0)
  520. {
  521. if (m_objImgBuff != null)
  522. m_objImgBuff.flush();
  523. m_objImgBuff = (BufferedImage)this.createImage(getWidth(), getHeight());
  524. }
  525.  
  526. @Override
  527. public void componentShown(ComponentEvent arg0) {}
  528.  
  529. }
Add Comment
Please, Sign In to add comment