Merge remote branch 'origin/master'

This commit is contained in:
Jonathan Puckey 2011-03-06 15:48:02 +01:00
commit 9f1bf92ecd
4 changed files with 84 additions and 8 deletions

50
src/basic/Line.js Normal file
View file

@ -0,0 +1,50 @@
var Line = this.Line = Base.extend({
initialize: function(point1, point2, infinite) {
// Convention: With 3 parameters, both points are absolute, and infinite
// controls wether the line extends beyond the defining points, meaning
// intersection outside the line segment are allowed.
// With two parameters, the 2nd parameter is a direction, and infinite
// is automatially true, since we're describing an infinite line.
point1 = Point.read(arguments, 0, 1);
point2 = Point.read(arguments, 1, 1);
if (arguments.length == 3) {
this.point = point1;
this.vector = point2.subtract(point1);
this.infinite = infinite;
} else {
this.point = point1;
this.vector = point2;
this.infinite = true;
}
},
intersect: function(line) {
var cross = this.vector.cross(line.vector);
// Epsilon tolerance
if (Math.abs(cross) <= 10e-6)
return null;
var v = line.point.subtract(this.point)
t1 = v.cross(line.vector) / cross,
t2 = v.cross(this.vector) / cross;
// Check the ranges of t parameters if the line is not allowed to
// extend beyond the definition points.
return (this.infinite || 0 <= t1 && t1 <= 1)
&& (line.infinite || 0 <= t2 && t2 <= 1)
? this.point.add(this.vector.multiply(t1)) : null;
},
getSide: function(p) {
var v1 = this.vector,
v2 = p.subtract(this.point),
ccw = v2.cross(v1);
if (ccw == 0.0) {
ccw = v2.dot(v1);
if (ccw > 0.0) {
ccw = (v2 - v1).dot(v1);
if (ccw < 0.0)
ccw = 0.0;
}
}
return ccw < 0.0 ? -1 : ccw > 0.0 ? 1 : 0;
}
});

View file

@ -31,6 +31,7 @@ var PathStyle = this.PathStyle = Base.extend(new function() {
} else {
this['_' + key] = isColor ? Color.read(arguments) : value;
}
return this;
};
fields[get] = function() {
@ -53,6 +54,7 @@ var PathStyle = this.PathStyle = Base.extend(new function() {
this[set] = function(value) {
this._style[set](value);
return this;
};
this[get] = function() {

View file

@ -187,6 +187,8 @@ var Curve = this.Curve = Base.extend({
x, y;
// Handle special case at beginning / end of curve
// TODO: Port back to Scriptographer, so 0.000000000001 won't be
// required anymore
if (t == 0 || t == 1) {
var point;
switch (type) {
@ -235,7 +237,9 @@ var Curve = this.Curve = Base.extend({
}
}
// The normal is simply the rotated tangent:
return type == 2 ? new Point(-y, x) : new Point(x, y);
// TODO: Rotate normals the other way in Scriptographer too?
// (Depending on orientation, I guess?)
return type == 2 ? new Point(y, -x) : new Point(x, y);
}
return {

View file

@ -404,9 +404,7 @@ var Path = this.Path = PathItem.extend({
// Add some tolerance for good roots, as t = 0 / 1 are added seperately
// anyhow, and we don't want joins to be added with radiuses in
// calculateBounds
// TODO: Find out about the maximum precision of these calculations.
// -32 was chosen arbitrarily.
var epsilon = Math.pow(2, -32),
var epsilon = 10e-6,
tMin = epsilon,
tMax = 1 - epsilon;
@ -543,7 +541,9 @@ var Path = this.Path = PathItem.extend({
radius = width / 2,
join = this.getStrokeJoin(),
cap = this.getStrokeCap(),
miter = this.getMiterLimit(),
// miter is relative to width. Divide it by 2 since we're
// measuring half the distance below
miter = this.getMiterLimit() * width / 2,
segments = this._segments,
length = segments.length,
closed= this.closed,
@ -552,8 +552,9 @@ var Path = this.Path = PathItem.extend({
function addBevelJoin(curve, t) {
var point = curve.getPoint(t),
normal = curve.getNormal(t).normalize(radius);
// TODO: Both required? Check other directions
bounds = bounds.include(point.add(normal));
bounds = bounds.include(point.subtract(normal));
// bounds = bounds.include(point.subtract(normal));
}
function addJoin(segment, join) {
@ -565,11 +566,30 @@ var Path = this.Path = PathItem.extend({
} else {
switch (join) {
case 'bevel':
case 'miter':
var curve = segment.getCurve();
addBevelJoin(curve, 0);
addBevelJoin(curve.getPrevious(), 1);
break;
case 'miter':
var curve2 = segment.getCurve(),
curve1 = curve2.getPrevious(),
point = curve2.getPoint(0),
normal1 = curve1.getNormal(1).normalize(radius),
normal2 = curve2.getNormal(0).normalize(radius),
// Intersect the two lines
line1 = new Line(point.add(normal1),
new Point(-normal1.y, normal1.x)),
line2 = new Line(point.subtract(normal2),
new Point(-normal2.y, normal2.x)),
corner = line1.intersect(line2);
// Now measure the distance from the segment to the
// intersection, which his half of the miter distance
if (!corner || point.getDistance(corner) > miter) {
addJoin(segment, 'bevel');
} else {
bounds = bounds.include(corner);
}
break;
}
}
}
@ -587,7 +607,7 @@ var Path = this.Path = PathItem.extend({
// For square caps, we need to step away from point in the
// direction of the tangent, which is the rotated normal
if (cap == 'square') {
point = point.add(-normal.y, normal.x);
point = point.add(normal.y, -normal.x);
}
bounds = bounds.include(point.add(normal));
bounds = bounds.include(point.subtract(normal));