How to rotate a polygon around it's center? - java

I've found other questions asking how to do this but I haven't gotten any of them to work. I'm trying to write a method that rotates a polygon around it's center a number of degrees. My current code makes it disappear from the screen when it moves a degree.
public void rotate(double angle) {
AffineTransform at = new AffineTransform();
int xCoords [] = {(int)line1.getX1(), (int)line2.getX1(), (int)line3.getX1()};
int yCoords [] = {(int)line1.getY1(), (int)line2.getY1(), (int)line3.getY1()};
Polygon polygon = new Polygon(xCoords, yCoords, 3);
at.rotate(Math.toRadians(angle), getX(), getY());
for (int i = 0; i < polygon.npoints; i++){
Point p = new Point(polygon.xpoints[i], polygon.ypoints[i]);
at.transform(p, p);
//System.out.println(p.x);
//System.out.println(p.y);
poly.addPoint(p.x, p.y);
}
setA(poly.xpoints[1], poly.ypoints[1]);
setB(poly.xpoints[2], poly.ypoints[2]);
setC(poly.xpoints[3], poly.ypoints[3]);
}
edit: include attempt

Related

How to connect random points inside a non-convex polygon, without intersecting with the polygon boundaries, in java

I am using code from How to get a random point on the interior of an irregular polygon? slightly modified in order to draw a random path2D by connecting random points together one after the other inside a polygon Shape. The problem is when the Shape is a non-convex polygon, the path can intersect with the polygon sides. What would be a propper way to stop intersecting and create a path with all its segments inside the Shape area? A solution could be the reordering of points in a way that never intersect with Shape. A similar reordering example might help.
//generate random points inside a polygon Shape
public ArrayList<Point2D> generateDoubleRandomPointList(Shape region, int numberRandomPoints){
ArrayList<Point2D> randomPointList = new ArrayList<>();
for (int i = 0; i < numberRandomPoints; i++) {
Rectangle2D r = region.getBounds();
double x = 0, y = 0;
Random rand = new Random();
if(!r.isEmpty()) { // prevent null exception
do {
x = (double) (r.getX() + rand.nextDouble( (double) r.getWidth() ));
y = (double) (r.getY() + rand.nextDouble( (double) r.getHeight() ));
} while(!region.contains(x,y));
}
else{
//nothing here
}
randomPointList.add(new Point2D.Double(x,y)); // new
}
return randomPointList;
}
// create the path
public static Path2D createPathFromListOfPoints2D(List<Point2D> points) {
// Create a Path2D object
java.awt.geom.Path2D path = new java.awt.geom.Path2D.Double();
Point2D p = points.get(0);
double xΑ = p.getX();
double yΑ = p.getY();
// Start at the first coordinate given
path.moveTo(xΑ, yΑ);
// Loop over the remaining coordinates:
for(int i=1; i<points.size(); i++) {
p = points.get(i);
// And draw lines from corner to corner
path.lineTo(p.getX(), p.getY());
}
// After the loop, close the path to finish the polygon
path.closePath();
return path;
}

How to use AffineTransform with very little coordinates?

