0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2024-11-27 09:50:52 -05:00

cleanup Svg.pathToVertices

This commit is contained in:
liabru 2015-04-13 00:26:16 +01:00
parent e8205f84d8
commit 7db3d281a5
2 changed files with 23 additions and 22 deletions

View file

@ -1,5 +1,5 @@
/** /**
* The `Matter.Svg` module contains methods for converting SVG images into sets of `Matter.Vertices`. * The `Matter.Svg` module contains methods for converting SVG images into an array of vector points.
* *
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js) * See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples. * and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
@ -12,13 +12,17 @@ var Svg = {};
(function() { (function() {
/** /**
* Converts an SVG path into a `Matter.Vertices` object for the given `Matter.Body`. * Converts an SVG path into an array of vector points.
* @method pathToPoints * If the input path forms a concave shape, you must decompose the result into convex parts before use.
* @param {string} path * See `Bodies.fromVertices` which provides support for this.
* Note that this function is not guaranteed to support complex paths (such as those with holes).
* @method pathToVertices
* @param {SVGPathElement} path
* @param {Number} [sampleLength=15] * @param {Number} [sampleLength=15]
* @return {Vector} points * @return {Vector} points
*/ */
Svg.pathToPoints = function(path, sampleLength) { Svg.pathToVertices = function(path, sampleLength) {
// https://github.com/wout/svg.topoly.js/blob/master/svg.topoly.js
var i, il, total, point, segment, segments, var i, il, total, point, segment, segments,
segmentsQueue, lastSegment, segmentsQueue, lastSegment,
lastPoint, segmentIndex, points = [], lastPoint, segmentIndex, points = [],
@ -26,9 +30,8 @@ var Svg = {};
sampleLength = sampleLength || 15; sampleLength = sampleLength || 15;
// prepare helpers functions
var addPoint = function(px, py, pathSegType) { var addPoint = function(px, py, pathSegType) {
// all odd-numbered path types are relative, except PATHSEG_CLOSEPATH (1) // all odd-numbered path types are relative except PATHSEG_CLOSEPATH (1)
var isRelative = pathSegType % 2 === 1 && pathSegType > 1; var isRelative = pathSegType % 2 === 1 && pathSegType > 1;
// when the last point doesn't equal the current point add the current point // when the last point doesn't equal the current point add the current point
@ -61,7 +64,7 @@ var Svg = {};
var addSegmentPoint = function(segment) { var addSegmentPoint = function(segment) {
var segType = segment.pathSegTypeAsLetter.toUpperCase(); var segType = segment.pathSegTypeAsLetter.toUpperCase();
// don't bother processing path ends // skip path ends
if (segType === 'Z') if (segType === 'Z')
return; return;
@ -85,7 +88,6 @@ var Svg = {};
break; break;
} }
// add point
addPoint(x, y, segment.pathSegType); addPoint(x, y, segment.pathSegType);
}; };
@ -95,7 +97,7 @@ var Svg = {};
// get total length // get total length
total = path.getTotalLength(); total = path.getTotalLength();
// Put all path segments in a queue // queue segments
segments = []; segments = [];
for (i = 0; i < path.pathSegList.numberOfItems; i += 1) for (i = 0; i < path.pathSegList.numberOfItems; i += 1)
segments.push(path.pathSegList.getItem(i)); segments.push(path.pathSegList.getItem(i));
@ -104,13 +106,11 @@ var Svg = {};
// sample through path // sample through path
while (length < total) { while (length < total) {
// get segment index // get segment at position
segmentIndex = path.getPathSegAtLength(length); segmentIndex = path.getPathSegAtLength(length);
// get segment
segment = segments[segmentIndex]; segment = segments[segmentIndex];
// new segment? // new segment
if (segment != lastSegment) { if (segment != lastSegment) {
while (segmentsQueue.length && segmentsQueue[0] != segment) while (segmentsQueue.length && segmentsQueue[0] != segment)
addSegmentPoint(segmentsQueue.shift()); addSegmentPoint(segmentsQueue.shift());
@ -137,7 +137,7 @@ var Svg = {};
length += sampleLength; length += sampleLength;
} }
// add remaining segments we didn't pass while sampling // add remaining segments not passed by sampling
for (i = 0, il = segmentsQueue.length; i < il; ++i) for (i = 0, il = segmentsQueue.length; i < il; ++i)
addSegmentPoint(segmentsQueue[i]); addSegmentPoint(segmentsQueue[i]);
@ -146,15 +146,14 @@ var Svg = {};
var _svgPathToAbsolute = function(path) { var _svgPathToAbsolute = function(path) {
// http://phrogz.net/convert-svg-path-to-all-absolute-commands // http://phrogz.net/convert-svg-path-to-all-absolute-commands
var x0, y0, x1, y1, x2, y2, segs = path.pathSegList, var x0, y0, x1, y1, x2, y2, segs = path.pathSegList,
x = 0, y = 0, len = segs.numberOfItems; x = 0, y = 0, len = segs.numberOfItems;
for (var i = 0; i < len; ++i) { for (var i = 0; i < len; ++i) {
var seg = segs.getItem(i), var seg = segs.getItem(i),
c = seg.pathSegTypeAsLetter; segType = seg.pathSegTypeAsLetter;
if (/[MLHVCSQTA]/.test(c)) { if (/[MLHVCSQTA]/.test(segType)) {
if ('x' in seg) x = seg.x; if ('x' in seg) x = seg.x;
if ('y' in seg) y = seg.y; if ('y' in seg) y = seg.y;
} else { } else {
@ -165,7 +164,7 @@ var Svg = {};
if ('x' in seg) x += seg.x; if ('x' in seg) x += seg.x;
if ('y' in seg) y += seg.y; if ('y' in seg) y += seg.y;
switch (c) { switch (segType) {
case 'm': case 'm':
segs.replaceItem(path.createSVGPathSegMovetoAbs(x, y), i); segs.replaceItem(path.createSVGPathSegMovetoAbs(x, y), i);
@ -203,7 +202,7 @@ var Svg = {};
} }
} }
if (c == 'M' || c == 'm') { if (segType == 'M' || segType == 'm') {
x0 = x; x0 = x;
y0 = y; y0 = y;
} }

View file

@ -48,14 +48,16 @@ var Vertices = {};
}; };
/** /**
* Parses a _simple_ SVG-style path into a `Matter.Vertices` object for the given `Matter.Body`. * Parses a string containing ordered x y pairs separated by spaces (and optionally commas),
* into a `Matter.Vertices` object for the given `Matter.Body`.
* For parsing SVG paths, see `Svg.pathToVertices`.
* @method fromPath * @method fromPath
* @param {string} path * @param {string} path
* @param {body} body * @param {body} body
* @return {vertices} vertices * @return {vertices} vertices
*/ */
Vertices.fromPath = function(path, body) { Vertices.fromPath = function(path, body) {
var pathPattern = /L?\s*([\-\d\.]+)\s*([\-\d\.]+)\s*,?/ig, var pathPattern = /L?\s*([\-\d\.]+)[\s,]*([\-\d\.]+)*/ig,
points = []; points = [];
path.replace(pathPattern, function(match, x, y) { path.replace(pathPattern, function(match, x, y) {