this question is continue of GPS coordinates to pixel.
I need to draw a several polygons. I can draw each polygon alone, but cant all polygons on right position.
I load information about polygon from this file:
GPS
I have class Kraj, which represent each polygon.
public class Kraj {
String name;
Point2D.Double points[];
Point2D.Double transPoints[];
Point2D.Double max;
Point2D.Double min;
// polygon
Path2D.Double polygon;
ArrayList<Kraj> kraje;
public Kraj(String name, Point2D.Double body[])
{
this.name = name;
this.body = Arrays.copyOf(body, body.length);
// calculate a bounding box
zjistiLimity();
this.transPoints = new Point2D.Double[points.length];
}
private void transformToWindow(int width, int height)
{
// convert to window
double convertX = width / (max.x - min.x);
double convertY = height / (max.y - min.y);
// calculate polygon to fit in window with right aspect ratio
double convert = convertX > convertY ? convertY : convertX;
// min = 0, convert to interval <0: infinity> and multiply by convert,
for (int j = 0; j < points.length; j++) {
double transX = (points[j].x - min.x) * convert;
double transY = height - (points[j].y - min.y) * convert;
transPoints[j] = new Point2D.Double(transX, transY);
}
this.polygon = new Path2D.Double();
this.polygon.moveTo(transBody[0].x, transBody[0].y);
for (int i = 1; i < body.length; i++)
this.polygon.lineTo(transPoints[i].x, transPoints[i].y);
this.polygon.closePath();
}
private void drawKraj(Graphics2D g2, int width, int height) {
g2.setStroke(new BasicStroke(2));
g2.fill(polygon);
// vykreslime obrys
g2.setColor(Color.black);
g2.draw(polygon);
}
public void draw(Graphics2D g2,
int contextWidth, int contextHeight)
{
// fit to window size
int sirkaSOdsazenim = contextWidth;
int vyskaSOdsazenim = contextHeight;
this.transformujToWindow(sirkaSOdsazenim, vyskaSOdsazenim);
this.drawKraj(g2, sirkaSOdsazenim, vyskaSOdsazenim);
}
/**
* Set min and max
*/
private void zjistiLimity() {
max = new Point2D.Double(-Double.MAX_VALUE, -Double.MAX_VALUE);
min = new Point2D.Double(Double.MAX_VALUE, Double.MAX_VALUE);
for(int j = 0; j < 10; j++)
{
for (int i = 0; i < body.length; i++)
{
if (points[i].getX() < min.getX()) min.x = points[i].getX();
if (points[i].getY() < min.getY()) min.y = points[i].getY();
if (points[i].getX() > max.getX())max.x = points[i].getX();
if (points[i].getY() > max.getY()) max.y = points[i].getY();
}
}
}
With this code I can draw polygon, which fit to window. But I need to draw all polygons to fit to window (calculate coordinates to create this map):
What I need to edit or add? Thanks for all answers.
You can translate the entire polygon by using:
g2.translate(x, y);
g2.draw(polygon);
g2.translate(-x, -y)
Determining the appropriate x/y translation for each polygon is something you will need to do.
I need to draw a several polygons. I can draw each polygon alone, but I can't draw all polygons in the right position.
If you can draw each polygon alone, then your polygons are correct.
You need to add an origin point to your Kraj class. Then your draw method would transform the polygon points from the polygon origin to the map origin. Assuming your polygon origin is (10,10) and a particular polygon needs to be drawn at (20,30), then you would add 10 to the x and add 20 to the y of each point in the polygon before you draw it.
You can do this my making a copy of the polygon in the draw routine before you adjust the X and Y values of each point.
Edited to add: Here's your own code modified to transform the origin. I've not tested these changes.
private void transformToWindow(Point2D windowOrigin, int width, int height)
{
// convert to window
double convertX = width / (max.x - min.x);
double convertY = height / (max.y - min.y);
// calculate polygon to fit in window with right aspect ratio
double convert = convertX > convertY ? convertY : convertX;
// min = 0, convert to interval <0: infinity> and multiply by convert,
for (int j = 0; j < points.length; j++) {
double transX = (points[j].x - min.x) * convert;
double transY = height - (points[j].y - min.y) * convert;
transPoints[j] = new Point2D.Double(transX, transY);
}
this.polygon = new Path2D.Double();
double xShift = windowOrigin.x - transBody[0].x;
double yShift = windowOrigin.y - transBody[0].y;
this.polygon.moveTo(windowOrigin.x, windowOrigin.y);
for (int i = 1; i < body.length; i++)
this.polygon.lineTo(transPoints[i].x + xShift,
transPoints[i].y + yShift);
this.polygon.closePath();
}
Related
I am trying to make a program where there are lines in a grid pointing towards the mouse like magnets. I am a beginner in Processing, can someone point me towards a tutorial on how to do that or give me some code and explain what it does?
int x1 = 0;
int x2 = 0;
int y1 = 0;
int y2 = 0;
void setup() {
size(200, 200);
}
void draw() {
background(255, 255, 0);
x1 = (mouseX + 100) / 2;
y1 = (mouseY + 100) / 2;
x2 = -1 * x1 + 200;
y2 = -1 * y1 + 200;
line(x1, y1, x2, y2);
}
There's plenty of solutions for this project. One of the easiest is to use Processing's PVector class.
The PVector class can be used for two or three dimensional vectors. A vector is an entity that has both magnitude and direction. The PVector class, however, stores the components of the vector (x,y for 2D, and x,y,z for 3D). The magnitude and direction are calculated from the components and can be accessed via the methods mag() and heading().
A two dimensional vector in Processing is defined through x and y components:
PVector v = new PVector(xComponent, yComponent);
With some mathematical formulae, you can determine magnitude and direction using the x- and y-components. But we don't need to determine these.
Below, I've attached completed solution code. Most of it should make sense to you. But it's worth understanding what is going on with PVector.
A nested for loop within void draw() contains x and y variables that represent the coordinates of each grid vertex.
We first define PVector v as a vector given by an x-component of mouseX - x, or the difference between the x-positions of the mouse and each grid point. Similarly, the y-component given by mouseY - y has the same difference.
Creating a variable PVector u initialized from v.setMag(15) holds a PVector that has the same direction as v, but with a length of just 15.
Now to draw the lines. Vectors represent an offset, not a position (in this case), so drawing a line from a grid point to an offset of a grid point is key.
Hence line(x, y, x + u.x, y + u.y), where u.x and u.y are the x- and y-components of the vector u.
void setup() {
size(600, 600); // Set the size of the canvas to 600x600.
}
void draw() {
background(255);
stroke(200); // Set the stroke color to black
int distVertLine = width / 10; // This variable defines the distance between each subsequent vertical line.
for(int i = 0; i < width; i += distVertLine) {
line(i, 0, i, height); // Draw a line at x=i starting at the top of the canvas (y=0) and going to the bottom (y=height)
}
int distHorizLine = height / 10; // This variable defines the distance between each subsequent vertical line.
for(int i = 0; i < width; i += distHorizLine) {
line(0, i, width, i); // Draw a line at y=i starting at the left of the canvas (x=0) and going to the right (x=width)
}
stroke(0); // Set the stroke to black.
// Use a nested for loop to iterate through all grid vertices.
for(int x = 0; x <= width; x += width/10) {
for(int y = 0; y <= height; y += height/10) {
PVector v = new PVector(mouseX - x, mouseY - y); // Define a vector that points in the direction of the mouse from each grid point.
PVector u = v.setMag(15); // Make the vector have a length of 15 units.
line(x, y, x + u.x, y + u.y); // Draw a line from the grid vertex to the terminal point given by the vector.
}
}
}
The answer already given by Ben Myers is excellent! The code below has a few small modifications:
the two for loops for the grid lines have been combined (since width and height are equal);
the construction of the vector is combined with setting the magnitude;
some minor changes to colors and comments.
Modified code:
void setup() {
// Set the size of the canvas to 600x600 pixels.
size(600, 600);
}
void draw() {
// There are 10x10 grid cells that each have a size of 60x60 pixels.
int gridSize = width / 10;
// Set the background color to anthracite and the stroke color to orange.
background(56, 62, 66);
stroke(235, 113, 52);
// Draw vertical and horizontal grid lines.
for (int lineIndex = 0; lineIndex < gridSize; lineIndex++) {
line(lineIndex * gridSize, 0, lineIndex * gridSize, height);
line(0, lineIndex * gridSize, width, lineIndex * gridSize);
}
// Set the stroke color to blue.
stroke(0, 139, 225);
// Use a nested for loop to iterate through all grid cells.
for (int x = 0; x <= width; x += gridSize) {
for (int y = 0; y <= height; y += gridSize) {
// Define a vector that points in the direction of the mouse from
// each grid point and set the vector length to 15 units.
PVector vector = new PVector(mouseX - x, mouseY - y).setMag(15);
// Draw a line from the grid point to the end point using the vector.
line(x, y, x + vector.x, y + vector.y);
}
}
}
I'm trying to create a script that drawls a curve through 'n' vertexes equally spaced around the center of an ellipse.
The reason I'm not just drawling an ellipse around the center ellipse is because I eventually want to connect a micro-controller to Processing where the data points acquired from the 'n' amount of sensors will vary the height ('y') of each vertex, creating constantly changing, irregular curves around the center ellipse such as this possible curve:
Essentially, this is supposed to be a data visualizer, but I cannot figure out why this is not working or how to achieve this effect after going through examples and the documentation on https://processing.org/reference/.
Here is my code:
color WHITE = color(255);
color BLACK = color(0);
void setup() {
size(500, 500);
}
void draw() {
background(WHITE);
translate(width/2, height/2); // move origin to center of window
// center ellipse
noStroke();
fill(color(255, 0, 0));
ellipse(0, 0, 10, 10); // center point, red
fill(BLACK);
int n = 10;
int y = 100;
float angle = TWO_PI / n;
beginShape();
for (int i = 0; i < n; i++) {
rotate(angle);
curveVertex(0, y);
}
endShape();
}
The matrix operations like rotate do not transform the single vertices in a shape. The current matrix is applied to the entire shape when it is draw (at endShape). You've to calculate all the vertex coordinates:
Create a ArrayList of PVector, fill it with points and draw it in a loop:
color WHITE = color(255);
color BLACK = color(0);
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size(500, 500);
int n = 10;
int radius = 100;
for (int i = 0; i <= n; i++) {
float angle = TWO_PI * (float)i/n;
points.add(new PVector(cos(angle)*radius, sin(angle)*radius));
}
}
void draw() {
background(WHITE);
translate(width/2, height/2);
noFill();
stroke(255, 0, 0);
beginShape();
PVector last = points.get(points.size()-1);
curveVertex(last.x, last.y);
for (int i = 0; i < points.size(); i++) {
PVector p = points.get(i);
curveVertex(p.x, p.y);
}
PVector first = points.get(0);
curveVertex(first.x, first.y);
endShape();
}
I'm working on an ASCII graphics engine in Java, to emulate terminal graphics without some of the headaches of dealing with actual terminals.
One key element is coloring the background of characters. So at every position, I put a rectangle, which serves as the background color, and a Text object, which represents a character (using monospace fonts).
I've tried using FlowPanes, TilePanes, GridPanes, but regular Panes seem to work best (least spacing achieved). Here is an image that shows the issue at hand: Screenshot
I'm trying to make all the rectangles align in a way that there is no visible space to see through to the background. In the image linked above, there should be no black ridges between the colored rectangles.
Here is the code I have that adds the Rectangle and Text for each "pixel" (which is simply a class called Char that holds a Rectangle and a Text object).
for (int x = 0; x < COLUMNS; x++)
for (int y = 0; y < ROWS; y++)
pixels[x][y] = new Char(pane, paddingX + x * width, paddingY + y * height, width, height);
The height and width are calculated before this block, and are determined based on the font used. They represent the width and height of any character, since the font used is monospace. The padding is just a number used to center the "pixels", and is also determined before the nested loop.
Char class:
private Text ch;
private Rectangle background;
Char(Pane pane, double x, double y, double w, double h) {
ch = new Text();
ch.relocate(x, y);
ch.setFont(View.font);
ch.setFill(Color.WHITE);
background = new Rectangle(w, h, Color.BLACK);
background.relocate(x, y);
ch.setBoundsType(TextBoundsType.VISUAL);
pane.getChildren().addAll(background, ch);
}
This is a rounding issue. It can be fixed by making sure you're using integral locations and sizes.
In the following code you replacing the assignments for x, y, nx and ny to the ones in the comments results in visible gaps but changing w and h to integral values, e.g. 10, also prevents visible gaps:
#Override
public void start(Stage primaryStage) {
double w = 10.5;
double h = 10.5;
Pane pane = new Pane();
for (int i = 0; i < 57; i++) {
for (int j = 0; j < 57; j++) {
double x = Math.floor(i * w);
double y = Math.floor(j * h);
double nx = Math.floor((i + 1) * w);
double ny = Math.floor((j + 1) * h);
// double x = i * w;
// double y = j * h;
// double nx = (i + 1) * w;
// double ny = (j + 1) * h;
Rectangle rect = new Rectangle(x, y, nx - x, ny - y);
rect.setFill(Color.BLACK);
pane.getChildren().add(rect);
}
}
primaryStage.setScene(new Scene(pane, 600, 600));
primaryStage.show();
}
I'm coding an Android game and I'm trying to put the character in the middle of the screen (X axis).
In order to get the middle of the screen I get the screen width withe the following command:
int phoneWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
Then I divide phoneWidth by two and hoped that the character would appear in the middle of the screen but it appears slightly to the right.
This is the code that I use:
public void drawCharacter() {
charImg = new Texture("pika.PNG");
charSprite = new Sprite(charImg);
float ahaha = Gdx.graphics.getWidth();
charPosX = (float)phoneWidth/ 2;
}
#Override
public void render() {
ch.stop();
double elapsedSeconds = ch.getSeconds();
checkLevel();
handleObstacles();
scrollTimer = scrollTimer + Gdx.graphics.getDeltaTime() / 2;
if (scrollTimer > 1.0f)
scrollTimer = 0.0f;
sprite.setV(scrollTimer);
sprite.setV2(scrollTimer + 2);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
charSprite.setPosition(charPosX, charPosY);
for (int i = 0; i < obstacles.size(); i++) {
obstacleSprites.get(i).setPosition(obstacles.get(i).getPosX(), obstacles.get(i).getPosY());
}
spriteBatch.begin();
sprite.draw(spriteBatch);
charSprite.draw(spriteBatch);
for (int i = 0; i < obstacleSprites.size(); i++) {
obstacleSprites.get(i).draw(spriteBatch);
}
spriteBatch.end();
moveCharacter();
moveObstacle();
}
Does anyone know where this error come from?
The left-hand edge of your sprite will be in the middle of the screen.
Subtract half the sprite width from half the screen width to draw the sprite centered horizontally.
I have a shape and a vector of shape's points, and I want to zoom in/out (resize whatever) the shape by dragging the mouse from a point of the shape to other random point (like in windows point for example)
What I search e read is that to scale a shape you have to recalculate all coordinates to:
xScaled = firstX * scaleX
yScaled = firstY * sclaleY
My problem is how to find that scale factor, what is the formula? Remebering that I have acess to the firstHitPoint, the actual point and all the points of the shape, and I have to do this by dragging the mouse.
Here is a peaceof my code:
#Override
public void transformPoints() {
findTransformationFactors();
int size = points.size();
for(int i = 0; i < size; i++)
points.set(i, new Point(points.get(i).x * scaleX, points.get(i).y * scaleY));
}
#Override
public void findTransformationFactors() {
int oldx = firstHitPoint.x;
int oldY = firstHitPoint.y;
int actualX = actualPoint.x;
int actualY = actualPoint.y;
scaleX = ??
scaleY = ??
}
The X factor taking the center as a constant point:
xVar = (initial.getX()-mouse.getX())/(center.getX()-initial.getX());
scaleX=xVar+1.0;
Then you must control that the scale applied is not negative --> avoid mirror transform