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:
parent
e8205f84d8
commit
7db3d281a5
2 changed files with 23 additions and 22 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue