I'm trying to draw Pie chart with PDFbox, but there are white lines between the slices, could anyone help me with this? is there an option for this?
Attached the code for drawing the arc that I'm using:
while (start < stop) {
List<Float> smallArc = PdfUtils.createSmallArc(a, b, radius, start, start +
2.0944 > stop ? stop : start + 2.0944);
contentStream.saveGraphicsState();
contentStream.setNonStrokingColor(components[0], components[1],
components[2]);
contentStream.moveTo(smallArc.get(0), smallArc.get(1));
contentStream.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4),
smallArc.get(5), smallArc.get(6), smallArc.get(7));
contentStream.fill();
contentStream.restoreGraphicsState();
start += 2.0944;
}
public static List<Float> createSmallArc(float x, float y, double r, double a1, double a2) {
double a = (a2 - a1) / 2;
double x4 = r * Math.cos(a);
double y4 = r * Math.sin(a);
double x1 = x4;
double y1 = -y4;
double q1 = x1 * x1 + y1 * y1;
double q2 = q1 + x1 * x4 + y1 * y4;
double k2 = 4 / 3d * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
double x2 = x1 - k2 * y1;
double y2 = y1 + k2 * x1;
double x3 = x2;
double y3 = -y2;
double ar = a + a1;
double cos_ar = Math.cos(ar);
double sin_ar = Math.sin(ar);
List<Float> list = new ArrayList<Float>();
list.add((float) (r * Math.cos(a1)) + x);
list.add((float) -(r * Math.sin(a1)) + y);
list.add((float) (x2 * cos_ar - y2 * sin_ar) + x);
list.add((float) -(x2 * sin_ar + y2 * cos_ar) + y);
list.add((float) (x3 * cos_ar - y3 * sin_ar) + x);
list.add((float) -(x3 * sin_ar + y3 * cos_ar) + y);
list.add((float) (r * Math.cos(a2)) + x);
list.add((float) -(r * Math.sin(a2)) + y);
return list;
}
Attached image of the result:
Thanks
Instead of using fill(), use the fillAndStroke() method and call setStrokingColor() with the same parameters that you used for setNonStrokingColor().
Related
I am trying to draw a certain type of polygon but i can't manage to get it to work. Are my formula wrong ? And if so, can you help me?
I want to draw a polygon using Java.awt.polygon
TMP = new Polygon();
// this.getX() and this.getY() return an int
// consider getX() and getY() as x0 and y0
int x1,x2,x3,x4;
int y1,y2,y3,y4;
x1 = (int) Math.round(this.getX() - this.getLength() * Math.cos(this.getAngle()));
y1 = (int) Math.round(this.getY() - this.getLength() * Math.sin(this.getAngle()));
x3 = (int) Math.round(x1 - this.getWidth() * Math.cos((Math.PI / 2) - this.getAngle()));
y3 = (int) Math.round(y1 + this.getWidth() * Math.sin((Math.PI/2) - this.getAngle()));
x4 = (int) Math.round(this.getX() - this.getWidth() * Math.cos((Math.PI/2) - this.getAngle()));
y4 = (int) Math.round(this.getX() + this.getWidth() * Math.sin((Math.PI/2) - this.getAngle()));
x2 = (int) Math.round((x1 + x3) / 2 + Math.cos(this.getAngle()) * this.getLength() / 2);
y2 = (int) Math.round((y1 + y3) / 2 + Math.sin(this.getAngle()) * this.getLength() / 2);
TMP.addPoint(this.getX(), this.getY());
TMP.addPoint(x1, y1);
TMP.addPoint(x2, y2);
TMP.addPoint(x3, y3);
TMP.addPoint(x4, y4);
this.setPolygon(TMP);
This is what i expect
https://i.gyazo.com/bdd8510d0128bab6347bb6c110f03c92.png
And i'm getting this
https://i.gyazo.com/55a00ae07d4f31732db12805fa592aec.png
My formulas were right. My values for length and widths were incorrect. My width was my length and mylength was my width. Sorry!
I have a Line(,) on canvas even it may be skewed, all i want to do is , to draw a new parallel line with respect to old Line(,) with equal Line Length.
Tried this one >>>>
double d = getLength(x1, y1, x2, y2);
double m = getSlope(x1, y1, x2, y2);
double r = Math.sqrt(1 + Math.pow(m, 2));
double endX = x + d / r;
double endY = y + ((d * m) / r);
return new double[]{x, y, endX, endY};
To make parallel segment, you need to build perpendicular vector of needed length.
Note that there are two solutions for both sided of segment
dx = x2 - x1
dy = y2 - y1
len = sqrt(dx*dx+dy*dy)
perpx = -dy * distance / len
perpy = dx * distance / len
// "left" line start
x1' = x1 + perpx
y1' = y1 + perpy
// "left" line end
x2' = x2 + perpx
y2' = y2 + perpy
// "right" line
x1'' = x1 - perpx
y1'' = y1 - perpy
x2'' = x2 - perpx
y2'' = y2 - perpy
Hi
I have a program where you drag and drop circles on a scene using JavaFX. I don't want circles to collide to each other so I added a collision algorithm to check that, which now works. What puzzles me is what I want to do afterwards.
If two circles overlap I want to make a vector between the middle of the two and transform the moved circle in the direction of the vector until they no longer overlap.
for (Stone stn:getCurrentScenario().getStones()) {
if (stn.circle == circle) continue;
double x1 = stn.circle.getTranslateX();
double y1 = stn.circle.getTranslateY();
double r1 = stn.circle.getRadius()+stn.circle.getStrokeWidth();
double x2 = circle.getTranslateX();
double y2 = circle.getTranslateY();
double r2 = circle.getRadius();
double distSq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double radSumSq = (r1 + r2) * (r1 + r2);
if (!(distSq != radSumSq && distSq > radSumSq)) {
System.out.println("Collision.");
// Transform "circle".
}
}
I ended up skipping the vector idea and went by angle instead. Going to keep the title if someone else runs into a similar issue:
double newX = circle.getTranslateX();
double newY = circle.getTranslateY();
for (Stone stn:getCurrentScenario().getStones()) {
if (stn.circle == circle) continue;
double x1 = stn.circle.getTranslateX();
double y1 = stn.circle.getTranslateY();
double r1 = stn.circle.getRadius()+stn.circle.getStrokeWidth();
double x2 = newX;
double y2 = newY;
double r2 = circle.getRadius();
double distSq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double radSumSq = (r1 + r2) * (r1 + r2);
if (!(distSq != radSumSq && distSq > radSumSq)) {
double angle = Math.atan2(x1-x2,y1-y2);
newX = x1 - Math.sin(angle) * (circle.getRadius() + circle.getStrokeWidth() + stn.circle.getRadius() + .01);
newY = y1 - Math.cos(angle) * (circle.getRadius() + circle.getStrokeWidth() + stn.circle.getRadius() + .01);
}
}
for (Stone stn:getCurrentScenario().getStones()) {
if (stn.circle == circle) continue;
double x1 = stn.circle.getTranslateX();
double y1 = stn.circle.getTranslateY();
double r1 = stn.circle.getRadius()+stn.circle.getStrokeWidth();
double x2 = newX;
double y2 = newY;
double r2 = circle.getRadius();
double distSq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double radSumSq = (r1 + r2) * (r1 + r2);
if (!(distSq != radSumSq && distSq > radSumSq)) {
newX = oldX;
newY = oldY;
break;
}
}
circle.setTranslateX(newX);
circle.setTranslateY(newY);
I made that piece of code just to make sure that it works as intended. Going to improve it now.
I designed a simple java program viewing 3D Cube, but i do not why i guess there is something illogically in that.
the length of rib = 350
the front square depth (z axis) is 0
the back square depth (z axis) is equal to the length of rib,
but the result was very tall cube !!:
I designed a simple java program viewing 3D Cube, but i do not why i guess there is something illogically in that.
the length of rib = 350
the front square depth (z axis) is 0
the back square depth (z axis) is equal to the length of rib,
but the result was very tall cube !!:
The code:
public void paint(Graphics g){
super.paint(g);
int squareLengthRib = 350; // Ribs length
int frontSquareDepth = 0; // Z value (Depth of front square)
int backSquareDepth = frontSquareDepth + squareLengthRib; // Z value (Depth of back square)
x1 = 300;
y1 = 300;
z1 = frontSquareDepth;
x2 = x1 + squareLengthRib;
y2 = y1 ;
z2 = z1;
x3 = x2;
y3 = y2 + squareLengthRib;
z3 = z2;
x4 = x1;
y4 = y3;
z4 = z3;
/**********************************************/
x5 = x1;
y5 = y1;
z5 = backSquareDepth;
x6 = x2;
y6 = y2;
z6 = z5;
x7 = x3;
y7 = y3;
z7 = z6;
x8 = x4;
y8 = y4;
z8 = z7;
PerspectiveProjection();
g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
g.drawLine((int)x2, (int)y2, (int)x3, (int)y3);
g.drawLine((int)x3, (int)y3, (int)x4, (int)y4);
g.drawLine((int)x4, (int)y4, (int)x1, (int)y1);
g.drawLine((int)x5, (int)y5, (int)x6, (int)y6);
g.drawLine((int)x6, (int)y6, (int)x7, (int)y7);
g.drawLine((int)x7, (int)y7, (int)x8, (int)y8);
g.drawLine((int)x8, (int)y8, (int)x5, (int)y5);
g.drawLine((int)x1, (int)y1, (int)x5, (int)y5);
g.drawLine((int)x2, (int)y2, (int)x6, (int)y6);
g.drawLine((int)x3, (int)y3, (int)x7, (int)y7);
g.drawLine((int)x4, (int)y4, (int)x8, (int)y8);
}
private void PerspectiveProjection() {
double d = 100;
double xd, yd;
xd = (x1 * d) / (z1 + d);
yd = (y1 * d) / (z1 + d);
x1 = xd;
y1 = yd;
xd = (x2 * d) / (z2 + d);
yd = (y2 * d) / (z2 + d);
x2 = xd;
y2 = yd;
xd = (x3 * d) / (z3 + d);
yd = (y3 * d) / (z3 + d);
x3 = xd;
y3 = yd;
xd = (x4 * d) / (z4 + d);
yd = (y4 * d) / (z4 + d);
x4 = xd;
y4 = yd;
xd = (x5 * d) / (z5 + d);
yd = (y5 * d) / (z5 + d);
x5 = xd;
y5 = yd;
xd = (x6 * d) / (z6 + d);
yd = (y6 * d) / (z6 + d);
x6 = xd;
y6 = yd;
xd = (x7 * d) / (z7 + d);
yd = (y7 * d) / (z7 + d);
x7 = xd;
y7 = yd;
xd = (x8 * d) / (z8 + d);
yd = (y8 * d) / (z8 + d);
x8 = xd;
y8 = yd;
}
Can anyone guide me how to code the arrow line in different direction.
wa and wl is positive the rectangle will be on top of the x-axis. Below example shown if wl is negative and wa is positive. The code below shown how i code the rectangle shape. x1 is the varaible to state where to start at x axis. e1 is the length of the shape, wa1 and wl1 is the height. wsign to determine the height wa1 or wl1 should display at negative side or positive side.
if (Math.abs(wl1) > Math.abs(wa1)) {
y_scale = (load_y0 - 40) / (double) Math.abs(wl1);
} else {
y_scale = (load_y0 - 40) / (double) Math.abs(wa1);
}
g.drawLine((int) ((double) x0 + x1 * x_scale), (int) (load_y),
(int) ((double) x0 + x1 * x_scale),
(int) (load_y + (wa1 * y_scale) * -1));
g.drawLine((int) ((double) x0 + (x1 + e1) * x_scale),
(int) (load_y), (int) ((double) x0 + (x1 + e1)
* x_scale), (int) (load_y + (wl1 * y_scale)
* -1));
g.drawLine((int) ((double) x0 + x1 * x_scale),
(int) (load_y + (wa1 * y_scale * -1)),
(int) ((double) x0 + (x1 + e1) * x_scale),
(int) (load_y + (wl1 * y_scale) * -1));
Here is a simple routine (adopted from here) for drawing arbitrary arrows:
import static java.awt.geom.AffineTransform.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
public class Main {
public static void main(String args[]) {
JFrame t = new JFrame();
t.add(new JComponent() {
private final int ARR_SIZE = 4;
void drawArrow(Graphics g1, int x1, int y1, int x2, int y2) {
Graphics2D g = (Graphics2D) g1.create();
double dx = x2 - x1, dy = y2 - y1;
double angle = Math.atan2(dy, dx);
int len = (int) Math.sqrt(dx*dx + dy*dy);
AffineTransform at = AffineTransform.getTranslateInstance(x1, y1);
at.concatenate(AffineTransform.getRotateInstance(angle));
g.transform(at);
// Draw horizontal arrow starting in (0, 0)
g.drawLine(0, 0, len, 0);
g.fillPolygon(new int[] {len, len-ARR_SIZE, len-ARR_SIZE, len},
new int[] {0, -ARR_SIZE, ARR_SIZE, 0}, 4);
}
public void paintComponent(Graphics g) {
for (int x = 15; x < 200; x += 16)
drawArrow(g, x, x, x, 150);
drawArrow(g, 30, 300, 300, 190);
}
});
t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.setSize(400, 400);
t.setVisible(true);
}
}
Result:
Simple arrow sample
/**
* #param fromPoint end of the arrow
* #param rotationDeg rotation angle of line
* #param length arrow length
* #param wingsAngleDeg wingspan of arrow
* #return Path2D arrow shape
*/
public static Path2D createArrowForLine(
Point2D fromPoint,
double rotationDeg,
double length,
double wingsAngleDeg) {
double ax = fromPoint.getX();
double ay = fromPoint.getY();
double radB = Math.toRadians(-rotationDeg + wingsAngleDeg);
double radC = Math.toRadians(-rotationDeg - wingsAngleDeg);
Path2D resultPath = new Path2D.Double();
resultPath.moveTo(length * Math.cos(radB) + ax, length * Math.sin(radB) + ay);
resultPath.lineTo(ax, ay);
resultPath.lineTo(length * Math.cos(radC) + ax, length * Math.sin(radC) + ay);
return resultPath;
}