Implement correct checks for primitives (rect, ellipse, circle).

This commit is contained in:
Jürg Lehni 2012-11-06 01:22:16 -08:00
parent a6d19ac681
commit 4c51544b6e
3 changed files with 41 additions and 27 deletions

View file

@ -487,7 +487,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
getRotation: function() { getRotation: function() {
var angle1 = -Math.atan2(this._b, this._d), var angle1 = -Math.atan2(this._b, this._d),
angle2 = Math.atan2(this._c, this._a); angle2 = Math.atan2(this._c, this._a);
return Math.abs(angle1 - angle2) < Numerical.TOLERANCE return Math.abs(angle1 - angle2) < Numerical.EPSILON
? angle1 * 180 / Math.PI : undefined; ? angle1 * 180 / Math.PI : undefined;
}, },

View file

@ -15,7 +15,8 @@
*/ */
Path.inject({ statics: new function() { Path.inject({ statics: new function() {
var kappa = 2 / 3 * (Math.sqrt(2) - 1); // Kappa, see: http://www.whizkidtech.redprince.net/bezier/circle/kappa/
var kappa = 2 * (Math.sqrt(2) - 1) / 3;
var ovalSegments = [ var ovalSegments = [
new Segment([0, 0.5], [0, kappa ], [0, -kappa]), new Segment([0, 0.5], [0, kappa ], [0, -kappa]),

View file

@ -224,44 +224,57 @@ var SvgExporter = this.SvgExporter = new function() {
} }
function determineType(path, segments) { function determineType(path, segments) {
function isOrthogonal(i) {
var segment = segments[i],
point = segment.getPoint();
return Numerical.isZero(90 - Math.abs(
segment.getNext().getPoint().subtract(point).getAngle(
segment.getPrevious().getPoint().subtract(point))));
}
// Kappa, see: http://www.whizkidtech.redprince.net/bezier/circle/kappa/
var kappa = 4 * (Math.sqrt(2) - 1) / 3;
function isArc(i) {
var segment = segments[i],
next = segment.getNext(),
handle1 = segment.getHandleOut(),
handle2 = next.getHandleIn();
if (Numerical.isZero(90 - Math.abs(handle1.getAngle(handle2)))) {
var from = segment.getPoint(),
to = next.getPoint(),
corner = new Line(from, handle1).intersect(new Line(to, handle2));
return Numerical.isZero(handle1.length / corner.subtract(from).length - kappa)
&& Numerical.isZero(handle2.length / corner.subtract(to).length - kappa);
}
}
// See if actually have any curves in the path. Differentiate // See if actually have any curves in the path. Differentiate
// between straight objects (line, polyline, rect, and polygon) and // between straight objects (line, polyline, rect, and polygon) and
// objects with curves(circle, ellipse, roundedRectangle). // objects with curves(circle, ellipse, roundedRectangle).
if (path.isPolygon()) { if (path.isPolygon()) {
// If the distance between (point0 and point1) and (point2 and return segments.length === 4 && path._closed && isOrthogonal(0)
// point3) are equal, then it is a rectangle && isOrthogonal(1) && isOrthogonal(2) && isOrthogonal(3)
return segments.length == 4 && Numerical.isZero(
getDistance(segments, 0, 1) - getDistance(segments, 3, 2))
? 'rect' ? 'rect'
: segments.length >= 3 : segments.length >= 3
? path._closed ? 'polygon' : 'polyline' ? path._closed ? 'polygon' : 'polyline'
: 'line'; : 'line';
} else { } else if (path._closed) {
if (segments.length == 8) { if (segments.length === 8) {
// If the distance between (point0 and point3) and (point7 and // If the distance between (point0 and point3) and (point7 and
// point4) are equal then it is a roundedRectangle // point4) are equal then it is a roundedRectangle
if (Numerical.isZero( if (Numerical.isZero(
getDistance(segments, 0, 3) - getDistance(segments, 7, 5))) getDistance(segments, 0, 3) - getDistance(segments, 7, 5)))
return 'roundrect'; return 'roundrect';
} else if (segments.length == 4) { } else if (segments.length === 4
// Check if the values of the point have values similar to && isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
// circles and ellipses. // If the distance between (point0 and point2) and (point1
var checkPointValues = true; // and point3) are equal, then it is a circle
for (var i = 0; i < segments.length && checkPointValues; i++) { return Numerical.isZero(getDistance(segments, 0, 2)
var handleIn = segments[i]._handleIn, - getDistance(segments, 1, 3))
handleOut = segments[i]._handleOut; ? 'circle'
checkPointValues = !handleIn.isZero() : 'ellipse';
&& Numerical.isZero(Math.abs(handleIn._x) - Math.abs(handleOut._x))
&& Numerical.isZero(Math.abs(handleIn._y) - Math.abs(handleOut._y));
}
if (checkPointValues) {
// If the distance between (point0 and point2) and (point1
// and point3) are equal, then it is a circle
return Numerical.isZero(getDistance(segments, 0, 2)
- getDistance(segments, 1, 3))
? 'circle'
: 'ellipse';
}
} }
} }
return 'path'; return 'path';