Results 1 to 10 of 10
  1. #1
    Vinvar is offline Member
    Join Date
    Nov 2012
    Posts
    18
    Rep Power
    0

    Default Triangle coordinate calculating

    Hi All,
    I have a (mathematical) question. I have a Boid with two vectors. One vector is representing the position (x,y) and the other vector representing the direction (i,j). I want to visualize the Boid with a triangle centered around the position and facing the direction.
    Traingle coordinates calculating-vectorknown.png
    The black point is the position vector, the red arrow represents the direction vector. The purple and orange dots are the three points needed to render the (blue) triangle.

    As the direction vector changes the triangle should ‘rotate’. For instance:
    Traingle coordinates calculating-vectors.png

    So, given a position and a direction, the triangle points are:
    Traingle coordinates calculating-vectorunknown1.png

    My question is how I can calculate these three points. I came up with one possibility to calculate the front point.
    The front triangle has a length of 3 from the position. Also, it is in the same direction as the direction vector. So, I can normalize the direction vector and scale it by 3 to get the point in front of the position vector.
    Traingle coordinates calculating-vectorlength.png
    Do you know smarter (CPU wise) ways to calculate this point?

    For the two rear points, I have two theories. However, I do not know the math or which of the two is faster (CPU wise). Could you help me, please?

    Method 1: calculate based on the direction vector.
    For the rear points of the triangle, we know the angle of the triangle (with these ratios it is 45 degrees) and if we use the direction vector, we can calculate two new vectors.
    Traingle coordinates calculating-vectorsecundairy-directionvectors.png

    Also, we can calculate the length of the side, which is = sqrt(40) ≈ 6,3246.
    Traingle coordinates calculating-vectorpythagorasfront.png

    So, we can use the same method: normalize the two secondary vectors and scale them by sqrt(40).

    Method 2 : use the radiant.
    If you map the four ‘standard’ poses on top of each other, two circles are shown.
    Traingle coordinates calculating-vectorradiant.png

    Based on the direction vector the front point is somewhere on the purple circle. The two rear points are somewhere on the orange circle. R1 = 3, as we saw earlier. R2 ≈ 2,8284.
    Traingle coordinates calculating-vectorpythagorasrear.png

    So, if we calculate two vectors from the position to the rear, using the angle between the direction vector and the new vector. This should be 135 degrees, if we use the ratio of R1:R2 = 3:sqrt(8).
    Traingle coordinates calculating-vectortertair.png

    Can someone verify my methods. Also, are there better ways (in terms of less CPU usage) to calculate the three triangle points?

    Thanks in advance,
    Vinvar
    Last edited by Vinvar; 08-12-2017 at 12:07 PM.

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    19,942
    Rep Power
    30

    Default Re: Traingle coordinates calculating

    You'll have to wait until our mathematician comes along.
    I'm only a java programmer and don't see any java programming question here.
    If you do have questions about your code, post the code wrapped in code tags and ask your questions.
    If you don't understand my response, don't ignore it, ask a question.

  3. #3
    Vinvar is offline Member
    Join Date
    Nov 2012
    Posts
    18
    Rep Power
    0

    Default Re: Traingle coordinates calculating

    Hi Norm, thanks for your reply.

    I created some code. Code is tested and works (meaning: it is compilable and runnable).

    First we have a Boid class and a Triangle class. The Triangle class holds the points needed to visualise the Boid.
    Java Code:
    /**
     * Class to store data about a triangle.
     * 
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 ({@code build 1}).
     */
    public class Triangle {
    	// Number of points a triangle has.
    	public static final int trianglePoints = 3;
    
    	// Array of points, representing the Triangle.
    	// The points are relative to the Boid's position.
    	public float[] xPoints;
    	public float[] yPoints;
    
    	public Triangle() {
    		xPoints = new float[trianglePoints];
    		yPoints = new float[trianglePoints];
    	}
    
    	// ..Getters & Setters...
    }
    Java Code:
    import java.awt.Color;
    import java.awt.Graphics2D;
    
    /**
     * Class to store data about a Boid.
     * 
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 {@code build 1}
     */
    public class Boid {
    
    	public Vector2f position, velocity;
    
    	public Triangle visualisationTriangle;
    
    	// Size of the helper points to render the position and trianglePoints.
    	public static final int pointSize = 20;
    
    	public Boid(Vector2f pos, Vector2f vel) {
    		position = pos;
    		velocity = vel;
    
    		visualisationTriangle = new Triangle();
    	}
    
    	// Every time a tick has been done, this method is called
    	public void setTriangle() {
    		// Front point of triangle
    		Vector2f normalisedVelocity = new Vector2f(velocity.x, velocity.y);
    		normalisedVelocity.normalise();
    
    		Vector2f front = normalisedVelocity.scale(3 * TriangleCoordinate.gridSize);
    		visualisationTriangle.xPoints[0] = front.x;
    		visualisationTriangle.yPoints[0] = front.y;
    
    		// TODO
    		// Point rearLeft = ??;
    
    		// TODO
    		// Point rearRight = ??;
    	}
    
    	// ... draw methods ...
    
    	/* Method to draw the parameters (position & velocity) of the Boid. */
    	public void drawBoid(Graphics2D graphics2D) {
    		// draw position of Boid
    		graphics2D.setColor(Color.BLACK);
    		graphics2D.fillOval((int) position.x - (pointSize / 2), (int) position.y - (pointSize / 2), pointSize,
    				pointSize);
    
    		// draw velocity of Boid
    		graphics2D.setColor(Color.RED);
    		graphics2D.drawLine((int) position.x, (int) position.y, (int) (position.x + (velocity.x * 100)),
    				(int) (position.y + (velocity.y * 100)));
    	}
    
    	/*
    	 * Method to draw the parameters (front, rearLeft and rearRight) of the
    	 * triangleVisualisation.
    	 */
    	public void drawTrianglePoints(Graphics2D graphics2D) {
    		// Draw front point
    		graphics2D.setColor(new Color(139, 0, 139)); // Dark purple
    		graphics2D.fillOval((int) (position.x + visualisationTriangle.xPoints[0] - (pointSize / 2)),
    				(int) (position.y + visualisationTriangle.yPoints[0] - (pointSize / 2)), pointSize, pointSize);
    
    		// Draw rearRight point
    		graphics2D.setColor(Color.ORANGE);
    		// g.drawLine();
    
    		// Draw rearLeft point
    		graphics2D.setColor(Color.ORANGE);
    		// g.drawLine();
    	}
    
    	/* Method to draw the visualisationTriangle to the Boid. */
    	public void drawTriangle(Graphics2D graphics2D) {
    		graphics2D.setColor(Color.BLUE);
    		// TODO first the three points in visualisationTriangle should be calculated correctly. 
    		// graphics2D.drawPolygon(visualisationTriangle.xPoints, visualisationTriangle.yPoints, Triangle.trianglePoints);
    	}
    
    	// ...Getters & setters...
    }

    And here we have a class which creates a Boid and a window the visualise what is happening. The class changes the velocity to all directions and calculates/renders the visualisationTriangle.
    Java Code:
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    /**
     * TriangleCoordinate is a demo to visualise a Boid facing its velocity at all
     * time. Demo is made as a response on thread:
     * https://www.java-forums.org/java-2d/97324-traingle-coordinates-calculating.html
     * 
     * ToDo
     * <ul>
     * <li>Fix issues</li>
     * <li>Move the front of the visualisationTriangle along with the velocity.</li>
     * <li>Calculate and move the rearLeft and rearRight point of the
     * visualisationTriangle.</li>
     * </ul>
     * 
     * Current issues:
     * <ul>
     * <li>The velocity does not walks smoothly along an imaginary circle. At the
     * beginning it switches between positive and negative. Later, the velocity
     * becomes a random point.</li?<li>The velocity decreases.</li>
     * </ul>
     * 
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 {@code build 1}
     */
    public class TriangleCoordinate {
    
    	// MainWindow parameters
    	private JFrame mainWindow;
    	private static final int WIDTH = 300;
    	private static final int HEIGHT = WIDTH;
    	private static final Dimension windowSize = new Dimension(WIDTH, HEIGHT);
    
    	// Parameters to render to/with.
    	private JPanel mainPanel;
    	private BufferedImage bufferedImage;
    	private Graphics2D graphics2D;
    
    	// Grid parameters
    	public static final int gridSize = 25;
    
    	// Boid parameters
    	private Boid boid;
    
    	public TriangleCoordinate() {
    		// Set up Boid
    		boid = new Boid(new Vector2f(WIDTH / 2f, HEIGHT / 2f), new Vector2f(0f, -6f));
    
    		// Calculate the Boid's visualisation.
    		boid.setTriangle();
    
    		initRenderer();
    
    		faceAllDirections();
    	}
    
    	/* Method to set up the window, panel, bufferedImage and Graphics2D object. */
    	private void initRenderer() {
    		mainPanel = new JPanel();
    		mainPanel.setPreferredSize(windowSize);
    		bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
    		graphics2D = (Graphics2D) bufferedImage.getGraphics();
    
    		mainWindow = new JFrame("TriangleCoordinate");
    		mainWindow.setPreferredSize(windowSize);
    		mainWindow.add(mainPanel);
    
    		mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		mainWindow.pack();
    		mainWindow.setVisible(true);
    	}
    
    	/*
    	 * Method to rotate the velocity and check if the visualisation changes
    	 * accordingly.
    	 */
    	private void faceAllDirections() {
    		// How many degrees do the want to increment each tick.
    		int incrementAngleperTick = 1;
    		
    		// Make a full circle (aka: check all directions).
    		for (int currentAngle = 0; currentAngle <= 360; currentAngle += incrementAngleperTick) {
    			// Change the current angle from degrees to radians.
    			double angleInRadians = Math.toRadians(currentAngle);
    
    			// Calculate the new velocity
    			float xOld = boid.velocity.x;
    			boid.velocity.x = (float) (xOld * Math.cos(angleInRadians) - boid.velocity.y * Math.sin(angleInRadians));
    			boid.velocity.y = (float) (xOld * Math.sin(angleInRadians) - boid.velocity.y * Math.cos(angleInRadians));
    
    			// Calculate the Boid's visualisation accordingly.
    			boid.setTriangle();
    
    			// Repaint the bufferedImage.
    			bakeScene();
    			drawScene();
    
    			// Wait one tenth of a second (so my eyes can follow the progress).
    			try {
    				Thread.sleep(100);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	/* Method to bake the next bufferedImage. */
    	public void bakeScene() {
    		graphics2D.clearRect(0, 0, WIDTH, HEIGHT);
    		graphics2D.setBackground(Color.WHITE);
    
    		drawGrid();
    
    		boid.drawBoid(graphics2D);
    
    		boid.drawTrianglePoints(graphics2D);
    
    		boid.drawTriangle(graphics2D);
    	}
    
    	/* Method to draw a grid on the JPanel. */
    	private void drawGrid() {
    		graphics2D.setColor(Color.LIGHT_GRAY);
    
    		// Can be one loop as WDITH = HEIGHT.
    		for (int i = 0; i <= TriangleCoordinate.HEIGHT; i += gridSize) {
    			graphics2D.drawLine(0, i, TriangleCoordinate.WIDTH, i);
    			graphics2D.drawLine(i, 0, i, TriangleCoordinate.HEIGHT);
    		}
    	}
    
    	/* Method to draw (thus show) the next bufferedImage to the mainPanel. */
    	private void drawScene() {
    		Graphics g2 = mainPanel.getGraphics();
    		g2.drawImage(bufferedImage, 0, 0, WIDTH, HEIGHT, null);
    		g2.dispose();
    	}
    
    	public static void main(String[] args) {
    		new TriangleCoordinate();
    	}
    }
    My first question would be; why are the velocity and the frontPoint not nicely 'walking' in a circle around the boid.position?

  4. #4
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    19,942
    Rep Power
    30

    Default Re: Traingle coordinates calculating

    The posted code does not compile without errors (missing class) to be able to execute it for testing.

    Can you make a SSCCE?
    If you don't understand my response, don't ignore it, ask a question.

  5. #5
    Vinvar is offline Member
    Join Date
    Nov 2012
    Posts
    18
    Rep Power
    0

    Default Re: Traingle coordinates calculating

    Quote Originally Posted by Norm View Post
    The posted code does not compile without errors (missing class) to be able to execute it for testing.

    Can you make a SSCCE?
    Norm, thank you for looking at it and I am sorry about me forgetting the Vector2f class. I was trying to make a SSCCE and I thought this was as SSCCE it can be without stop making sense. How would you make this (even more) SSCCE? If you want I can leave the render part (JFrame, etc) out of it. However, I think it would be much harder to see what is happening, looking at values in the console.

    Missing class:
    Java Code:
    /**
     * A 2D Vector where the variables are floats.
     *
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 {@code build 1}
     */
    public class Vector2f {
    
    	/** the x-component of this vector **/
    	public float x;
    	/** the y-component of this vector **/
    	public float y;
    
    	/**
    	 * Constructs a Vector2f with the given components
    	 * 
    	 * @param x
    	 *            The x-component
    	 * @param y
    	 *            The y-component
    	 */
    	public Vector2f(float x, float y) {
    		this.x = x;
    		this.y = y;
    	}
    
    	public float lengthSquared() {
    		return (float) Math.sqrt(x * x + y * y);
    	}
    
    	public Vector2f normalise() {
    		float squaredLength = lengthSquared();
    		if (squaredLength != 0) {
    			x /= squaredLength;
    			y /= squaredLength;
    		}
    		return this;
    	}
    
    	public Vector2f scale(float scalar) {
    		x *= scalar;
    		y *= scalar;
    
    		return this;
    	}
    }

  6. #6
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    19,942
    Rep Power
    30

    Default Re: Traingle coordinates calculating

    Take a look at the recommended way to write custom painting in Swing: Lesson: Performing Custom Painting (The Java™ Tutorials > Creating a GUI With JFC/Swing)
    Basically, the code overrides a GUI component's paintComponent method where the output is drawn to the GUI. Other methods build what is to be shown and call repaint that causes the paintComponent method to be called where the new display is shown. Movement is created by the timing between calls to repaint.
    If you don't understand my response, don't ignore it, ask a question.

  7. #7
    Vinvar is offline Member
    Join Date
    Nov 2012
    Posts
    18
    Rep Power
    0

    Default Re: Traingle coordinates calculating

    I got rid of the swing components (yes, it could have been better coded but it is not the main problem ).

    I redid the TriangleCoordinate and Boid class. Triangle and Vector2f are unchanged.
    Java Code:
    /**
     * TriangleCoordinate is a demo to visualise a Boid facing its velocity at all
     * time. Demo is made as a response on thread:
     * https://www.java-forums.org/java-2d/97324-traingle-coordinates-calculating.html
     * 
     * ToDo
     * <ul>
     * <li>Fix issues</li>
     * <li>Move the front of the visualisationTriangle along with the velocity.</li>
     * <li>Calculate and move the rearLeft and rearRight point of the
     * visualisationTriangle.</li>
     * </ul>
     * 
     * Current issues:
     * <ul>
     * <li>The velocity does not walks smoothly along an imaginary circle. At the
     * beginning it switches between positive and negative. Later, the velocity
     * becomes a random point.</li?<li>The velocity decreases.</li>
     * </ul>
     * 
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 {@code build 2}
     */
    public class TriangleCoordinate {
    
    	// Boid parameters
    	private Boid boid;
    
    	public TriangleCoordinate() {
    		System.out.println("Testing the direction the Boid is facing.\n");
    		System.out.println(
    				"Outcome should be:\n Current angle(0)       = front( 0, 3).\n Current angle(90)      = front( 3, 0).\n Current angle(180/-0)  = front( 0,-3).\n Current angle(270/-90) = front(-3, 0).");
    		System.out.println(" At angles in between the front(x,y) should interpolate between the values.\n");
    
    		// Set up Boid
    		boid = new Boid(new Vector2f(0f, 0f), new Vector2f(0f, -6f));
    
    		// Calculate the Boid's visualisation.
    		boid.setTriangle();
    
    		faceAllDirections();
    	}
    
    	/*
    	 * Method to rotate the velocity and check if the visualisation changes
    	 * accordingly.
    	 */
    	private void faceAllDirections() {
    		// How many degrees do the want to increment each tick.
    		int incrementAngleperTick = 1;
    
    		// Make a full circle (aka: check all directions).
    		System.out.println("...Start simulation...");
    		for (int currentAngle = 0; currentAngle < 360; currentAngle += incrementAngleperTick) {
    			// Change the current angle from degrees to radians.
    			double angleInRadians = Math.toRadians(currentAngle);
    
    			// Calculate the new velocity
    			float xOld = boid.velocity.x;
    			boid.velocity.x = (float) (xOld * Math.cos(angleInRadians) - boid.velocity.y * Math.sin(angleInRadians));
    			boid.velocity.y = (float) (xOld * Math.sin(angleInRadians) - boid.velocity.y * Math.cos(angleInRadians));
    
    			// Calculate the Boid's visualisation accordingly.
    			boid.setTriangle();
    
    			// Print output
    			System.out.printf("Current angle (%s) = front (%s,%s).\n",
    					currentAngle, boid.visualisationTriangle.xPoints[0], boid.visualisationTriangle.yPoints[0]);
    		}
    	}
    
    	public static void main(String[] args) {
    		new TriangleCoordinate();
    	}
    }
    Java Code:
    /**
     * Class to store data about a Boid.
     * 
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 {@code build 2}
     */
    public class Boid {
    
    	public Vector2f position, velocity;
    
    	public Triangle visualisationTriangle;
    
    	// Size of the helper points to render the position and trianglePoints.
    	public static final int pointSize = 20;
    
    	public Boid(Vector2f pos, Vector2f vel) {
    		position = pos;
    		velocity = vel;
    
    		visualisationTriangle = new Triangle();
    	}
    
    	// Every time a tick has been done, this method is called
    	public void setTriangle() {
    		// Front point of triangle
    		Vector2f normalisedVelocity = new Vector2f(velocity.x, velocity.y);
    		normalisedVelocity.normalise();
    
    		Vector2f front = normalisedVelocity.scale(3);
    		visualisationTriangle.xPoints[0] = front.x;
    		visualisationTriangle.yPoints[0] = front.y;
    
    		// TODO
    		// Point rearLeft = ??;
    
    		// TODO
    		// Point rearRight = ??;
    	}
    
    	// ...Getters & setters...
    }
    At the first three lines of the simulation the first problem is shown already. It is switching between positive and negative. Also, the expected outcomes are not
    Java Code:
    Outcome should be:
     Current angle(0)       = front( 0, 3).
     Current angle(90)      = front( 3, 0).
     Current angle(180/-0)  = front( 0,-3).
     Current angle(270/-90) = front(-3, 0).
    
    ...Start simulation...
    Current angle (0) = front (0.0,3.0).
    Current angle (1) = front (-0.05235722,-2.9995432).
    Current angle (2) = front (0.052421063,2.9995418).
    Current angle (3) = front (-0.10482629,-2.998168).
    Current angle (4) = front (0.105082646,2.998159).
    
    Current angle (90) = front (2.1213202,-2.1213202).
    
    Current angle (180) = front (-2.7353E-40,2.7353E-40).
    
    Current angle (270) = front (0.0,0.0).

  8. #8
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    19,942
    Rep Power
    30

    Default Re: Traingle coordinates calculating

    It is switching between positive and negative
    Where are the values being computed? Try debugging that code to see why it is switching its sign.
    If you don't understand my response, don't ignore it, ask a question.

  9. #9
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,174
    Rep Power
    12

    Default Re: Traingle coordinates calculating

    Not certain what I can add to your math approach other than adjusting the origin in the equations.

    Take the following:

    You have a point at (x,y) and you want to rotate it about (sx, sy) by some angle A.

    x1 = sx + (x - sx)cos(A) - (y - sy)sin(A);
    y1 = sy + (x - sx)sin(A) + (y - sy)cos(A);

    where (x1,y1) is the new position. If you are rotating around (0,0) then sx and sy fall out of the equation.

    But you can also do the following:

    Stuff the points in a Polygon instance; create an AffineTransform rotate instance; and get
    the Polygon Pathiterator, applying the transform as the argument. Then you iterate over the path to get
    the transformed points. Note: this is the only way I have done it in the past since there is no obvious way
    available to get a list of the transformed coordinates.

    There will still be some slight errors. For example, when you rotate (100,100) 45 degrees clockwise, it should be (141..., 0).
    But the 0 is actually a very small non-zero number.

    Regards,
    Jim
    Last edited by jim829; 08-12-2017 at 05:22 PM.
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  10. #10
    Vinvar is offline Member
    Join Date
    Nov 2012
    Posts
    18
    Rep Power
    0

    Default Re: Traingle coordinates calculating

    Hi All,

    I solved the issue with Norm's and Jim829's help. Thanks!

    As said earlier, the front and rear point will move following a circular pattern. Looking at it, at any given time the x value of the front point is within the radius. Whatever the value of x, the y value of the front point will also be within the radius.
    Traingle coordinates calculating-vectorradiant.png
    Thus, x and y values of the front point will vary between -3 and 3.

    So, if x moves from -3 to 3 and back, this can be visually represented by a parabola. Which made me think of the standard sinus and the cosinus parabolas.
    Traingle coordinates calculating-sinus.png

    If we multiple the standard sinus and cosinus with the radius of the front point, we get the relative difference between the position of the Boid and the front point.
    Java Code:
    // Distance between the front point and the position.
    public static final float RADIUS_FRONT = 3f;
    
    (...)
    
    float xDelta = (float) Math.cos(angleInRadians) * RADIUS_FRONT;
    float yDelta = (float) Math.sin(angleInRadians) * RADIUS_FRONT;
    
    (...)
    
    // Front point of triangle (relative to the position of the Boid).
    bodyVisualisation.xPoints[0] = xDelta;
    bodyVisualisation.yPoints[0] = yDelta;
    The angleInRadians can be calculated by doing
    Java Code:
    double angleInRadians = Math.toRadians(currentAngle + UP_VECTOR_CORRECTION);
    To get the angleInRadians, you'll need the currentAngle. The current angle can be calculated with Math.atan2.
    Java Code:
    double currentAngle = Math.toDegrees(Math.atan2(0 + rotation.x, 0 - rotation.y));
    And that is it, basically. If we store xDelta and yDelta to the xPoints[] and yPoints[] of the Boid's triangle, we have the offset of the front point. The same math can be applied to get the x and y value of the two rear points.


    To be complete, hereby the complete demo code:
    Boid class, in the setTriangle() method is where the points are calculated
    Java Code:
    /**
     * Class to store data about a Boid.
     * 
     * @author Vinvar
     * @version 1.1
     * @since August 13th, 2017 {@code build 3}
     */
    public class Boid {
    
    	/*
    	 * Normally, angle(0) is to the right. Correct it so upwards is equal to
    	 * angle(0).
    	 */
    	public static final int UP_VECTOR_CORRECTION = -90;
    	/*
    	 * The rear points are not perpendicular from the rotation. Therefore, add an
    	 * angle correction.
    	 */
    	public static final int REAR_ANGLE_CORRECTION = 45;
    	// Distance between the front point and the position.
    	public static final float RADIUS_FRONT = 3f;
    	// Distance between the rear points and the position.
    	public static final float RADIUS_BACK = (float) Math.sqrt(8);
    
    	// Every Boid has a position, rotation (and velocity but it is not needed in this demo.)
    	public Vector2f position, rotation;
    
    	// A triangle visualising the 'body' of the Boid.
    	public Triangle bodyVisualisation;
    
    	public Boid(Vector2f pos, Vector2f rot) {
    		position = pos;
    		rotation = rot;
    
    		bodyVisualisation = new Triangle();
    	}
    
    	/* Set the triangle according to the current rotation of the Boid. */
    	public void setTriangle() {
    
    		// Not needed in this demo: rotation.normalise();
    		double currentAngle = Math.toDegrees(Math.atan2(0 + rotation.x, 0 - rotation.y));
    
    		// Change the current angle from degrees to radians.
    		double angleInRadians = Math.toRadians(currentAngle + UP_VECTOR_CORRECTION);
    
    		// Calculate the delta on both axis for the front point.
    		float xDelta = (float) Math.cos(angleInRadians) * RADIUS_FRONT;
    		float yDelta = (float) Math.sin(angleInRadians) * RADIUS_FRONT;
    
    		// Front point of triangle (relative to the position of the Boid).
    		bodyVisualisation.xPoints[0] = xDelta;
    		bodyVisualisation.yPoints[0] = yDelta;
    
    		// Change the current angle from degrees to radians
    		// Also, include the difference between the currentAngle and the rearLeft angle.
    		angleInRadians = Math.toRadians(currentAngle + REAR_ANGLE_CORRECTION + UP_VECTOR_CORRECTION);
    
    		// Calculate the delta on both axis for the rear point.
    		xDelta = (float) Math.cos(angleInRadians) * RADIUS_BACK;
    		yDelta = (float) Math.sin(angleInRadians) * RADIUS_BACK;
    
    		// Rear left point of triangle (relative to the position of the Boid).
    		bodyVisualisation.xPoints[1] = xDelta;
    		bodyVisualisation.yPoints[1] = yDelta;
    
    		// Change the current angle from degrees to radians.
    		// Also, include the difference between the currentAngle and the rearRight angle.
    		angleInRadians = Math.toRadians(currentAngle - REAR_ANGLE_CORRECTION + UP_VECTOR_CORRECTION);
    
    		// Calculate the delta on both axis for the rear point.
    		xDelta = (float) Math.cos(angleInRadians) * RADIUS_BACK;
    		yDelta = (float) Math.sin(angleInRadians) * RADIUS_BACK;
    
    		// Rear right point of triangle (relative to the position of the Boid).
    		bodyVisualisation.xPoints[2] = xDelta;
    		bodyVisualisation.yPoints[2] = yDelta;
    	}
    
    	// ...Getters & setters...
    }
    TriangleCoordinate class. Just a simple (quick and dirty) helper class to test the Boid class.
    Java Code:
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    /**
     * TriangleCoordinate is a demo to visualise a Boid facing its rotation at all
     * time. Demo is made as a response on thread:
     * https://www.java-forums.org/java-2d/97324-traingle-coordinates-calculating.html
     * 
     * Current issues:
     * <ul>
     * <li>No issues known.</li>
     * </ul>
     * 
     * @author Vinvar
     * @version 1.1
     * @since August 13th, 2017 {@code build 3}
     */
    public class TriangleCoordinate {
    
    	// MainWindow parameters
    	private JFrame mainWindow;
    	private static final int WIDTH = 300;
    	private static final int HEIGHT = WIDTH;
    	private static final Dimension windowSize = new Dimension(WIDTH, HEIGHT);
    
    	// Parameters to render to/with.
    	private JPanel mainPanel;
    	private BufferedImage bufferedImage;
    	private Graphics2D graphics2D;
    
    	// Grid parameters
    	public static final int GRID_SIZE = 25;
    
    	// Boid parameters
    	private Boid boid;
    	public static final int BOID_POINT_SIZE = 20;
    
    	public TriangleCoordinate() {
    		System.out.println("Testing the direction the Boid is facing.\n");
    		System.out.println(
    				"Outcome should be:\n Current angle(0)       = front( 0,-3), rearLeft( 2,-2), rearRight(-2,-2).");
    		System.out.println(" Current angle(90)      = front( 3, 0), rearLeft( 2, 2), rearRight( 2,-2).");
    		System.out.println(" Current angle(180/-0)  = front( 0, 3), rearLeft(-2, 2), rearRight( 2, 2).");
    		System.out.println(" Current angle(270/-90) = front(-3, 0), rearLeft(-2,-2), rearRight(-2, 2).");
    		System.out.println(" At angles in between the front(x,y) should interpolate between the values.\n");
    
    		// Set up Boid
    		boid = new Boid(new Vector2f(WIDTH / 2f, HEIGHT / 2f), new Vector2f(0f, -6f));
    
    		// Calculate the Boid's visualisation.
    		boid.setTriangle();
    
    		initRenderer();
    
    		faceAllDirections();
    	}
    
    	/* Method to set up the window, panel, bufferedImage and Graphics2D object. */
    	private void initRenderer() {
    		mainPanel = new JPanel();
    		mainPanel.setPreferredSize(windowSize);
    		bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
    		graphics2D = (Graphics2D) bufferedImage.getGraphics();
    
    		mainWindow = new JFrame("TriangleCoordinate");
    		mainWindow.setPreferredSize(windowSize);
    		mainWindow.add(mainPanel);
    
    		mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		mainWindow.pack();
    		mainWindow.setVisible(true);
    	}
    
    	/*
    	 * Method to rotate the direction and check if the visualisation changes
    	 * accordingly.
    	 */
    	private void faceAllDirections() {
    		// How many degrees do the want to increment each tick.
    		int incrementAngleperTick = 1;
    
    		// Make a full circle (aka: check all directions).
    		System.out.println("...Start simulation...");
    		for (int currentAngle = 0; currentAngle <= 360; currentAngle += incrementAngleperTick) {
    			// Stub method to change the rotation of the Boid.
    			// Normally the velocity will change and with it the rotation.
    			// As the rotation changes, I want to...
    			setRotation(currentAngle);
    
    			// ... calculate the Boid's visualisation accordingly.
    			boid.setTriangle();
    
    			// Output to console
    			if (currentAngle % 90 == 0) {
    				System.out.printf(" Current angle(%s) = front(%s, %s), rearLeft(%s,%s), rearRight(%s,%s).\n",
    						currentAngle, Math.round(boid.bodyVisualisation.xPoints[0]),
    						Math.round(boid.bodyVisualisation.yPoints[0]), Math.round(boid.bodyVisualisation.xPoints[1]),
    						Math.round(boid.bodyVisualisation.yPoints[1]), Math.round(boid.bodyVisualisation.xPoints[2]),
    						Math.round(boid.bodyVisualisation.yPoints[2]));
    			}
    			// Repaint the bufferedImage.
    			bakeScene();
    			drawScene();
    
    			// Wait one hundredth of a second (so my eyes can follow the progress).
    			try {
    				Thread.sleep(10);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		System.out.println("...End of simulation...");
    	}
    
    	/*
    	 * Method to change the rotation of the Boid.
    	 * 
    	 * This method is a stub method. Normally a steering force (or something alike)
    	 * will change the velocity and with it the rotation of the Boid.
    	 */
    	private void setRotation(int currentAngle) {
    		// Calculate the difference between the upwards angle and the currentAngle.
    		// Also, change the current angle from degrees to radians.
    		double angleInRadians = Math.toRadians(currentAngle + Boid.UP_VECTOR_CORRECTION);
    
    		// Calculate the delta on both axis.
    		float xDelta = (float) Math.cos(angleInRadians);
    		float yDelta = (float) Math.sin(angleInRadians);
    
    		// Set the new rotation...
    		boid.rotation = new Vector2f(xDelta, yDelta);
    	}
    
    	/* Method to bake the next bufferedImage. */
    	public void bakeScene() {
    		graphics2D.clearRect(0, 0, WIDTH, HEIGHT);
    		graphics2D.setBackground(Color.WHITE);
    
    		drawGrid();
    
    		drawBoid();
    
    		drawTrianglePoints();
    
    		drawTriangle();
    	}
    
    	/* Method to draw a grid on the JPanel. */
    	private void drawGrid() {
    		graphics2D.setColor(Color.LIGHT_GRAY);
    
    		// Can be one loop as WDITH = HEIGHT.
    		for (int i = 0; i <= TriangleCoordinate.HEIGHT; i += GRID_SIZE) {
    			graphics2D.drawLine(0, i, TriangleCoordinate.WIDTH, i);
    			graphics2D.drawLine(i, 0, i, TriangleCoordinate.HEIGHT);
    		}
    	}
    
    	// ... draw methods ...
    
    	/* Method to draw the parameters (position & rotation) of the Boid. */
    	public void drawBoid() {
    		// draw position of Boid
    		graphics2D.setColor(Color.BLACK);
    		graphics2D.fillOval((int) boid.position.x - (BOID_POINT_SIZE / 2),
    				(int) boid.position.y - (BOID_POINT_SIZE / 2), BOID_POINT_SIZE, BOID_POINT_SIZE);
    
    		// draw rotation of Boid
    		graphics2D.setColor(Color.RED);
    		graphics2D.drawLine((int) boid.position.x, (int) boid.position.y,
    				(int) (boid.position.x + (boid.rotation.x * (GRID_SIZE * 10))),
    				(int) (boid.position.y + (boid.rotation.y * (GRID_SIZE * 10))));
    	}
    
    	/*
    	 * Method to draw the parameters (front, rearLeft and rearRight) of the
    	 * triangleVisualisation.
    	 */
    	public void drawTrianglePoints() {
    		// Draw front point
    		graphics2D.setColor(new Color(139, 0, 139)); // Dark purple
    		graphics2D.fillOval(
    				(int) (boid.position.x + boid.bodyVisualisation.xPoints[0] * GRID_SIZE - (BOID_POINT_SIZE / 2)),
    				(int) (boid.position.y + boid.bodyVisualisation.yPoints[0] * GRID_SIZE - (BOID_POINT_SIZE / 2)),
    				BOID_POINT_SIZE, BOID_POINT_SIZE);
    
    		// Draw rearLeft point
    		graphics2D.setColor(Color.ORANGE);
    		graphics2D.fillOval(
    				(int) (boid.position.x - boid.bodyVisualisation.xPoints[2] * GRID_SIZE - (BOID_POINT_SIZE / 2)),
    				(int) (boid.position.y - boid.bodyVisualisation.yPoints[2] * GRID_SIZE - (BOID_POINT_SIZE / 2)),
    				BOID_POINT_SIZE, BOID_POINT_SIZE);
    
    		// Draw rearRight point
    		graphics2D.setColor(Color.ORANGE);
    		graphics2D.fillOval(
    				(int) (boid.position.x - boid.bodyVisualisation.xPoints[1] * GRID_SIZE - (BOID_POINT_SIZE / 2)),
    				(int) (boid.position.y - boid.bodyVisualisation.yPoints[1] * GRID_SIZE - (BOID_POINT_SIZE / 2)),
    				BOID_POINT_SIZE, BOID_POINT_SIZE);
    	}
    
    	/* Method to draw the visualisationTriangle to the Boid. */
    	public void drawTriangle() {
    
    		// Convert float[] to int[] as drawPolygon requires int[].
    		int[] intPointsX = new int[3];
    		int[] intPointsY = new int[3];
    
    		intPointsX[0] = (int) (boid.position.x + (boid.bodyVisualisation.xPoints[0] * GRID_SIZE));
    		intPointsY[0] = (int) (boid.position.y + (boid.bodyVisualisation.yPoints[0] * GRID_SIZE));
    
    		for (int i = 1; i < intPointsX.length; i++) {
    			intPointsX[i] = (int) (boid.position.x - (boid.bodyVisualisation.xPoints[i] * GRID_SIZE));
    			intPointsY[i] = (int) (boid.position.y - (boid.bodyVisualisation.yPoints[i] * GRID_SIZE));
    		}
    
    		// Draw polygon
    		graphics2D.setColor(Color.BLUE);
    		graphics2D.drawPolygon(intPointsX, intPointsY, Triangle.trianglePoints);
    	}
    
    	/* Method to draw (thus show) the next bufferedImage to the mainPanel. */
    	private void drawScene() {
    		Graphics g2 = mainPanel.getGraphics();
    		g2.drawImage(bufferedImage, 0, 0, WIDTH, HEIGHT, null);
    		g2.dispose();
    	}
    
    	public static void main(String[] args) {
    		new TriangleCoordinate();
    	}
    }
    Triangle class, not changed
    Java Code:
    /**
     * Class to store data about a triangle.
     * 
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 ({@code build 1}).
     */
    public class Triangle {
    	// Number of points a triangle has.
    	public static final int trianglePoints = 3;
    
    	// Array of points, representing the Triangle.
    	// The points are relative to the Boid's position.
    	// Stored counter clockwise: front, rearLeft, rearRight.
    	public float[] xPoints;
    	public float[] yPoints;
    
    	public Triangle() {
    		xPoints = new float[trianglePoints];
    		yPoints = new float[trianglePoints];
    	}
    
    	// ..Getters & Setters...
    }
    Vector2f class, not changed
    Java Code:
    /**
     * A 2D Vector where the variables are floats.
     *
     * @author Vinvar
     * @version 1.0
     * @since August 12th, 2017 {@code build 1}
     */
    public class Vector2f {
    
    	/** the x-component of this vector **/
    	public float x;
    	/** the y-component of this vector **/
    	public float y;
    
    	/**
    	 * Constructs a Vector2f with the given components
    	 * 
    	 * @param x
    	 *            The x-component
    	 * @param y
    	 *            The y-component
    	 */
    	public Vector2f(float x, float y) {
    		this.x = x;
    		this.y = y;
    	}
    
    	/**
    	 * 
    	 * @return Float representing the length of the Vector2f.
    	 */
    	public float lengthSquared() {
    		return (float) Math.sqrt(x * x + y * y);
    	}
    
    	/**
    	 * Method to normalise this Vecotr2f.
    	 * 
    	 * @return Normalised Vector2f.
    	 */
    	public Vector2f normalise() {
    		float squaredLength = lengthSquared();
    		if (squaredLength != 0) {
    			x /= squaredLength;
    			y /= squaredLength;
    		}
    		return this;
    	}
    
    	/**
    	 * Method to scale this Vector2f.
    	 * 
    	 * @param scalar
    	 *            Float of scale value.
    	 * @return Scaled Vector2f.
    	 */
    	public Vector2f scale(float scalar) {
    		x *= scalar;
    		y *= scalar;
    
    		return this;
    	}
    
    	/**
    	 * Converts this {@code Vector2f} to a string in the format {@code (x,y)}.
    	 * 
    	 * @return a string representation of this object.
    	 */
    	@Override
    	public String toString() {
    		return "(" + x + "," + y + ")";
    	}
    }

Similar Threads

  1. Flipping these coordinates.
    By zFollette in forum New To Java
    Replies: 2
    Last Post: 01-15-2014, 01:41 AM
  2. Getting the right coordinates (Bubblegame)
    By NGE in forum New To Java
    Replies: 7
    Last Post: 06-27-2011, 11:19 PM
  3. Coordinates out of bounds
    By trishtren in forum Java 2D
    Replies: 3
    Last Post: 05-19-2011, 08:10 PM
  4. Coordinates in PDFBox
    By arunsegar in forum Advanced Java
    Replies: 1
    Last Post: 05-16-2011, 09:41 AM
  5. Coordinates
    By Witik in forum New To Java
    Replies: 3
    Last Post: 09-06-2010, 07:05 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •