mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-15 07:48:29 -04:00
fixes bug if invalid arc radii are used
This commit is contained in:
parent
c3b43b753a
commit
c83cb41210
@ -255,6 +255,20 @@ public class PolygonParser {
|
|||||||
*/
|
*/
|
||||||
//CHECKSTYLE.OFF: ParameterNumberCheck
|
//CHECKSTYLE.OFF: ParameterNumberCheck
|
||||||
private void addArc(Polygon p, VectorInterface current, float rx, float ry, float rot, boolean large, boolean sweep, VectorFloat pos) {
|
private void addArc(Polygon p, VectorInterface current, float rx, float ry, float rot, boolean large, boolean sweep, VectorFloat pos) {
|
||||||
|
|
||||||
|
// if rx=0 or ry=0 add a straight line
|
||||||
|
if (rx == 0 || ry == 0) {
|
||||||
|
p.add(pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// take the absolute value of rx, ry
|
||||||
|
if (rx < 0)
|
||||||
|
rx = -rx;
|
||||||
|
if (ry < 0)
|
||||||
|
ry = -ry;
|
||||||
|
|
||||||
|
// transform the ellipse to a circle
|
||||||
Transform tr = Transform.IDENTITY;
|
Transform tr = Transform.IDENTITY;
|
||||||
if (rx != ry)
|
if (rx != ry)
|
||||||
tr = TransformMatrix.scale(1, rx / ry);
|
tr = TransformMatrix.scale(1, rx / ry);
|
||||||
@ -270,6 +284,11 @@ public class PolygonParser {
|
|||||||
// ellipse is transformed to a circle with radius r
|
// ellipse is transformed to a circle with radius r
|
||||||
float r = rx;
|
float r = rx;
|
||||||
|
|
||||||
|
// correct invalid radii
|
||||||
|
final float dist = p1.sub(p2).len();
|
||||||
|
if (dist > r * 2)
|
||||||
|
r = dist / 2;
|
||||||
|
|
||||||
double x1 = p1.getXFloat();
|
double x1 = p1.getXFloat();
|
||||||
double y1 = p1.getYFloat();
|
double y1 = p1.getYFloat();
|
||||||
double x2 = p2.getXFloat();
|
double x2 = p2.getXFloat();
|
||||||
@ -281,6 +300,7 @@ public class PolygonParser {
|
|||||||
double y2q = y2 * y2;
|
double y2q = y2 * y2;
|
||||||
double rq = r * r;
|
double rq = r * r;
|
||||||
|
|
||||||
|
try {
|
||||||
double x0A = (r * (y1 - y2) * sqrt(rq * (4 * rq - y1q + y2 * (2 * y1 - y2)) - rq * (x1q - 2 * x1 * x2 + x2q)) * sign(x1 - x2) + r * (x1 + x2) * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q))) / (2 * r * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)));
|
double x0A = (r * (y1 - y2) * sqrt(rq * (4 * rq - y1q + y2 * (2 * y1 - y2)) - rq * (x1q - 2 * x1 * x2 + x2q)) * sign(x1 - x2) + r * (x1 + x2) * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q))) / (2 * r * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)));
|
||||||
double y0A = (r * (y1 + y2) * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)) - r * sqrt(rq * (4 * rq - y1q + y2 * (2 * y1 - y2)) - rq * (x1q - 2 * x1 * x2 + x2q)) * abs(x1 - x2)) / (2 * r * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)));
|
double y0A = (r * (y1 + y2) * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)) - r * sqrt(rq * (4 * rq - y1q + y2 * (2 * y1 - y2)) - rq * (x1q - 2 * x1 * x2 + x2q)) * abs(x1 - x2)) / (2 * r * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)));
|
||||||
double x0B = (r * (x1 + x2) * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)) - r * (y1 - y2) * sqrt(rq * (4 * rq - y1q + y2 * (2 * y1 - y2)) - rq * (x1q - 2 * x1 * x2 + x2q)) * sign(x1 - x2)) / (2 * r * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)));
|
double x0B = (r * (x1 + x2) * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)) - r * (y1 - y2) * sqrt(rq * (4 * rq - y1q + y2 * (2 * y1 - y2)) - rq * (x1q - 2 * x1 * x2 + x2q)) * sign(x1 - x2)) / (2 * r * sqrt(rq * (y1q - 2 * y1 * y2 + y2q) + rq * (x1q - 2 * x1 * x2 + x2q)));
|
||||||
@ -325,6 +345,10 @@ public class PolygonParser {
|
|||||||
start += delta;
|
start += delta;
|
||||||
}
|
}
|
||||||
addArcPoint(p, lastStart, end, x0, y0, r, invert);
|
addArcPoint(p, lastStart, end, x0, y0, r, invert);
|
||||||
|
|
||||||
|
} catch (SqrtException e) {
|
||||||
|
p.add(pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//CHECKSTYLE.ON: ParameterNumberCheck
|
//CHECKSTYLE.ON: ParameterNumberCheck
|
||||||
|
|
||||||
@ -336,8 +360,13 @@ public class PolygonParser {
|
|||||||
p.add(c.transform(tr), p1.transform(tr));
|
p.add(c.transform(tr), p1.transform(tr));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double sqrt(double x) {
|
private static double sqrt(double x) throws SqrtException {
|
||||||
|
if (x > 0)
|
||||||
return Math.sqrt(x);
|
return Math.sqrt(x);
|
||||||
|
if (x > -1e-6)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
throw new SqrtException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double sign(double x) {
|
private static double sign(double x) {
|
||||||
@ -394,4 +423,6 @@ public class PolygonParser {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class SqrtException extends Exception {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ class Context {
|
|||||||
tr = Transform.IDENTITY;
|
tr = Transform.IDENTITY;
|
||||||
thickness = 1;
|
thickness = 1;
|
||||||
color = Color.BLACK;
|
color = Color.BLACK;
|
||||||
|
fill = Color.BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Context(Context parent) {
|
private Context(Context parent) {
|
||||||
@ -50,6 +51,7 @@ class Context {
|
|||||||
color = parent.color;
|
color = parent.color;
|
||||||
thickness = parent.thickness;
|
thickness = parent.thickness;
|
||||||
fontSize = parent.fontSize;
|
fontSize = parent.fontSize;
|
||||||
|
textAnchor = parent.textAnchor;
|
||||||
fillRuleEvenOdd = parent.fillRuleEvenOdd;
|
fillRuleEvenOdd = parent.fillRuleEvenOdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +130,6 @@ class Context {
|
|||||||
return fontSize;
|
return fontSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private interface AttrParser {
|
private interface AttrParser {
|
||||||
void parse(Context c, String value) throws SvgException;
|
void parse(Context c, String value) throws SvgException;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ public class SvgImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void drawPolygon(CustomShapeDescription csd, Context c, Polygon polygon) {
|
private void drawPolygon(CustomShapeDescription csd, Context c, Polygon polygon) {
|
||||||
if (c.getFilled() != null)
|
if (c.getFilled() != null && polygon.isClosed())
|
||||||
csd.addPolygon(polygon.transform(c.getTransform()), c.getThickness(), c.getFilled(), true);
|
csd.addPolygon(polygon.transform(c.getTransform()), c.getThickness(), c.getFilled(), true);
|
||||||
if (c.getColor() != null)
|
if (c.getColor() != null)
|
||||||
csd.addPolygon(polygon.transform(c.getTransform()), c.getThickness(), c.getColor(), false);
|
csd.addPolygon(polygon.transform(c.getTransform()), c.getThickness(), c.getColor(), false);
|
||||||
@ -184,10 +184,7 @@ public class SvgImporter {
|
|||||||
.add(c.v(x + width, y + height))
|
.add(c.v(x + width, y + height))
|
||||||
.add(c.v(x, y + height));
|
.add(c.v(x, y + height));
|
||||||
|
|
||||||
if (c.getFilled() != null)
|
drawPolygon(csd, c, polygon);
|
||||||
csd.addPolygon(polygon, c.getThickness(), c.getFilled(), true);
|
|
||||||
if (c.getColor() != null)
|
|
||||||
csd.addPolygon(polygon, c.getThickness(), c.getColor(), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawCircle(CustomShapeDescription csd, Element element, Context c) {
|
private void drawCircle(CustomShapeDescription csd, Element element, Context c) {
|
||||||
@ -229,10 +226,7 @@ public class SvgImporter {
|
|||||||
.add(c.v(x + rx, y - cy), c.v(x + cx, y - ry), c.v(x, y - ry))
|
.add(c.v(x + rx, y - cy), c.v(x + cx, y - ry), c.v(x, y - ry))
|
||||||
.add(c.v(x - cx, y - ry), c.v(x - rx, y - cy), c.v(x - rx, y));
|
.add(c.v(x - cx, y - ry), c.v(x - rx, y - cy), c.v(x - rx, y));
|
||||||
|
|
||||||
if (c.getFilled() != null)
|
drawPolygon(csd, c, poly);
|
||||||
csd.addPolygon(poly, c.getThickness(), c.getFilled(), true);
|
|
||||||
if (c.getColor() != null)
|
|
||||||
csd.addPolygon(poly, c.getThickness(), c.getColor(), false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,6 +278,18 @@ public class SvgImporterTest extends TestCase {
|
|||||||
.check();
|
.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testInvalidArcRadii() throws IOException, SvgException, PolygonParser.ParserException, PinException {
|
||||||
|
CustomShapeDescription custom = new SvgImporter(
|
||||||
|
in("<svg viewBox=\"0 0 200 100\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
||||||
|
"<path fill=\"none\" stroke=\"black\" stroke-width=\"3\"\n" +
|
||||||
|
" d=\"M 0,0 L 40,0 A 10,20,0,1,1,100,0 L 140,0\"/>\n" +
|
||||||
|
"</svg>")).create();
|
||||||
|
|
||||||
|
new CSDChecker(custom)
|
||||||
|
.checkPolygon("M 0,0 L 40,0 Q 40,-16.076952 44.019238,-30 Q 48.038475,-43.92305 55,-51.961525 Q 61.961525,-60 70,-60 Q 78.038475,-60 85,-51.961525 Q 91.961525,-43.92305 95.98076,-30 Q 100,-16.076952 100,-1.469576E-14 L 140,0")
|
||||||
|
.check();
|
||||||
|
}
|
||||||
|
|
||||||
public void testInkscape1() throws IOException, SvgException, PolygonParser.ParserException, PinException {
|
public void testInkscape1() throws IOException, SvgException, PolygonParser.ParserException, PinException {
|
||||||
CustomShapeDescription custom = new SvgImporter(
|
CustomShapeDescription custom = new SvgImporter(
|
||||||
in("<svg viewBox=\"0 0 200 100\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
in("<svg viewBox=\"0 0 200 100\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
||||||
@ -429,7 +441,7 @@ public class SvgImporterTest extends TestCase {
|
|||||||
ArrayList<VectorInterface> isPoints = new ArrayList<>();
|
ArrayList<VectorInterface> isPoints = new ArrayList<>();
|
||||||
polygon.traverse(isPoints::add);
|
polygon.traverse(isPoints::add);
|
||||||
|
|
||||||
//System.out.println(polygon);
|
System.out.println(polygon);
|
||||||
|
|
||||||
assertEquals("not the correct polygon size", shouldPoints.size(), isPoints.size());
|
assertEquals("not the correct polygon size", shouldPoints.size(), isPoints.size());
|
||||||
for (int i = 0; i < shouldPoints.size(); i++) {
|
for (int i = 0; i < shouldPoints.size(); i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user