Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.awt.*;
- import java.awt.event.ComponentEvent;
- import java.awt.event.ComponentListener;
- import java.awt.geom.*;
- import java.awt.image.BufferedImage;
- import java.util.ArrayList;
- import javax.swing.*;
- @SuppressWarnings("serial")
- public class RobotRouteWorld extends JPanel implements ComponentListener
- {
- private final int GRID_BORDER = 50; // Border between frame and grid.
- private Robot m_objRobot = null; // Robot object.
- private ArrayList<Landmark> m_arrLM = null; // Landmarks.
- public ArrayList<Landmark> m_arrSeenLM = null; // Seen landmarks (when using trig).
- private ArrayList<int[]> m_arrWP = null; // Route.
- private ArrayList<double[]> m_arrMapping = null; // Mapping of coordinates to corresponding GUI position.
- private BufferedImage m_objImgBuff = null; // Image buffer.
- private double m_dBoxSize = 0; // Grid box size.
- private boolean m_bCheckedLM = false; // Check intersected landmarks.
- private boolean m_bUseTrig = false; // Draw using trig?
- private boolean m_bDrawLM = false; // Draw landmarks?
- private boolean m_bDrawWP = false; // Draw route?
- /**
- * Constructor.
- */
- public RobotRouteWorld()
- {
- super();
- m_arrMapping = new ArrayList<double[]>();
- m_arrSeenLM = new ArrayList<Landmark>();
- addComponentListener(this);
- }
- /**
- * Box width.
- */
- public double getBoxWidth()
- {
- return m_dBoxSize;
- }
- /**
- * Sets the robot.
- * @param objRobot Robot object.
- */
- public void setRobot(Robot objRobot)
- {
- m_objRobot = objRobot;
- }
- /**
- * Gets seen landmarks when using trig.
- * @return ArrayList of Landmarks.
- */
- public ArrayList<Landmark> getSeenLandmarks()
- {
- return m_arrSeenLM;
- }
- /**
- * Draw landmarks.
- * @param arrLM Array of landmarks.
- */
- public void drawLandmarks(ArrayList<Landmark> arrLM)
- {
- // Set landmarks and a flag.
- m_arrLM = arrLM;
- m_bDrawLM = true;
- // Redraw.
- repaint();
- }
- /**
- * Draw the robot's route.
- * @param arrLM Array of waypoints.
- */
- public void drawRoute(ArrayList<int[]> arrWP, boolean bUseTrig)
- {
- // Set waypoints and a few other bits.
- m_arrWP = arrWP;
- m_bDrawWP = true;
- m_bUseTrig = bUseTrig;
- m_bCheckedLM = false;
- m_arrSeenLM.clear();
- // Redraw.
- repaint();
- }
- /**
- * Draw landmarks on the grid.
- */
- public void _drawLandmarks(Graphics2D g2)
- {
- // Owt to do?
- if (m_arrLM == null || m_arrLM.size() == 0)
- return;
- RoundRectangle2D.Double gRect;
- // Iterate over landmarks and draw them.
- for (Landmark objLM : m_arrLM)
- {
- double[] dPos = getPosFromCoords(objLM.getX(), objLM.getY());
- if (dPos != null)
- {
- gRect = new RoundRectangle2D.Double(dPos[0], dPos[1], m_dBoxSize, m_dBoxSize, 10, 10);
- g2.fill(gRect);
- }
- }
- }
- /**
- * Draw the route using trigonometry.
- * @param g Graphics2D object.
- */
- private void _drawRouteTrig(Graphics2D g2)
- {
- // Owt to do?
- if (m_objRobot == null || m_arrMapping == null || m_arrMapping.size() == 0 || m_arrWP == null || m_arrWP.size() == 0)
- return;
- // Line width.
- g2.setStroke(new BasicStroke(2));
- g2.setColor(new Color(255, 0, 0));
- // Starting coordinates.
- int iPrevX = 0;
- int iPrevY = 0;
- // Half grid box size.
- double dHalf = m_dBoxSize >> 1;
- double dQtr = dHalf >> 1;
- double dEighth = dQtr >> 1;
- // Iterate over route.
- for (int[] arrWP : m_arrWP)
- {
- // Coordinate.
- int iThisX = arrWP[0];
- int iThisY = arrWP[1];
- double[] arrGUIPrev = getPosFromCoords(iPrevX, iPrevY);
- double[] arrGUIThis = getPosFromCoords(iThisX, iThisY);
- // Draw a line from the previous coordinate to this one.
- if (arrGUIPrev != null && arrGUIThis != null)
- {
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- // Draw the start.
- if (iPrevX == 0 && iPrevX == 0)
- {
- g2.fill(new Ellipse2D.Double(
- arrGUIPrev[0] + dHalf - dEighth,
- arrGUIPrev[1] + dHalf - dEighth,
- dQtr,
- dQtr
- ));
- }
- // Current coordinates.
- g2.fill(new Ellipse2D.Double(
- arrGUIThis[0] + dHalf - dEighth,
- arrGUIThis[1] + dHalf - dEighth,
- dQtr,
- dQtr
- ));
- // No anti-aliasing for the line.
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
- g2.draw(new Line2D.Double(
- arrGUIPrev[0] + dHalf,
- arrGUIPrev[1] + dHalf,
- arrGUIThis[0] + dHalf,
- arrGUIThis[1] + dHalf
- ));
- }
- iPrevX = iThisX;
- iPrevY = iThisY;
- }
- }
- /**
- * Find which landmarks have been intersected by lines when using trigonometry.
- * @param g Graphics object.
- */
- private void updateSeenLandmarks()
- {
- // Already checked.
- if (m_bCheckedLM == true)
- return;
- // Make sure we have something to check.
- if (m_objRobot != null && m_arrLM != null && m_arrLM.size() > 0 && m_objImgBuff != null)
- {
- LM: for (Landmark objLM : m_arrLM)
- {
- int iX = objLM.getX();
- int iY = objLM.getY();
- // Get GUI pos.
- double dPos[] = getPosFromCoords(iX, iY);
- if (dPos != null)
- {
- // [*]-----[*]
- // * *
- // [*]-----[*]
- int iXR = (int)(dPos[0] + m_dBoxSize);
- int iYB = (int)(dPos[1] + m_dBoxSize);
- int iXL = (int)dPos[0];
- int iYT = (int)dPos[1];
- // Loop over pixels.
- for (int i = iYT; i < iYB; i++)
- {
- for (int j = iXL; j < iXR; j++)
- {
- int iClr = m_objImgBuff.getRGB(j, i);
- if (iClr == -65536) // aka 11111111 11111111 00000000 aka 255 255 0 aka red.
- {
- if (!m_arrSeenLM.contains(objLM))
- m_arrSeenLM.add(objLM);
- continue LM;
- }
- }
- }
- }
- }
- m_bCheckedLM = true;
- }
- }
- /**
- * Draw the route on the grid without using trigonometry.
- */
- public void _drawRoute(Graphics2D g2)
- {
- // Owt to do?
- if (m_objRobot == null || m_arrMapping == null || m_arrMapping.size() == 0 || m_arrWP == null || m_arrWP.size() == 0)
- return;
- // Starting coordinates.
- int iCurrX = 0;
- int iCurrY = 0;
- // Circle drawing variables.
- double[] arrGUI = null;
- double dBoxHalf = (m_dBoxSize >> 1) + 1;
- double dBoxQtr = (m_dBoxSize >> 2) + 1;
- // Circle and line.
- Ellipse2D.Double gElip;
- Arc2D.Double gArc;
- // Enable anti-aliasing.
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- // Indicate starting position.
- arrGUI = getPosFromCoords(0, 0);
- if (arrGUI != null)
- {
- gElip = new Ellipse2D.Double(
- arrGUI[0] + dBoxHalf - dBoxQtr,
- arrGUI[1] + dBoxHalf - dBoxQtr,
- dBoxHalf,
- dBoxHalf
- );
- g2.setColor(Color.BLUE);
- g2.fill(gElip);
- }
- // Iterate over route.
- for (int[] arrWP : m_arrWP)
- {
- // Coordinate.
- int iNextX = arrWP[0];
- int iNextY = arrWP[1];
- // Directional arrow.
- double dSeg = 0;
- Color cSeg = Color.RED;
- // Draw the supplied coordinate.
- arrGUI = getPosFromCoords(iNextX, iNextY);
- if (arrGUI != null)
- {
- gElip = new Ellipse2D.Double(
- arrGUI[0] + dBoxHalf - dBoxQtr,
- arrGUI[1] + dBoxHalf - dBoxQtr,
- dBoxHalf,
- dBoxHalf
- );
- g2.setColor(Color.BLUE);
- g2.fill(gElip);
- }
- // Get the intermediate path between waypoints.
- ArrayList<int[]> arrPath = m_objRobot.getPath(iCurrX, iCurrY, iNextX, iNextY);
- // Draw them.
- for (int[] arrCoords : arrPath)
- {
- // Draw an intermediate coordinate.
- arrGUI = getPosFromCoords(arrCoords[0], arrCoords[1]);
- if (arrGUI != null)
- {
- // Work out the direction and set the color/position.
- if (arrCoords[0] > iCurrX)
- {
- dSeg = 135;
- cSeg = Color.MAGENTA;
- }
- else if (arrCoords[0] < iCurrX)
- {
- dSeg = 315;
- cSeg = Color.GRAY;
- }
- if (arrCoords[1] > iCurrY)
- {
- dSeg = 225;
- cSeg = Color.GREEN;
- }
- else if (arrCoords[1] < iCurrY)
- {
- dSeg = 45;
- cSeg = Color.RED;
- }
- gElip = new Ellipse2D.Double(
- arrGUI[0] + dBoxHalf - dBoxQtr,
- arrGUI[1] + dBoxHalf - dBoxQtr,
- dBoxHalf,
- dBoxHalf
- );
- // Direction.
- g2.setColor(cSeg);
- gArc = new Arc2D.Double(
- arrGUI[0] + dBoxHalf - dBoxQtr,
- arrGUI[1] + dBoxHalf - dBoxQtr,
- dBoxHalf,
- dBoxHalf,
- dSeg,
- 90,
- Arc2D.PIE
- );
- g2.fill(gArc);
- }
- }
- // Update.
- iCurrX = iNextX;
- iCurrY = iNextY;
- }
- }
- /**
- * Get the relevant GUI position from x/y coordinates.
- * @return GUI position as a double array.
- */
- public double[] getPosFromCoords(int iX, int iY)
- {
- // Nothing to do.
- if (m_arrMapping == null || m_arrMapping.size() == 0)
- return null;
- // Look for the supplied coordinates.
- for (double[] arrPos : m_arrMapping)
- {
- int iMyX = (int)arrPos[0];
- int iMyY = (int)arrPos[1];
- // We've found the correct position.
- if (iX == iMyX && iY == iMyY)
- return new double[] { arrPos[2], arrPos[3] };
- }
- return null;
- }
- /**
- * Perform painting operations.
- */
- protected void paintComponent(Graphics g)
- {
- Graphics2D g2D = (Graphics2D)g;
- // Only if null.
- if (m_objImgBuff == null)
- m_objImgBuff = (BufferedImage)this.createImage(getWidth(), getHeight());
- Graphics2D g2 = m_objImgBuff.createGraphics();
- // Reset surface.
- g2.setColor(Color.WHITE);
- g2.fillRect(0, 0, m_objImgBuff.getWidth(), m_objImgBuff.getHeight());
- // Get our current dimensions. We need to draw a square.
- int iPanelWidth = getWidth();
- int iPanelHeight = getHeight();
- // The square can only be as wide/tall as the shortest dimension.
- int iSmallestDim = iPanelWidth > iPanelHeight ? iPanelHeight : iPanelWidth;
- double dOffsetX = 0;
- double dOffsetY = 0;
- // Centre the grid by finding out the offsets.
- if (iSmallestDim < iPanelWidth) dOffsetX = (iPanelWidth - iSmallestDim) / 2;
- if (iSmallestDim < iPanelHeight) dOffsetY = (iPanelHeight - iSmallestDim) / 2;
- // Add the border.
- dOffsetX += GRID_BORDER;
- dOffsetY += GRID_BORDER;
- // Deduct the border.
- iSmallestDim -= GRID_BORDER << 1;
- if (iSmallestDim < 0)
- return;
- // Get the box size.
- double dBoxSize = iSmallestDim / 20;
- double dTmpX = dOffsetX;
- double dTmpY = dOffsetY;
- // Set the grid color.
- g2.setColor(Color.BLACK);
- // Clear mapping.
- m_arrMapping.clear();
- m_dBoxSize = dBoxSize;
- // Used to draw each box. We could draw lines for better performance but rectangles make it easy to
- // associate waypoints with the associated GUI position.
- RoundRectangle2D.Double gRect;
- // Draw the grid.
- for (int i = 19; i >= 0; i--)
- {
- for (int j = 0; j <= 19; j++)
- {
- gRect = new RoundRectangle2D.Double(dTmpX, dTmpY, dBoxSize, dBoxSize, 10, 10);
- g2.draw(gRect);
- // Save.
- m_arrMapping.add(new double[] { j, i, dTmpX, dTmpY });
- // Draw x coordinates.
- if (i == 0)
- g2.drawString(j + "", (int)dTmpX, (int)(dTmpY + dBoxSize + GRID_BORDER / 2));
- // Update x position.
- dTmpX += dBoxSize;
- // New row?
- if (j == 19)
- {
- dTmpX = dOffsetX;
- dTmpY += dBoxSize;
- }
- }
- // Draw y coordinate numbers.
- g2.drawString(i + "", (int)(dTmpX - (GRID_BORDER / 2)), (int)dTmpY);
- }
- // Are we drawing landmarks?
- if (m_bDrawLM)
- _drawLandmarks(g2);
- // Are we drawing the route?
- if (m_bDrawWP)
- {
- if (m_bUseTrig)
- {
- _drawRouteTrig(g2);
- if (!m_bCheckedLM)
- updateSeenLandmarks();
- }
- else
- _drawRoute(g2);
- }
- g2D.drawImage(m_objImgBuff, null, 0, 0);
- }
- /**
- * Resets GUI.
- */
- public void resetGUI()
- {
- // Reset state.
- m_bDrawLM = false;
- m_bDrawWP = false;
- m_bUseTrig = false;
- m_bCheckedLM = false;
- // Clear data.
- if (m_arrLM != null)
- m_arrLM.clear();
- if (m_arrSeenLM != null)
- m_arrSeenLM.clear();
- if (m_arrWP != null)
- m_arrWP.clear();
- // Repaint.
- repaint();
- }
- @Override
- public void componentHidden(ComponentEvent arg0) {}
- @Override
- public void componentMoved(ComponentEvent arg0) {}
- @Override
- public void componentResized(ComponentEvent arg0)
- {
- if (m_objImgBuff != null)
- m_objImgBuff.flush();
- m_objImgBuff = (BufferedImage)this.createImage(getWidth(), getHeight());
- }
- @Override
- public void componentShown(ComponentEvent arg0) {}
- }
Add Comment
Please, Sign In to add comment