I have a set of two dimensions points. Their X and Y are greater than -2 and lesser than 2. Such point could be : (-0.00012 ; 1.2334 ).
I would want to display these points on a graph, using rectangles (a rectangle illustrates a point, and has its coordinates set to its point's ones - moreover, it has a size of 10*10).
Rectangles like (... ; Y) should be displayed above any rectangles like (... ; Y-1) (positive Y direction is up). Thus, I must set the graph's origin not at the top-left hand-corner, but somewhere else.
I'm trying to use Graphics2D's AffineTransform to do that.
I get the minimal value for all the X coordinates
I get the minimal value for all the Y coordinates
I get the maximal value for all the X coordinates
I get the maximal value for all the Y coordinates
I get the distance xmax-xmin and ymax-ymin
Then, I wrote the code I give you below.
Screenshots
Some days ago, using my own method to scale, I had this graph:
(so as I explained, Y are inverted and that's not a good thing)
For the moment, i.e., with the code I give you below, I have only one point that takes all the graph's place! Not good at all.
I would want to have:
(without lines, and without graph's axis. The important here is that points are correctly displayed, according to their coordinates).
Code
To get min and max coordinates value:
x_min = Double.parseDouble((String) list_all_points.get(0).get(0));
x_max = Double.parseDouble((String) list_all_points.get(0).get(0));
y_min = Double.parseDouble((String) list_all_points.get(0).get(1));
y_max = Double.parseDouble((String) list_all_points.get(0).get(1));
for(StorableData s : list_all_points) {
if(Double.parseDouble((String) s.get(0)) < x_min) {
x_min = Double.parseDouble((String) s.get(0));
}
if(Double.parseDouble((String) s.get(0)) > x_max) {
x_max = Double.parseDouble((String) s.get(0));
}
if(Double.parseDouble((String) s.get(1)) < y_min) {
y_min = Double.parseDouble((String) s.get(1));
}
if(Double.parseDouble((String) s.get(1)) > y_max) {
y_max = Double.parseDouble((String) s.get(1));
}
}
To draw a point:
int x, y;
private void drawPoint(Cupple storable_data) {
//x = (int) (storable_data.getNumber(0) * scaling_coef + move_x);
//y = (int) (storable_data.getNumber(1) * scaling_coef + move_y);
x = storable_data.getNumber(0).intValue();
y = storable_data.getNumber(1).intValue();
graphics.fillRect(x, y, 10, 10);
graphics.drawString(storable_data.toString(), x - 5, y - 5);
}
To paint the graph:
#Override
public void paint(Graphics graphics) {
this.graphics = graphics;
Graphics2D graphics_2d = ((Graphics2D) this.graphics);
AffineTransform affine_transform = graphics_2d.getTransform();
affine_transform.scale(getWidth()/(x_max - x_min), getHeight()/(y_max - y_min));
affine_transform.translate(x_min, y_min);
graphics_2d.transform(affine_transform);
for(StorableData storable_data : list_all_points) {
graphics_2d.setColor(Color.WHITE);
this.drawPoint((Cupple) storable_data);
}
I suggest you map each data point to a point on the screen, thus avoiding the following coordinate system pitfalls. Take your list of points and create from them a list of points to draw. Take into account that:
The drawing is pixel-based, so you will want to scale your points (or you would have rectangles 1 to 4 pixels wide...).
You will need to translate all your points because negative values will be outside the boundaries of the component on which you draw.
The direction of the y axis is reversed in the drawing coordinates.
Once that is done, use the new list of points for the drawing and the initial one for calculations. Here is an example:
public class Graph extends JPanel {
private static int gridSize = 6;
private static int scale = 100;
private static int size = gridSize * scale;
private static int translate = size / 2;
private static int pointSize = 10;
List<Point> dataPoints, scaledPoints;
Graph() {
setBackground(Color.WHITE);
// points taken from your example
Point p1 = new Point(-1, -2);
Point p2 = new Point(-1, 0);
Point p3 = new Point(1, 0);
Point p4 = new Point(1, -2);
dataPoints = Arrays.asList(p1, p2, p3, p4);
scaledPoints = dataPoints.stream()
.map(p -> new Point(p.x * scale + translate, -p.y * scale + translate))
.collect(Collectors.toList());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(size, size);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// draw a grid
for (int i = 0; i < gridSize; i++) {
g2d.drawLine(i * scale, 0, i * scale, size);
g2d.drawLine(0, i * scale, size, i * scale);
}
// draw the rectangle
g2d.setPaint(Color.RED);
g2d.drawPolygon(scaledPoints.stream().mapToInt(p -> p.x).toArray(),
scaledPoints.stream().mapToInt(p -> p.y).toArray(),
scaledPoints.size());
// draw the points
g2d.setPaint(Color.BLUE);
// origin
g2d.fillRect(translate, translate, pointSize, pointSize);
g2d.drawString("(0, 0)", translate, translate);
// data
for (int i = 0; i < dataPoints.size(); i++) {
Point sp = scaledPoints.get(i);
Point dp = dataPoints.get(i);
g2d.fillRect(sp.x, sp.y, pointSize, pointSize);
g2d.drawString("(" + dp.x + ", " + dp.y + ")", sp.x, sp.y);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setContentPane(new Graph());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
And another:
You might want to have the points aligned on the grid intersections and not below and to the right of them. I trust you will figure this one out.
Also, I ordered the points so that drawPolygon will paint the lines in the correct order. If your points are arbitrarily arranged, look for ways to find the outline. If you want lines between all points like in your example, iterate over all combinations of them with drawLine.

Algorithm to verify if a shape is inside another - javafx

I have a rectangular and circle. I need to verify whether a rectangle is inside that circle.
I tried to Shape.intersects but intersects is checked the number 1.
Does anyone know this kind of algorithm in javafx?
Just to exemplifly, in the figure only rectangles 1, 2, 3, and 4 are inside the circle.
thanks for your help.
Solution
The basic idea behind this solution is that any polygon is contained within any convex (see comments) shape iff every point within the polygon is within the shape. The intersects() method that you're attempting to use returns true if at least one point of the polygon is within the shape. You've already figured out that it'll work, but it'll also offer false positives for any partially-intersected shapes. To fix it, we define our own intersection test which looks at all points.
This can be generalized to scan any given polygon for "total intersection" with any given shape:
public boolean totalIntersects(Polygon poly, Shape testShape) {
List<Point> points = flatDoublesToPoints(poly.getPoints());
boolean inside = true; // If this is false after testing all points, the poly has at least one point outside of the shape.
for(Point point : points) {
if(!testShape.intersects(point.x, point.y, 1, 1)) { // The 3rd and 4th parameters here are "width" and "height". 1 for a point.
inside = false;
}
}
return inside;
}
where flatDoublesToPoints() and Point are defined as:
private List<Point> flatDoublesToPoints(List<Double> flatDoubles) {
List<Point> points = new ArrayList<>();
for(int i = 0; i < flatDoubles.size(); i += 2) {
points.add(new Point(flatDoubles.get(i), flatDoubles.get(i + 1)));
}
return points;
}
class Point {
public double x, y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
flatDoublesToPoints() is needed to split the "flat" {x1, y1, x2, y2, x3, y3...} polygon lists into a more easy-to-understand data structure. If you're doing tons of comparisons, it may be helpful to skip this step, however, and operate on the "flat list" directly for memory reasons.
Application
The following applies the other methods to a situation extremely similar to yours. (Not exact, because I didn't have your code.)
public class Main extends Application {
public static final int SIZE = 600;
#Override
public void start(Stage primaryStage) throws Exception {
Pane rootPane = new Pane();
List<Rectangle> rects = new ArrayList<>();
for (int j = 0; j < 2; j++) {
for(int i = 0; i < 5; i++) {
Rectangle r = new Rectangle(i * 100, j == 0 ? 0 : 300, 100, 200);
r.setFill(Color.BEIGE);
r.setStroke(Color.BLACK);
rects.add(r);
}
}
rootPane.getChildren().addAll(rects);
Circle circle = new Circle(350, 100, 200);
circle.setStroke(Color.BLACK);
circle.setFill(null);
rootPane.getChildren().add(circle);
List<Polygon> polys = new ArrayList<>();
for(Rectangle rect : rects) {
polys.add(rectangleToPolygon(rect));
}
List<Polygon> intersects = getTotalIntersections(polys, circle);
System.out.println(intersects);
primaryStage.setScene(new Scene(rootPane, SIZE, SIZE));
primaryStage.show();
}
public List<Polygon> getTotalIntersections(List<Polygon> polys, Shape testShape) {
List<Polygon> intersections = new ArrayList<>();
for(Polygon poly : polys) {
if(totalIntersects(poly, testShape)) {
intersections.add(poly);
}
}
return intersections;
}
public static Polygon rectangleToPolygon(Rectangle rect) {
double[] points = {rect.getX(), rect.getY(),
rect.getX() + rect.getWidth(), rect.getY(),
rect.getX() + rect.getWidth(), rect.getY() + rect.getHeight(),
rect.getX(), rect.getY() + rect.getHeight()};
return new Polygon(points);
}
public static void main(String[] args) {
Main.launch(args);
}
}
This code will print the following:
[Polygon[points=[200.0, 0.0, 300.0, 0.0, 300.0, 200.0, 200.0, 200.0], fill=0x000000ff], Polygon[points=[300.0, 0.0, 400.0, 0.0, 400.0, 200.0, 300.0, 200.0], fill=0x000000ff], Polygon[points=[400.0, 0.0, 500.0, 0.0, 500.0, 200.0, 400.0, 200.0], fill=0x000000ff]]
Which is your three polygons labeled 2, 3, and 4.
I don't think that JavaFX will have some special methods for this case.
To draw that circle you need coordinates (X_c, Y_c) of center and radius (R).
To draw rectangles you need to have coordinates ((X_1, Y_1), (X_2, Y_2) etc.) of angle points.
Then all you need is to check if all points of the rectangle is inside of the circle:
(X_1 - X_c)^2 + (Y_1 - Y_c)^2 < R^2
(X_2 - X_c)^2 + (Y_2 - Y_c)^2 < R^2
...
Try this :
import javafx.geometry.Point2D;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
/*
Check if a rectangle is contained with in a circle by checking
all rectangle corners.
For the rectangle to be contained in a circle, all its corners should be
in a distance smaller or equal to the circle's radius, from the circle's center.
Note:
Requires some more testing. I tested only a few test cases.
I am not familiar with javafx. This solution does not take into
calculation rectangle's arc or other attributes I may not be aware of.
*/
public class Test{
//apply
public static void main(String[] args){
Circle circle = new Circle(0 ,0, 100);
Rectangle rec = new Rectangle(0, 0, 50 , 50);
System.out.println("Is rectungle inside the circle ? "
+ isContained(circle,rec));
}
//check if rectangle is contained within a circle
private static boolean isContained(Circle circle,Rectangle rec) {
boolean isInside = true;
//get circle center & radius
Point2D center = new Point2D(circle.getCenterX(), circle.getCenterY());
double radius= circle.getRadius();
Point2D[] corners = getRectangleCorners(rec);
for(Point2D corner : corners) {
//if any corner falls outside the circle
//the rectangle is not contained in the circle
if(distanceBetween2Points(corner, center) > radius) {
return false;
}
}
return isInside;
}
//calculate distance between two points
//(updated a per fabian's suggestion)
private static double distanceBetween2Points
(Point2D corner, Point2D center) {
return corner.distance(center);
}
private static Point2D[] getRectangleCorners(Rectangle rec) {
Point2D[] corners = new Point2D[4];
corners[0] = new Point2D(rec.getX(), rec.getY());
corners[1] = new Point2D(rec.getX()+ rec.getWidth() , rec.getY());
corners[2] = new Point2D(rec.getX()+ rec.getWidth(), rec.getY()+ rec.getHeight());
corners[3] = new Point2D(rec.getX(), rec.getY()+ rec.getHeight());
return corners;
}
}
There is a working simple solution here : https://stackoverflow.com/a/8721483/1529139
Copy-paste here:
class Boundary {
private final Point[] points; // Points making up the boundary
...
/**
* Return true if the given point is contained inside the boundary.
* See: http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
* #param test The point to check
* #return true if the point is inside the boundary, false otherwise
*
*/
public boolean contains(Point test) {
int i;
int j;
boolean result = false;
for (i = 0, j = points.length - 1; i < points.length; j = i++) {
if ((points[i].y > test.y) != (points[j].y > test.y) &&
(test.x < (points[j].x - points[i].x) * (test.y - points[i].y) / (points[j].y-points[i].y) + points[i].x)) {
result = !result;
}
}
return result;
}
}

Drawing using Graphics java [duplicate]

I need to:
1.) move the origin and also rotate the coordinate plane so that x-values progress rightward and y-values progress upward from the new origin(which needs to be the bottom left corner of the inner, blue rectangle in the code below). This will enable me to plot points at x,y coordinate pairs in the code below.
2.) plot rotated labels for the tic marks on the y-axis of the data plot.
The code below sets up this problem. It works, except for two problems:
1.) the data points are being plotted with the upper left hand corner as the origin and y-values descending downward
2.) the labels for the tic marks on the y-axis are not being drawn on the screen
Can anyone show me how to fix the code below so that it fixes these two problems and does what the first paragraph above describes?
The code is in the following two java files:
DataGUI.java
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
class DataGUI extends JFrame{
DataGUI() {
super("X,Y Plot");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(800, 400));
this.pack();
this.setSize(new Dimension(800, 600));
this.setLocationRelativeTo(null);
setLayout(new GridLayout());
ArrayList<Double> myDiffs = new ArrayList<Double>();
myDiffs.add(25.0);
myDiffs.add(9.0);
myDiffs.add(7.0);
myDiffs.add(16.0);
myDiffs.add(15.0);
myDiffs.add(6.0);
myDiffs.add(2.0);
myDiffs.add(8.0);
myDiffs.add(2.0);
myDiffs.add(27.0);
myDiffs.add(14.0);
myDiffs.add(12.0);
myDiffs.add(19.0);
myDiffs.add(10.0);
myDiffs.add(11.0);
myDiffs.add(8.0);
myDiffs.add(19.0);
myDiffs.add(2.0);
myDiffs.add(16.0);
myDiffs.add(5.0);
myDiffs.add(18.0);
myDiffs.add(23.0);
myDiffs.add(9.0);
myDiffs.add(4.0);
myDiffs.add(8.0);
myDiffs.add(9.0);
myDiffs.add(3.0);
myDiffs.add(3.0);
myDiffs.add(9.0);
myDiffs.add(13.0);
myDiffs.add(17.0);
myDiffs.add(7.0);
myDiffs.add(0.0);
myDiffs.add(2.0);
myDiffs.add(3.0);
myDiffs.add(33.0);
myDiffs.add(23.0);
myDiffs.add(26.0);
myDiffs.add(12.0);
myDiffs.add(12.0);
myDiffs.add(19.0);
myDiffs.add(14.0);
myDiffs.add(9.0);
myDiffs.add(26.0);
myDiffs.add(24.0);
myDiffs.add(13.0);
myDiffs.add(19.0);
myDiffs.add(2.0);
myDiffs.add(7.0);
myDiffs.add(28.0);
myDiffs.add(15.0);
myDiffs.add(2.0);
myDiffs.add(5.0);
myDiffs.add(17.0);
myDiffs.add(2.0);
myDiffs.add(16.0);
myDiffs.add(19.0);
myDiffs.add(2.0);
myDiffs.add(31.0);
DataPanel myPP = new DataPanel(myDiffs,this.getHeight(),this.getWidth());
this.add(myPP);
this.setVisible(true);// Display the panel.
}
public static void main(String[] args){
DataGUI myDataGUI = new DataGUI();
myDataGUI.setVisible(true);
}
}
DataPanel.java (Note: I edited the code below to include trashgod's suggestions, but it still does not work.)
import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;
class DataPanel extends JPanel {
Insets ins; // holds the panel's insets
ArrayList<Double> myDiffs;
double maxDiff = Double.NEGATIVE_INFINITY;
double minDiff = Double.POSITIVE_INFINITY;
double maxPlot;
DataPanel(ArrayList<Double> Diffs, int h, int w){
setOpaque(true);// Ensure that panel is opaque.
setPreferredSize(new Dimension(w, h));
setMinimumSize(new Dimension(w, h));
setMaximumSize(new Dimension(w, h));
myDiffs = Diffs;
repaint();
this.setVisible(true);
}
protected void paintComponent(Graphics g){// Override paintComponent() method.
super.paintComponent(g);
//get data about plotting environment and about text
int height = getHeight();
int width = getWidth();
ins = getInsets();
Graphics2D g2d = (Graphics2D)g;
FontMetrics fontMetrics = g2d.getFontMetrics();
String xString = ("x-axis label");
int xStrWidth = fontMetrics.stringWidth(xString);
int xStrHeight = fontMetrics.getHeight();
String yString = "y-axis label";
int yStrWidth = fontMetrics.stringWidth(yString);
int yStrHeight = fontMetrics.getHeight();
String titleString ="Title of Graphic";
int titleStrWidth = fontMetrics.stringWidth(titleString);
int titleStrHeight = fontMetrics.getHeight();
int leftMargin = ins.left;
//set parameters for inner rectangle
int hPad=10;
int vPad = 6;
int testLeftStartPlotWindow = ins.left+5+(3*yStrHeight);
int testInnerWidth = width-testLeftStartPlotWindow-ins.right-hPad;
getMaxMinDiffs();
getMaxPlotVal();
double increment = 5.0;
int numTicks = (int)(maxPlot/increment);//will use numTicks for: remainder, leftStartPlotWindow, innerRectangle+labels+tickmarks
int remainder = testInnerWidth%numTicks;
int leftStartPlotWindow = testLeftStartPlotWindow-remainder;
System.out.println("remainder is: "+remainder);
int bottomPad = (3*xStrHeight)-vPad;
int blueTop = ins.bottom+(vPad/2)+titleStrHeight;
int blueHeight = height-bottomPad-blueTop;
int blueWidth = blueHeight;
int blueBottom = blueHeight+blueTop;
//plot outer rectangle
g.setColor(Color.red);
int redWidth = width-leftMargin-1;
g.drawRect(leftMargin, ins.bottom, redWidth, height-ins.bottom-1);
//write top label
g.setColor(Color.black);
g.drawString(titleString, leftStartPlotWindow+((blueWidth/2)-(titleStrWidth/2)), titleStrHeight);
// fill, then plot, inner rectangle
g.setColor(Color.white);
g.fillRect(leftStartPlotWindow, blueTop, blueWidth, blueHeight);
g.setColor(Color.blue);
g.drawRect(leftStartPlotWindow, blueTop, blueWidth, blueHeight);
//scale the diffs to fit window
double Scalar = blueWidth/maxPlot;
ArrayList<Double> scaledDiffs = new ArrayList<Double>();
for(int e = 0;e<myDiffs.size();e++){scaledDiffs.add(myDiffs.get(e)*Scalar);}
//plot the scaled Diffs
AffineTransform at = g2d.getTransform();//save the graphics context's transform
g2d.translate(leftStartPlotWindow, blueTop);//translate origin to bottom-left corner of blue rectangle
g2d.scale(1, -1);//invert the y-axis
for(int w = 0;w<scaledDiffs.size();w++){
if(w>0){
double prior = scaledDiffs.get(w-1);
int priorInt = (int)prior;
double current = scaledDiffs.get(w);
int currentInt = (int)current;
g2d.drawOval(priorInt, currentInt, 4, 4);
}
}
g2d.setTransform(at);//restore the transform for conventional rendering
//write x-axis label
g.setColor(Color.red);
g.drawString(xString, leftStartPlotWindow+((blueWidth/2)-(xStrWidth/2)), height-ins.bottom-vPad);
//write y-axis label
g2d.rotate(Math.toRadians(-90), 0, 0);//rotate text 90 degrees counter-clockwise
g.drawString(yString, -(height/2)-(yStrWidth/2), yStrHeight);
g2d.rotate(Math.toRadians(+90), 0, 0);//rotate text 90 degrees clockwise
// draw tick marks on x-axis
NumberFormat formatter = new DecimalFormat("#0.0");
double k = (double)blueWidth/(double)numTicks;
double iteration = 0;
for(int h=0;h<=numTicks;h++){
int xval = (int)(h*k);
g.setColor(Color.red);
g.drawLine(leftStartPlotWindow+xval, blueBottom+2, leftStartPlotWindow+xval, blueBottom+(xStrHeight/2));//draw tick marks
g.drawString(formatter.format(iteration),leftStartPlotWindow+xval-(fontMetrics.stringWidth(Double.toString(iteration))/2),blueBottom+(xStrHeight/2)+13);
iteration+=increment;
}
// draw tick marks on y-axis
iteration = 0;
for(int h=0;h<=numTicks;h++){
int yval = (int)(h*k);
g.setColor(Color.red);
g.drawLine(leftStartPlotWindow-2, blueBottom-yval, leftStartPlotWindow-(yStrHeight/2), blueBottom-yval);//draw tick marks
g2d.rotate(Math.toRadians(-90), 0, 0);//rotate text 90 degrees counter-clockwise
g.drawString(formatter.format(iteration),leftStartPlotWindow-2,blueBottom-(fontMetrics.stringWidth(Double.toString(iteration))/2));
g2d.rotate(Math.toRadians(+90), 0, 0);//rotate text 90 degrees clockwise
iteration+=increment;
}
}
void getMaxMinDiffs(){// get max and min of Diffs
for(int u = 0;u<myDiffs.size();u++){
if(myDiffs.get(u)>maxDiff){maxDiff = myDiffs.get(u);}
if(myDiffs.get(u)<minDiff){minDiff = myDiffs.get(u);}
}
}
void getMaxPlotVal(){
maxPlot = maxDiff;
maxPlot += 1;//make sure maxPlot is bigger than the max data value
while(maxPlot%5!=0){maxPlot+=1;}//make sure maxPlot is a multiple of 5
}
}
Also, as always, links to articles or tutorials on the topic are much appreciated.
One approach is shown in SineTest. In outline,
Save the graphics context's transform.
Graphics2D g2d = (Graphics2D) g;
AffineTransform at = g2d.getTransform();
Translate the origin to the center.
g2d.translate(w / 2, h / 2);
Invert the y-axis.
g2d.scale(1, -1);
Render using cartesian coordinates.
Restore the transform for conventional rendering.
g2d.setTransform(at);
Apologies for somewhat incomplete answer, but this may get your gears turning. Java draws things the way you described them: It considers the top left corner of the screen to be 0, 0 and draws x increasing to the right and y increasing downwards. If you make the line that states
g2d.drawOval(priorInt, currentInt, 4, 4);
into
g2d.drawOval(blueWidth - priorInt, blueHeight - currentInt, 4, 4);
it should yield the correct results for your first issue. I need a bit more info on the second problem to help you with that one though. Are they just off the screen or are the getting drawn over by something else? Try flipping +s and -s around to see if you can get the correct result if that is the case.

My method scale isn't working, what may be the issue?

I have been trying to scale a Shape in java, but I'm having some problems. When i try it the Shape simple dissapears... This method receives 2 points, toScale is the point that i want the shape to extend to, and p1 is the point that I clicked in the rectangle that is around the shape to select (there's a rectangle(boundingBox) surrounding the shape wheter is a polygone or a rectangle or just polylines)
Here's the scale method code:
public void scale(Point toScale, Point p1) {
Graphics g = parent.getGraphics();
int distanceToClicked = 0;
int distanceToBoundingBox = 0;
int scaleFactor = 0;
Vector<Point> pointsAux = new Vector<Point>();
Iterator<Point> it = points.iterator();
while (it.hasNext()){
Point p = it.next();
distanceToClicked = (int) Math.sqrt(Math.pow(getCentroid().getX()-p1.getX(), 2)+Math.pow(getCentroid().getY()-p1.getY(),2));
distanceToBoundingBox = (int) Math.sqrt(Math.pow(getCentroid().getX()-toScale.getX(),2)+Math.pow(getCentroid().getY()-toScale.getY(),2));
scaleFactor = distanceToClicked/distanceToBoundingBox;
p = new Point((int)p.getX()*scaleFactor,(int) p.getY()*scaleFactor);
pointsAux.add(p);
}
points.clear();
points.addAll(pointsAux);
}
public Point getCentroid(){
int sumx = 0;
int sumy = 0;
for(int i = 0; i<points.size();i++){
sumx+=points.get(i).getX();
sumy+=points.get(i).getY();
}
Point centroid = new Point(sumx/points.size(), sumy/points.size());
return centroid;
}
Any help would be appreciated
Thanks in advance, and eventually I'm sorry for the misunderstanding code
Something like that would do the trick:
public Collection<Point> scaleShape(float scale, Collection<Point> shape) {
Point centroid = getCentroid();
Collection<Point> scaledShape = new ArrayList<>(shape.size());
for (Point point : shape) {
Point diff = new Point(point.x() - centroid.x(), point.y() - centroid.y());
Point scaledPoint = new Point(
(int) (centroid.x() + scale * diff.x()),
(int) (centroid.y() + scale * diff.y()));
scaledShape.add(scaledPoint);
}
return scaledShape;
}
Basically, every points make a linear function with the centroid. Centroid's relative x = 0, while the current computed point is at relative x = 1. You want to find the point if it were at relative x = scale.

Categories

Resources