diff --git a/src/path/Path.js b/src/path/Path.js index 6937f2ae..3e330780 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -1,11 +1,20 @@ -Path = PathItem.extend({ - initialize: function() { - this.base.apply(this, arguments); - }, - - statics: { - Line: Base.extend({ - initialize: function() { +Path = PathItem.extend(new function() { + var kappa = 2 / 3 * (Math.sqrt(2) - 1); + + var ovalSegments = [ + new Segment([0, 0.5], [0, kappa ], [0, -kappa]), + new Segment([0.5, 0], [-kappa, 0], [kappa, 0 ]), + new Segment([1, 0.5], [0, -kappa], [0, kappa ]), + new Segment([0.5, 1], [kappa, 0 ], [-kappa, 0]) + ]; + + return { + initialize: function() { + this.base.apply(this, arguments); + }, + + statics: { + Line: function() { var path = new Path(); if (arguments.length == 2) { path.addSegment(new Segment(arguments[0])); @@ -15,11 +24,9 @@ Path = PathItem.extend({ path.addSegment(Segment.read(arguments[2], arguments[3])); } return path; - } - }), - - Rectangle: Base.extend({ - initialize: function() { + }, + + Rectangle: function() { var path = new Path(); path.closed = true; var rectangle = Rectangle.read(arguments); @@ -28,79 +35,62 @@ Path = PathItem.extend({ path.add(rectangle[corners[i]]); } return path; - } - }), - - RoundRectangle: Base.extend(new function() { - var u = 4 / 3 * (Math.sqrt(2) - 1); - return { - initialize: function() { - var path = new Path(); - var rect, size; - if (arguments.length == 2) { - rect = new Rectangle(arguments[0]); - size = new Size(arguments[1]); - } else { - rect = new Rectangle(arguments[0], arguments[1], - arguments[2], arguments[3]); - size = new Size(arguments[4], arguments[5]); - } - size = Size.min(size, rect.size.divide(2)); - uSize = size.multiply(u); + }, - var bl = rect.bottomLeft; - path.add(bl.add(size.width, 0), null, [-uSize.width, 0]); - path.add(bl.subtract(0, size.height), [0, uSize.height], null); - - var tl = rect.topLeft; - path.add(tl.add(0, size.height), null, [0, -uSize.height]); - path.add(tl.add(size.width, 0), [-uSize.width, 0], null); - - var tr = rect.topRight; - path.add(tr.subtract(size.width, 0), null, [uSize.width, 0]); - path.add(tr.add(0, size.height), [0, -uSize.height], null); - - var br = rect.bottomRight; - path.add(br.subtract(0, size.height), null, [0, uSize.height]); - path.add(br.subtract(size.width, 0), [uSize.width, 0], null); - - path.closed = true; - return path; - } - } - }), - - Oval: Base.extend(new function() { - var u = 2 / 3 * (Math.sqrt(2) - 1); - var segments = [ - { handleOut: [0, -u], handleIn: [0, u], point: [ 0, 0.5] }, - { handleOut: [u, 0], handleIn: [-u, 0], point: [ 0.5, 0] }, - { handleOut: [0, u], handleIn: [0, -u], point: [ 1, 0.5] }, - { handleOut: [-u, 0], handleIn: [u, 0], point: [0.5, 1] } - ]; - return { - initialize: function() { - var path = new Path(); - var rect = Rectangle.read(arguments); - var topLeft = rect.topLeft; - var size = new Size(rect.width, rect.height); - for (var i = 0; i < 4; i++) { - var segment = Segment.read([segments[i]]); - segment.handleIn = segment.handleIn.multiply(size); - segment.handleOut = segment.handleOut.multiply(size); - segment.point = segment.point.multiply(size).add(topLeft); - path._segments.push(segment); - } - path.closed = true; - return path; - } - } - }), - - Circle: Base.extend({ - initialize: function() { + RoundRectangle: function() { var path = new Path(); + var rect, size; + if (arguments.length == 2) { + rect = new Rectangle(arguments[0]); + size = new Size(arguments[1]); + } else { + rect = new Rectangle(arguments[0], arguments[1], + arguments[2], arguments[3]); + size = new Size(arguments[4], arguments[5]); + } + size = Size.min(size, rect.size.divide(2)); + uSize = size.multiply(kappa * 2); + + var bl = rect.bottomLeft; + path.add(bl.add(size.width, 0), null, [-uSize.width, 0]); + path.add(bl.subtract(0, size.height), [0, uSize.height], null); + + var tl = rect.topLeft; + path.add(tl.add(0, size.height), null, [0, -uSize.height]); + path.add(tl.add(size.width, 0), [-uSize.width, 0], null); + + var tr = rect.topRight; + path.add(tr.subtract(size.width, 0), null, [uSize.width, 0]); + path.add(tr.add(0, size.height), [0, -uSize.height], null); + + var br = rect.bottomRight; + path.add(br.subtract(0, size.height), null, [0, uSize.height]); + path.add(br.subtract(size.width, 0), [uSize.width, 0], null); + + path.closed = true; + return path; + }, + + Oval: function() { + var path = new Path(); + var rect = Rectangle.read(arguments); + var topLeft = rect.topLeft; + var size = new Size(rect.width, rect.height); + for (var i = 0; i < 4; i++) { + var segment = ovalSegments[i]; + path.addSegment(new Segment( + segment.point.multiply(size).add(topLeft), + segment.handleIn.multiply(size), + segment.handleOut.multiply(size) + )); + } + path.closed = true; + return path; + }, + + Circle: function() { var center, radius; + // TODO: Have Point.read() return consumed index somehow? if (arguments.length == 3) { center = new Point(arguments[0], arguments[1]); radius = arguments[2]; @@ -108,24 +98,16 @@ Path = PathItem.extend({ center = new Point(arguments[0]); radius = arguments[1]; } - var left = center.subtract(radius, 0); - path.moveTo(left); - path.arcTo(center.add(radius, 0), true); - path.arcTo(left, true); - var last = path._segments.pop(); - path._segments[0].handleIn = last.handleIn; - path.closed = true; - return path; - } - }), - - Arc: PathItem.extend({ - initialize: function(from, through, to) { + return Path.Oval(new Rectangle(center.subtract(radius), + new Size(radius * 2, radius * 2))); + }, + + Arc: function(from, through, to) { var path = new Path(); path.moveTo(from); path.arcTo(through, to); return path; } - }) + } } });