1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-26 17:54:52 +02:00

curve moulding

This commit is contained in:
Pomax
2016-01-06 23:02:36 -08:00
parent f79fb75769
commit c8c6a3504c
12 changed files with 1301 additions and 97 deletions

View File

@@ -63,9 +63,15 @@
var React = __webpack_require__(9); var React = __webpack_require__(9);
var ReactDOM = __webpack_require__(166); var ReactDOM = __webpack_require__(166);
var Article = __webpack_require__(167); var Article = __webpack_require__(167);
var style = __webpack_require__(202); var style = __webpack_require__(203);
ReactDOM.render(React.createElement(Article, null), document.getElementById("article")); ReactDOM.render(React.createElement(Article, null), document.getElementById("article"), function () {
// trigger a #hash navigation
if (window.location.hash) {
var hash = window.location.hash;
window.location.hash = hash;
}
});
/***/ }, /***/ },
/* 9 */ /* 9 */
@@ -19810,11 +19816,11 @@
tracing: __webpack_require__(199), tracing: __webpack_require__(199),
intersections: __webpack_require__(200), intersections: __webpack_require__(200),
curveintersection: __webpack_require__(201) curveintersection: __webpack_require__(201),
moulding: __webpack_require__(202)
}; };
/* /*
moulding: require("./moulding"),
pointcurves: require("./pointcurves"), pointcurves: require("./pointcurves"),
catmullconv: require("./catmullconv"), catmullconv: require("./catmullconv"),
@@ -20156,6 +20162,11 @@
fix(evt); fix(evt);
this.mx = evt.offsetX; this.mx = evt.offsetX;
this.my = evt.offsetY; this.my = evt.offsetY;
this.moving = false;
this.dragging = false;
this.down = true;
this.lpts.forEach(function (p) { this.lpts.forEach(function (p) {
if (Math.abs(_this.mx - p.x) < 10 && Math.abs(_this.my - p.y) < 10) { if (Math.abs(_this.mx - p.x) < 10 && Math.abs(_this.my - p.y) < 10) {
_this.moving = true; _this.moving = true;
@@ -20165,8 +20176,8 @@
} }
}); });
if (this.props.mouseDown) { if (this.props.onMouseDown) {
this.props.mouseDown(evt, this); this.props.onMouseDown(evt, this);
} }
}, },
@@ -20174,6 +20185,10 @@
fix(evt); fix(evt);
if (!this.props.static) { if (!this.props.static) {
if (this.down) {
this.dragging = true;
}
var found = false; var found = false;
this.lpts.forEach(function (p) { this.lpts.forEach(function (p) {
var mx = evt.offsetX; var mx = evt.offsetX;
@@ -20209,8 +20224,12 @@
} }
} }
if (this.props.mouseMove) { if (this.props.onMouseMove) {
this.props.mouseMove(evt, this); this.props.onMouseMove(evt, this);
}
if (this.dragging && this.props.onMouseDrag) {
this.props.onMouseDrag(evt, this);
} }
if (!this.playing && this.props.draw) { if (!this.playing && this.props.draw) {
@@ -20219,7 +20238,14 @@
}, },
mouseUp: function mouseUp(evt) { mouseUp: function mouseUp(evt) {
if (!this.moving) return; this.down = false;
this.dragging = false;
if (!this.moving) {
if (this.props.onMouseUp) {
this.props.onMouseUp(evt, this);
}
return;
}
this.moving = false; this.moving = false;
this.mp = false; this.mp = false;
if (this.props.onMouseUp) { if (this.props.onMouseUp) {
@@ -20231,7 +20257,7 @@
fix(evt); fix(evt);
this.mx = evt.offsetX; this.mx = evt.offsetX;
this.my = evt.offsetY; this.my = evt.offsetY;
if (this.props.onClick) { if (!this.dragging && this.props.onClick) {
this.props.onClick(evt, this); this.props.onClick(evt, this);
} }
}, },
@@ -20285,7 +20311,7 @@
setCurve: function setCurve(c) { setCurve: function setCurve(c) {
var pts = []; var pts = [];
c = Array.from(arguments); c = Array.prototype.slice.call(arguments);
c.forEach(function (nc) { c.forEach(function (nc) {
pts = pts.concat(nc.points); pts = pts.concat(nc.points);
}); });
@@ -23271,6 +23297,12 @@
dot = dx1*dx2 + dy1*dy2; dot = dx1*dx2 + dy1*dy2;
return atan2(cross, dot); return atan2(cross, dot);
}, },
// round as string, to avoid rounding errors
round: function(v, d) {
var s = '' + v;
var pos = s.indexOf(".");
return parseFloat(s.substring(0,pos+1+d));
},
dist: function(p1, p2) { dist: function(p1, p2) {
var dx = p1.x - p2.x, var dx = p1.x - p2.x,
dy = p1.y - p2.y; dy = p1.y - p2.y;
@@ -23762,6 +23794,19 @@
} }
return this._lut; return this._lut;
}, },
on: function(point, error) {
error = error || 5;
var lut = this.getLUT(), hits = [], c, t=0;
for(var i=0; i<lut.length; i++) {
c = lut[i];
if (utils.dist(c,point) < error) {
hits.push(c)
t += i / lut.length;
}
}
if(!hits.length) return false;
return t /= hits.length;
},
get: function(t) { get: function(t) {
return this.compute(t); return this.compute(t);
}, },
@@ -30101,10 +30146,6 @@
var Graphic = __webpack_require__(172); var Graphic = __webpack_require__(172);
var SectionHeader = __webpack_require__(177); var SectionHeader = __webpack_require__(177);
var map = function map(v, ds, de, ts, te) {
return ts + (v - ds) / (de - ds) * (te - ts);
};
var Tracing = React.createClass({ var Tracing = React.createClass({
displayName: "Tracing", displayName: "Tracing",
@@ -30118,6 +30159,7 @@
var curve = api.getDefaultCubic(); var curve = api.getDefaultCubic();
api.setCurve(curve); api.setCurve(curve);
api.steps = 8; api.steps = 8;
this.map = curve.getUtils().map;
}, },
generate: function generate(api, curve, offset, pad, fwh) { generate: function generate(api, curve, offset, pad, fwh) {
@@ -30129,8 +30171,8 @@
t = v / 100; t = v / 100;
d = curve.split(t).left.length(); d = curve.split(t).left.length();
pts.push({ pts.push({
x: map(t, 0, 1, 0, fwh), x: this.map(t, 0, 1, 0, fwh),
y: map(d, 0, len, 0, fwh), y: this.map(d, 0, len, 0, fwh),
d: d, d: d,
t: t t: t
}); });
@@ -30183,6 +30225,8 @@
}, },
drawColoured: function drawColoured(api, curve) { drawColoured: function drawColoured(api, curve) {
var _this = this;
api.setPanelCount(3); api.setPanelCount(3);
var w = api.getPanelWidth(); var w = api.getPanelWidth();
var h = api.getPanelHeight(); var h = api.getPanelHeight();
@@ -30215,8 +30259,8 @@
} }
ts.forEach(function (p) { ts.forEach(function (p) {
var pt = { x: map(p.t, 0, 1, 0, fwh), y: 0 }; var pt = { x: _this.map(p.t, 0, 1, 0, fwh), y: 0 };
var pd = { x: 0, y: map(p.d, 0, len, 0, fwh) }; var pd = { x: 0, y: _this.map(p.d, 0, len, 0, fwh) };
api.setColor("black"); api.setColor("black");
api.drawCircle(pt, 3, offset); api.drawCircle(pt, 3, offset);
api.drawCircle(pd, 3, offset); api.drawCircle(pd, 3, offset);
@@ -30628,7 +30672,8 @@
this.pairs = []; this.pairs = [];
this.finals = []; this.finals = [];
pairs.forEach(function (p) { pairs.forEach(function (p) {
if (p.c1.length() < 1 && p.c2.length() < 1) {
if (p.c1.length() < 0.6 && p.c2.length() < 0.6) {
return _this.finals.push(p); return _this.finals.push(p);
} }
@@ -30965,15 +31010,555 @@
/***/ }, /***/ },
/* 202 */ /* 202 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var React = __webpack_require__(9);
var Graphic = __webpack_require__(172);
var SectionHeader = __webpack_require__(177);
var abs = Math.abs;
var Moulding = React.createClass({
displayName: "Moulding",
getDefaultProps: function getDefaultProps() {
return {
title: "Moulding a curve"
};
},
setupQuadratic: function setupQuadratic(api) {
var curve = api.getDefaultQuadratic();
curve.points[0].y -= 10;
api.setCurve(curve);
},
setupCubic: function setupCubic(api) {
var curve = api.getDefaultCubic();
curve.points[2].y -= 20;
api.setCurve(curve);
api.lut = curve.getLUT(100);
},
draw: function draw(api, curve) {
api.reset();
api.drawSkeleton(curve);
api.drawCurve(curve);
var h = api.getPanelHeight();
api.setColor("black");
if (!!api.t) {
api.drawCircle(api.curve.get(api.t), 3);
api.setColor("lightgrey");
var hull = api.drawHull(curve, api.t);
var utils = api.curve.getUtils();
var A, B, C;
if (hull.length === 6) {
A = curve.points[1];
B = hull[5];
C = utils.lli4(A, B, curve.points[0], curve.points[2]);
api.setColor("lightgrey");
api.drawLine(curve.points[0], curve.points[2]);
} else if (hull.length === 10) {
A = hull[5];
B = hull[9];
C = utils.lli4(A, B, curve.points[0], curve.points[3]);
api.setColor("lightgrey");
api.drawLine(curve.points[0], curve.points[3]);
}
api.setColor("#00FF00");
api.drawLine(A, B);
api.setColor("red");
api.drawLine(B, C);
api.setColor("black");
api.drawCircle(C, 3);
api.setFill("black");
api.text("A", { x: 10 + A.x, y: A.y });
api.text("B", { x: 10 + B.x, y: B.y });
api.text("C", { x: 10 + C.x, y: C.y });
var d1 = utils.dist(A, B);
var d2 = utils.dist(B, C);
var ratio = d1 / d2;
api.text("d1 (A-B): " + utils.round(d1, 2) + ", d2 (B-C): " + utils.round(d2, 2) + ", ratio (d1/d2): " + utils.round(ratio, 4), { x: 10, y: h - 2 });
}
},
onClick: function onClick(evt, api) {
api.t = api.curve.on({ x: evt.offsetX, y: evt.offsetY }, 7);
if (api.t < 0.05 || api.t > 0.95) api.t = false;
},
markQB: function markQB(evt, api) {
this.onClick(evt, api);
if (api.t) {
var t = api.t,
t2 = 2 * t,
top = t2 * t - t2,
bottom = top + 1,
ratio = abs(top / bottom),
curve = api.curve,
A = api.A = curve.points[1],
B = api.B = curve.get(t);
api.C = curve.getUtils().lli4(A, B, curve.points[0], curve.points[2]);
api.ratio = ratio;
}
},
markCB: function markCB(evt, api) {
this.onClick(evt, api);
if (api.t) {
var t = api.t,
mt = 1 - t,
t3 = t * t * t,
mt3 = mt * mt * mt,
bottom = t3 + mt3,
top = bottom - 1,
ratio = abs(top / bottom),
curve = api.curve,
hull = curve.hull(t),
A = api.A = hull[5],
B = api.B = curve.get(t),
db = api.db = curve.derivative(t);
api.C = curve.getUtils().lli4(A, B, curve.points[0], curve.points[3]);
api.ratio = ratio;
}
},
drag: function drag(evt, api) {
if (!api.t) return;
var newB = api.newB = {
x: evt.offsetX,
y: evt.offsetY
};
// find the current ABC and ratio values:
var A = api.A;
var B = api.B;
var C = api.C;
// now that we know A, B, C and the AB:BC ratio, we can compute the new A' based on the desired B'
var newA = api.newA = {
x: newB.x - (C.x - newB.x) / api.ratio,
y: newB.y - (C.y - newB.y) / api.ratio
};
},
dragQB: function dragQB(evt, api) {
if (!api.t) return;
this.drag(evt, api);
var curve = api.curve;
api.update = [api.newA];
},
dragCB: function dragCB(evt, api) {
if (!api.t) return;
this.drag(evt, api);
// preserve struts for B when repositioning
var curve = api.curve,
hull = curve.hull(api.t),
B = api.B,
Bl = hull[7],
Br = hull[8],
dbl = { x: Bl.x - B.x, y: Bl.y - B.y },
dbr = { x: Br.x - B.x, y: Br.y - B.y },
pts = curve.points,
// find new point on s--c1
p1 = { x: api.newB.x + dbl.x, y: api.newB.y + dbl.y },
sc1 = {
x: api.newA.x - (api.newA.x - p1.x) / (1 - api.t),
y: api.newA.y - (api.newA.y - p1.y) / (1 - api.t)
},
// find new point on c2--e
p2 = { x: api.newB.x + dbr.x, y: api.newB.y + dbr.y },
sc2 = {
x: api.newA.x + (p2.x - api.newA.x) / api.t,
y: api.newA.y + (p2.y - api.newA.y) / api.t
},
// construct new c1` based on the fact that s--sc1 is s--c1 * t
nc1 = {
x: pts[0].x + (sc1.x - pts[0].x) / api.t,
y: pts[0].y + (sc1.y - pts[0].y) / api.t
},
// construct new c2` based on the fact that e--sc2 is e--c2 * (1-t)
nc2 = {
x: pts[3].x - (pts[3].x - sc2.x) / (1 - api.t),
y: pts[3].y - (pts[3].y - sc2.y) / (1 - api.t)
};
api.p1 = p1;
api.p2 = p2;
api.sc1 = sc1;
api.sc2 = sc2;
api.nc1 = nc1;
api.nc2 = nc2;
api.update = [nc1, nc2];
},
commit: function commit(evt, api) {
if (!api.t) return;
api.setCurve(api.newcurve);
api.t = false;
api.redraw();
},
drawMould: function drawMould(api, curve) {
api.reset();
api.drawSkeleton(curve);
api.drawCurve(curve);
if (api.t) {
api.npts = [curve.points[0]].concat(api.update).concat([curve.points.slice(-1)[0]]);
api.newcurve = new api.Bezier(api.npts);
api.drawCurve(api.newcurve);
api.setColor("lightgrey");
api.drawHull(api.newcurve, api.t);
api.drawLine(api.npts[0], api.npts.slice(-1)[0]);
api.drawLine(api.newA, api.C);
api.setColor("grey");
api.drawCircle(api.newB, 3);
api.drawCircle(api.newA, 3);
api.drawCircle(api.C, 3);
}
},
render: function render() {
return React.createElement(
"section",
null,
React.createElement(SectionHeader, this.props),
React.createElement(
"p",
null,
"De Casteljau's algorithm is the pivotal algorithm when it comes to Bézier curves. You can use it not just to split curves, but also to draw them efficiently (especially for high-order Bézier curves), as well as to come up with curves based on three points and a tangent. Particularly this last thing is really useful because it lets us \"mould\" a curve, by picking it up at some point, and dragging that point around to change the curve's shape."
),
React.createElement(
"p",
null,
"How does that work? Succinctly: we run de Casteljau's algorithm in reverse!"
),
React.createElement(
"p",
null,
"Let's start out with a pre-existing curve, defined by ",
React.createElement(
"i",
null,
"start"
),
", two control points, and ",
React.createElement(
"i",
null,
"end"
),
". We can mould this curve by picking a point somewhere on the curve, at some ",
React.createElement(
"i",
null,
"t"
),
" value, and the moving it to a new location and reconstructing the curve that goes through ",
React.createElement(
"i",
null,
"start"
),
", our new point with the original tangent, and ",
React.createElement(
"i",
null,
"end"
),
". In order to see how and why we can do this, let's look at some identity information for Bézier curves. There's actually a hidden goldmine of identities that we can exploit when doing Bézier operations, and this will only scratch the surface. But, in a good way!"
),
React.createElement(
"p",
null,
"In the following graphic, click anywhere on the curves to see the identity information that we'll be using to run de Casteljau in reverse (you can manipulate the curve even after picking a point. Note the \"ratio\" value when you do so: does it change?):"
),
React.createElement(
"div",
{ className: "figure" },
React.createElement(Graphic, { inline: true, preset: "abc", title: "Projections in a quadratic Bézier curve", setup: this.setupQuadratic, draw: this.draw, onClick: this.onClick }),
React.createElement(Graphic, { inline: true, preset: "abc", title: "Projections in a cubic Bézier curve", setup: this.setupCubic, draw: this.draw, onClick: this.onClick })
),
React.createElement(
"p",
null,
"So, what exactly do we see in these graphics? First off, there's the three points ",
React.createElement(
"i",
null,
"A"
),
", ",
React.createElement(
"i",
null,
"B"
),
" and ",
React.createElement(
"i",
null,
"C"
),
"."
),
React.createElement(
"p",
null,
"Point ",
React.createElement(
"i",
null,
"B"
),
" is our \"on curve\" point, A is the first \"strut\" point when running de Casteljau's algorithm in reverse; for quadratic curves, this happens to also be the curve's control point. For cubic curves, it's the \"top of the triangle\" for the struts that lead to point ",
React.createElement(
"i",
null,
"B"
),
". Point ",
React.createElement(
"i",
null,
"C"
),
", finally, is the intersection of the line that goes through ",
React.createElement(
"i",
null,
"A"
),
" and ",
React.createElement(
"i",
null,
"B"
),
" and the baseline, between our start and end points."
),
React.createElement(
"p",
null,
"There is some important identity information here: as long as we don't pick a new ",
React.createElement(
"i",
null,
"t"
),
" coordinate, the location of point ",
React.createElement(
"i",
null,
"C"
),
" on the line ",
React.createElement(
"i",
null,
"start-end"
),
" represents a fixed ratio distance. We can drag around the control points as much as we like, that point won't move at all, and if we can drag around the start or end point, C will stay at the same ratio-value. For instance, if it was located midway between start and end, it'll stay midway between start and end, even if the line segment between start and end becomes longer or shorter."
),
React.createElement(
"p",
null,
"We can also see that the distances for the lines ",
React.createElement(
"i",
null,
"d1 = A-B"
),
" and ",
React.createElement(
"i",
null,
"d2 = B-C"
),
" may vary, but the ratio between them, ",
React.createElement(
"i",
null,
"d1/d2"
),
", is a constant value. We can drag any of the start, end, or control points around as much as we like, but that value also stays the same."
),
React.createElement(
"div",
{ className: "note" },
React.createElement(
"p",
null,
"In fact, because the distance ratio is a fixed value for each point ",
React.createElement(
"i",
null,
"B"
),
", which we get by picking some ",
React.createElement(
"i",
null,
"t"
),
" value on our curve, the distance ratio is actually an identity function for Bézier curves. If we were to plot all the ratio values for all possible ",
React.createElement(
"i",
null,
"t"
),
" values for quadratic and cubic curves, we'd see two very interesting functions: asymptotic at ",
React.createElement(
"i",
null,
"t=0"
),
" and ",
React.createElement(
"i",
null,
"t=1"
),
", tending towards positive infinity, with a zero-derivative minimum at ",
React.createElement(
"i",
null,
"t=0.5"
),
"."
),
React.createElement(
"p",
null,
"Since these are ratios, we can actually express the ratio values as a function of ",
React.createElement(
"i",
null,
"t"
),
". I actually failed at coming up with the precise functions, but thanks to some help from",
React.createElement(
"a",
{ href: "http://mathoverflow.net/questions/122257/finding-the-formula-for-Bézier-curve-ratios-hull-point-point-baseline" },
"Boris Zbarsky"
),
" we can see that the ratio functions are actually remarkably simple:"
),
React.createElement(
"table",
{ style: { width: "100%", border: 0 } },
React.createElement(
"tbody",
null,
React.createElement(
"tr",
null,
React.createElement(
"td",
null,
React.createElement(
"p",
null,
"Quadratic curves:",
React.createElement("img", { className: "LaTeX SVG", src: "images/latex/3607174eca6cb8780f98cc902e2b6eab50237b3e.svg", style: { width: "11.775150000000002rem", height: "2.7rem" } })
)
),
React.createElement(
"td",
null,
React.createElement(
"p",
null,
"Cubic curves: ",
React.createElement("img", { className: "LaTeX SVG", src: "images/latex/7f5e48e56c0a0fb80040fdc84a9713c62eb2c416.svg", style: { width: "13.80015rem", height: "2.77515rem" } })
)
)
)
)
),
React.createElement(
"p",
null,
"Unfortunately, this trick only works for quadratic and cubic curves. Once we hit higher order curves, things become a lot less predictable; the \"fixed point ",
React.createElement(
"i",
null,
"C"
),
"\" is no longer fixed, moving around as we move the control points, and projections of ",
React.createElement(
"i",
null,
"B"
),
" onto the line between start and end may actually lie on that line before the start, or after the end, and there are no simple ratios that we can exploit."
)
),
React.createElement(
"p",
null,
"So, with this knowledge, let's change a curve's shape by click-dragging some part of it. The follow graphics let us click-drag somewhere on the curve, repositioning point ",
React.createElement(
"i",
null,
"B"
),
" according to a simple rule: we keep the original point ",
React.createElement(
"i",
null,
"B"
),
"'s tangent:"
),
React.createElement(
"div",
{ className: "figure" },
React.createElement(Graphic, { inline: true, preset: "moulding", title: "Moulding a quadratic Bézier curve",
setup: this.setupQuadratic, draw: this.drawMould,
onClick: this.placeMouldPoint, onMouseDown: this.markQB, onMouseDrag: this.dragQB, onMouseUp: this.commit }),
React.createElement(Graphic, { inline: true, preset: "moulding", title: "Moulding a cubic Bézier curve",
setup: this.setupCubic, draw: this.drawMould,
onClick: this.placeMouldPoint, onMouseDown: this.markCB, onMouseDrag: this.dragCB, onMouseUp: this.commit })
)
);
}
});
module.exports = Moulding;
/***/ },
/* 203 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag // style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles // load the styles
var content = __webpack_require__(203); var content = __webpack_require__(204);
if(typeof content === 'string') content = [[module.id, content, '']]; if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM // add the styles to the DOM
var update = __webpack_require__(206)(content, {}); var update = __webpack_require__(207)(content, {});
if(content.locals) module.exports = content.locals; if(content.locals) module.exports = content.locals;
// Hot Module Replacement // Hot Module Replacement
if(false) { if(false) {
@@ -30990,21 +31575,21 @@
} }
/***/ }, /***/ },
/* 203 */ /* 204 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(204)(); exports = module.exports = __webpack_require__(205)();
// imports // imports
// module // module
exports.push([module.id, "html,\nbody {\n font-family: Verdana;\n width: 100%;\n margin: 0;\n padding: 0;\n}\nbody {\n background: url(" + __webpack_require__(205) + ");\n font-size: 16px;\n}\nheader,\nsection,\nfooter {\n width: 960px;\n margin: 0 auto;\n}\nheader {\n font-family: Times;\n text-align: center;\n margin-bottom: 2rem;\n}\nheader h1 {\n font-size: 360%;\n margin: 0;\n margin-bottom: 1rem;\n}\nheader h2 {\n font-size: 125%;\n margin: 0;\n}\narticle {\n font-family: Verdana;\n width: 960px;\n height: auto;\n margin: auto;\n background: rgba(255, 255, 255, 0.74);\n border: solid rgba(255, 0, 0, 0.35);\n border-width: 0;\n border-left-width: 1px;\n padding: 1em;\n box-shadow: 25px 0px 25px 25px rgba(255, 255, 255, 0.74);\n}\na,\na:visited {\n color: #0000c8;\n text-decoration: none;\n}\nfooter {\n font-style: italic;\n margin: 2em 0 1em 0;\n background: inherit;\n}\n.ribbon {\n position: fixed;\n top: 0;\n right: 0;\n}\n.ribbon img {\n position: relative;\n z-index: 999;\n}\nnavigation {\n font-family: Georgia;\n display: block;\n width: 70%;\n margin: 0 auto;\n padding: 0;\n border: 1px solid grey;\n}\nnavigation ul {\n background: #F2F2F9;\n list-style: none;\n margin: 0;\n padding: 0.5em 1em;\n}\nnavigation ul li:nth-child(n+2):before {\n content: \"\\A7\" attr(data-number) \". \";\n}\nsection {\n margin-top: 4em;\n}\nsection p {\n text-align: justify;\n}\nsection h2[data-num] {\n border-bottom: 1px solid grey;\n}\nsection h2[data-num]:before {\n content: \"\\A7\" attr(data-num) \" \\2014 \";\n}\nsection h2 a,\nsection h2 a:active,\nsection h2 a:hover,\nsection h2 a:visited {\n text-decoration: none;\n color: inherit;\n}\ndiv.note {\n font-size: 90%;\n margin: 1em 2em;\n padding: 1em;\n border: 1px solid grey;\n background: rgba(150, 150, 50, 0.05);\n}\ndiv.note * {\n margin: 0;\n padding: 0;\n}\ndiv.note p {\n margin: 1em 0;\n}\ndiv.note div.MathJax_Display {\n margin: 1em 0;\n}\n.howtocode {\n border: 1px solid #8d94bd;\n padding: 0 1em;\n margin: 0 2em;\n overflow-x: hidden;\n}\n.howtocode h3 {\n margin: 0 -1em;\n padding: 0;\n background: #91bef7;\n padding-left: 0.5em;\n color: white;\n text-shadow: 1px 1px 0 #000000;\n cursor: pointer;\n}\n.howtocode pre {\n border: 1px solid #8d94bd;\n background: rgba(223, 226, 243, 0.32);\n margin: 0.5em;\n padding: 0.5em;\n}\nfigure {\n display: inline-block;\n border: 1px solid grey;\n background: #F0F0F0;\n padding: 0.5em 0.5em 0 0.5em;\n text-align: center;\n}\nfigure.inline {\n border: none;\n margin: 0;\n}\nfigure canvas {\n display: inline-block;\n background: white;\n border: 1px solid lightgrey;\n}\nfigure canvas:focus {\n border: 1px solid grey;\n}\nfigure figcaption {\n text-align: center;\n padding: 0.5em 0;\n font-style: italic;\n font-size: 90%;\n}\nfigure:not([class=inline]) + figure:not([class=inline]) {\n margin-top: 2em;\n}\ndiv.figure {\n display: inline-block;\n border: 1px solid grey;\n text-align: center;\n}\ngithub-issues {\n position: relative;\n display: block;\n width: 100%;\n border: 1px solid #EEE;\n border-left: 0.3em solid #e5ecf3;\n background: white;\n padding: 0 0.3em;\n width: 95%;\n margin: auto;\n min-height: 33px;\n font: 13px Helvetica, arial, freesans, clean, sans-serif;\n}\ngithub-issues github-issue + github-issue {\n margin-top: 1em;\n}\ngithub-issues github-issue h3 {\n font-size: 100%;\n background: #e5ecf3;\n margin: 0;\n position: relative;\n left: -0.5%;\n width: 101%;\n font-weight: bold;\n border-bottom: 1px solid #999;\n}\ngithub-issues github-issue a {\n position: absolute;\n top: 2px;\n right: 10px;\n padding: 0 4px;\n color: #4183C4!important;\n background: white;\n line-height: 10px;\n font-size: 10px;\n}\nimg.LaTeX {\n display: block;\n margin-left: 2em;\n}\n", ""]); exports.push([module.id, "html,\nbody {\n font-family: Verdana;\n width: 100%;\n margin: 0;\n padding: 0;\n}\nbody {\n background: url(" + __webpack_require__(206) + ");\n font-size: 16px;\n}\nheader,\nsection,\nfooter {\n width: 960px;\n margin: 0 auto;\n}\nheader {\n font-family: Times;\n text-align: center;\n margin-bottom: 2rem;\n}\nheader h1 {\n font-size: 360%;\n margin: 0;\n margin-bottom: 1rem;\n}\nheader h2 {\n font-size: 125%;\n margin: 0;\n}\narticle {\n font-family: Verdana;\n width: 960px;\n height: auto;\n margin: auto;\n background: rgba(255, 255, 255, 0.74);\n border: solid rgba(255, 0, 0, 0.35);\n border-width: 0;\n border-left-width: 1px;\n padding: 1em;\n box-shadow: 25px 0px 25px 25px rgba(255, 255, 255, 0.74);\n}\na,\na:visited {\n color: #0000c8;\n text-decoration: none;\n}\nfooter {\n font-style: italic;\n margin: 2em 0 1em 0;\n background: inherit;\n}\n.ribbon {\n position: fixed;\n top: 0;\n right: 0;\n}\n.ribbon img {\n position: relative;\n z-index: 999;\n}\nnavigation {\n font-family: Georgia;\n display: block;\n width: 70%;\n margin: 0 auto;\n padding: 0;\n border: 1px solid grey;\n}\nnavigation ul {\n background: #F2F2F9;\n list-style: none;\n margin: 0;\n padding: 0.5em 1em;\n}\nnavigation ul li:nth-child(n+2):before {\n content: \"\\A7\" attr(data-number) \". \";\n}\nsection {\n margin-top: 4em;\n}\nsection p {\n text-align: justify;\n}\nsection h2[data-num] {\n border-bottom: 1px solid grey;\n}\nsection h2[data-num]:before {\n content: \"\\A7\" attr(data-num) \" \\2014 \";\n}\nsection h2 a,\nsection h2 a:active,\nsection h2 a:hover,\nsection h2 a:visited {\n text-decoration: none;\n color: inherit;\n}\ndiv.note {\n font-size: 90%;\n margin: 1em 2em;\n padding: 1em;\n border: 1px solid grey;\n background: rgba(150, 150, 50, 0.05);\n}\ndiv.note * {\n margin: 0;\n padding: 0;\n}\ndiv.note p {\n margin: 1em 0;\n}\ndiv.note div.MathJax_Display {\n margin: 1em 0;\n}\n.howtocode {\n border: 1px solid #8d94bd;\n padding: 0 1em;\n margin: 0 2em;\n overflow-x: hidden;\n}\n.howtocode h3 {\n margin: 0 -1em;\n padding: 0;\n background: #91bef7;\n padding-left: 0.5em;\n color: white;\n text-shadow: 1px 1px 0 #000000;\n cursor: pointer;\n}\n.howtocode pre {\n border: 1px solid #8d94bd;\n background: rgba(223, 226, 243, 0.32);\n margin: 0.5em;\n padding: 0.5em;\n}\nfigure {\n display: inline-block;\n border: 1px solid grey;\n background: #F0F0F0;\n padding: 0.5em 0.5em 0 0.5em;\n text-align: center;\n}\nfigure.inline {\n border: none;\n margin: 0;\n}\nfigure canvas {\n display: inline-block;\n background: white;\n border: 1px solid lightgrey;\n}\nfigure canvas:focus {\n border: 1px solid grey;\n}\nfigure figcaption {\n text-align: center;\n padding: 0.5em 0;\n font-style: italic;\n font-size: 90%;\n}\nfigure:not([class=inline]) + figure:not([class=inline]) {\n margin-top: 2em;\n}\ndiv.figure {\n display: inline-block;\n border: 1px solid grey;\n text-align: center;\n}\ngithub-issues {\n position: relative;\n display: block;\n width: 100%;\n border: 1px solid #EEE;\n border-left: 0.3em solid #e5ecf3;\n background: white;\n padding: 0 0.3em;\n width: 95%;\n margin: auto;\n min-height: 33px;\n font: 13px Helvetica, arial, freesans, clean, sans-serif;\n}\ngithub-issues github-issue + github-issue {\n margin-top: 1em;\n}\ngithub-issues github-issue h3 {\n font-size: 100%;\n background: #e5ecf3;\n margin: 0;\n position: relative;\n left: -0.5%;\n width: 101%;\n font-weight: bold;\n border-bottom: 1px solid #999;\n}\ngithub-issues github-issue a {\n position: absolute;\n top: 2px;\n right: 10px;\n padding: 0 4px;\n color: #4183C4!important;\n background: white;\n line-height: 10px;\n font-size: 10px;\n}\nimg.LaTeX {\n display: block;\n margin-left: 2em;\n}\n", ""]);
// exports // exports
/***/ }, /***/ },
/* 204 */ /* 205 */
/***/ function(module, exports) { /***/ function(module, exports) {
/* /*
@@ -31060,13 +31645,13 @@
/***/ }, /***/ },
/* 205 */ /* 206 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
module.exports = __webpack_require__.p + "images/packed/7d3b28205544712db60d1bb7973f10f3.png"; module.exports = __webpack_require__.p + "images/packed/7d3b28205544712db60d1bb7973f10f3.png";
/***/ }, /***/ },
/* 206 */ /* 207 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
/* /*

View File

@@ -89,6 +89,11 @@ var Graphic = React.createClass({
fix(evt); fix(evt);
this.mx = evt.offsetX; this.mx = evt.offsetX;
this.my = evt.offsetY; this.my = evt.offsetY;
this.moving = false;
this.dragging = false;
this.down = true;
this.lpts.forEach(p => { this.lpts.forEach(p => {
if(Math.abs(this.mx - p.x)<10 && Math.abs(this.my - p.y)<10) { if(Math.abs(this.mx - p.x)<10 && Math.abs(this.my - p.y)<10) {
this.moving = true; this.moving = true;
@@ -98,8 +103,8 @@ var Graphic = React.createClass({
} }
}); });
if (this.props.mouseDown) { if (this.props.onMouseDown) {
this.props.mouseDown(evt, this); this.props.onMouseDown(evt, this);
} }
}, },
@@ -107,6 +112,10 @@ var Graphic = React.createClass({
fix(evt); fix(evt);
if(!this.props.static) { if(!this.props.static) {
if (this.down) {
this.dragging = true;
}
var found = false; var found = false;
this.lpts.forEach(p => { this.lpts.forEach(p => {
var mx = evt.offsetX; var mx = evt.offsetX;
@@ -140,8 +149,12 @@ var Graphic = React.createClass({
} }
} }
if (this.props.mouseMove) { if (this.props.onMouseMove) {
this.props.mouseMove(evt, this); this.props.onMouseMove(evt, this);
}
if (this.dragging && this.props.onMouseDrag) {
this.props.onMouseDrag(evt, this);
} }
if (!this.playing && this.props.draw) { if (!this.playing && this.props.draw) {
@@ -150,7 +163,14 @@ var Graphic = React.createClass({
}, },
mouseUp: function(evt) { mouseUp: function(evt) {
if(!this.moving) return; this.down = false;
this.dragging = false;
if(!this.moving) {
if (this.props.onMouseUp) {
this.props.onMouseUp(evt, this);
}
return;
}
this.moving = false; this.moving = false;
this.mp = false; this.mp = false;
if (this.props.onMouseUp) { if (this.props.onMouseUp) {
@@ -162,7 +182,7 @@ var Graphic = React.createClass({
fix(evt); fix(evt);
this.mx = evt.offsetX; this.mx = evt.offsetX;
this.my = evt.offsetY; this.my = evt.offsetY;
if (this.props.onClick) { if (!this.dragging && this.props.onClick) {
this.props.onClick(evt, this); this.props.onClick(evt, this);
} }
}, },

View File

@@ -49,7 +49,8 @@ var CurveIntersections = React.createClass({
this.pairs = []; this.pairs = [];
this.finals = []; this.finals = [];
pairs.forEach(p => { pairs.forEach(p => {
if(p.c1.length() < 1 && p.c2.length() <1) {
if(p.c1.length() < 0.6 && p.c2.length() < 0.6) {
return this.finals.push(p); return this.finals.push(p);
} }

View File

@@ -30,12 +30,12 @@ module.exports = {
tracing: require("./tracing"), tracing: require("./tracing"),
intersections: require("./intersections"), intersections: require("./intersections"),
curveintersection: require("./curveintersection") curveintersection: require("./curveintersection"),
moulding: require("./moulding")
}; };
/* /*
moulding: require("./moulding"),
pointcurves: require("./pointcurves"), pointcurves: require("./pointcurves"),
catmullconv: require("./catmullconv"), catmullconv: require("./catmullconv"),

View File

@@ -0,0 +1,320 @@
var React = require("react");
var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx");
var abs = Math.abs;
var Moulding = React.createClass({
getDefaultProps: function() {
return {
title: "Moulding a curve"
};
},
setupQuadratic: function(api) {
var curve = api.getDefaultQuadratic();
curve.points[0].y -= 10;
api.setCurve(curve);
},
setupCubic: function(api) {
var curve = api.getDefaultCubic();
curve.points[2].y -= 20;
api.setCurve(curve);
api.lut = curve.getLUT(100);
},
draw: function(api, curve) {
api.reset();
api.drawSkeleton(curve);
api.drawCurve(curve);
var h = api.getPanelHeight();
api.setColor("black");
if (!!api.t) {
api.drawCircle(api.curve.get(api.t),3);
api.setColor("lightgrey");
var hull = api.drawHull(curve, api.t);
var utils = api.curve.getUtils();
var A, B, C;
if(hull.length === 6) {
A = curve.points[1];
B = hull[5];
C = utils.lli4(A, B, curve.points[0], curve.points[2]);
api.setColor("lightgrey");
api.drawLine(curve.points[0], curve.points[2]);
} else if(hull.length === 10) {
A = hull[5]
B = hull[9];
C = utils.lli4(A, B, curve.points[0], curve.points[3]);
api.setColor("lightgrey");
api.drawLine(curve.points[0], curve.points[3]);
}
api.setColor("#00FF00");
api.drawLine(A,B);
api.setColor("red");
api.drawLine(B,C);
api.setColor("black");
api.drawCircle(C,3);
api.setFill("black");
api.text("A", {x:10 + A.x, y: A.y});
api.text("B", {x:10 + B.x, y: B.y});
api.text("C", {x:10 + C.x, y: C.y});
var d1 = utils.dist(A, B);
var d2 = utils.dist(B, C);
var ratio = d1/d2;
api.text("d1 (A-B): " + utils.round(d1,2) + ", d2 (B-C): "+ utils.round(d2,2) + ", ratio (d1/d2): " + utils.round(ratio,4), {x:10, y:h-2});
}
},
onClick: function(evt, api) {
api.t = api.curve.on({x: evt.offsetX, y: evt.offsetY},7);
if (api.t < 0.05 || api.t > 0.95) api.t = false;
},
markQB: function(evt, api) {
this.onClick(evt, api);
if(api.t) {
var t = api.t,
t2 = 2*t,
top = t2*t - t2,
bottom = top + 1,
ratio = abs(top/bottom),
curve = api.curve,
A = api.A = curve.points[1],
B = api.B = curve.get(t);
api.C = curve.getUtils().lli4(A, B, curve.points[0], curve.points[2]);
api.ratio = ratio;
}
},
markCB: function(evt, api) {
this.onClick(evt, api);
if(api.t) {
var t = api.t,
mt = (1-t),
t3 = t*t*t,
mt3 = mt*mt*mt,
bottom = t3 + mt3,
top = bottom - 1,
ratio = abs(top/bottom),
curve = api.curve,
hull = curve.hull(t),
A = api.A = hull[5],
B = api.B = curve.get(t),
db = api.db = curve.derivative(t);
api.C = curve.getUtils().lli4(A, B, curve.points[0], curve.points[3]);
api.ratio = ratio;
}
},
drag: function(evt, api) {
if (!api.t) return;
var newB = api.newB = {
x: evt.offsetX,
y: evt.offsetY
};
// find the current ABC and ratio values:
var A = api.A;
var B = api.B;
var C = api.C;
// now that we know A, B, C and the AB:BC ratio, we can compute the new A' based on the desired B'
var newA = api.newA = {
x: newB.x - (C.x - newB.x) / api.ratio,
y: newB.y - (C.y - newB.y) / api.ratio
};
},
dragQB: function(evt, api) {
if (!api.t) return;
this.drag(evt, api);
var curve = api.curve;
api.update = [api.newA];
},
dragCB: function(evt, api) {
if (!api.t) return;
this.drag(evt,api);
// preserve struts for B when repositioning
var curve = api.curve,
hull = curve.hull(api.t),
B = api.B,
Bl = hull[7],
Br = hull[8],
dbl = { x: Bl.x - B.x, y: Bl.y - B.y },
dbr = { x: Br.x - B.x, y: Br.y - B.y },
pts = curve.points,
// find new point on s--c1
p1 = {x: api.newB.x + dbl.x, y: api.newB.y + dbl.y},
sc1 = {
x: api.newA.x - (api.newA.x - p1.x)/(1-api.t),
y: api.newA.y - (api.newA.y - p1.y)/(1-api.t),
},
// find new point on c2--e
p2 = {x: api.newB.x + dbr.x, y: api.newB.y + dbr.y},
sc2 = {
x: api.newA.x + (p2.x - api.newA.x)/(api.t),
y: api.newA.y + (p2.y - api.newA.y)/(api.t)
},
// construct new c1` based on the fact that s--sc1 is s--c1 * t
nc1 = {
x: pts[0].x + (sc1.x - pts[0].x)/(api.t),
y: pts[0].y + (sc1.y - pts[0].y)/(api.t)
},
// construct new c2` based on the fact that e--sc2 is e--c2 * (1-t)
nc2 = {
x: pts[3].x - (pts[3].x - sc2.x)/(1-api.t),
y: pts[3].y - (pts[3].y - sc2.y)/(1-api.t)
};
api.p1 = p1;
api.p2 = p2;
api.sc1 = sc1;
api.sc2 = sc2;
api.nc1 = nc1;
api.nc2 = nc2;
api.update = [nc1, nc2];
},
commit: function(evt, api) {
if (!api.t) return;
api.setCurve(api.newcurve);
api.t = false;
api.redraw();
},
drawMould: function(api, curve) {
api.reset();
api.drawSkeleton(curve);
api.drawCurve(curve);
if (api.t) {
api.npts = [curve.points[0]].concat(api.update).concat([curve.points.slice(-1)[0]]);
api.newcurve = new api.Bezier(api.npts);
api.drawCurve(api.newcurve);
api.setColor("lightgrey");
api.drawHull(api.newcurve, api.t);
api.drawLine(api.npts[0], api.npts.slice(-1)[0]);
api.drawLine(api.newA, api.C);
api.setColor("grey");
api.drawCircle(api.newB, 3);
api.drawCircle(api.newA, 3);
api.drawCircle(api.C, 3);
}
},
render: function() {
return (
<section>
<SectionHeader {...this.props} />
<p>De Casteljau's algorithm is the pivotal algorithm when it comes to Bézier curves. You can use it not just to split
curves, but also to draw them efficiently (especially for high-order Bézier curves), as well as to come up with curves
based on three points and a tangent. Particularly this last thing is really useful because it lets us "mould" a curve,
by picking it up at some point, and dragging that point around to change the curve's shape.</p>
<p>How does that work? Succinctly: we run de Casteljau's algorithm in reverse!</p>
<p>Let's start out with a pre-existing curve, defined by <i>start</i>, two control points, and <i>end</i>. We can
mould this curve by picking a point somewhere on the curve, at some <i>t</i> value, and the moving it to a new
location and reconstructing the curve that goes through <i>start</i>, our new point with the original tangent,
and <i>end</i>. In order to see how and why we can do this, let's look at some identity information for Bézier
curves. There's actually a hidden goldmine of identities that we can exploit when doing Bézier operations, and
this will only scratch the surface. But, in a good way!</p>
<p>In the following graphic, click anywhere on the curves to see the identity information that we'll
be using to run de Casteljau in reverse (you can manipulate the curve even after picking a point.
Note the "ratio" value when you do so: does it change?):</p>
<div className="figure">
<Graphic inline={true} preset="abc" title="Projections in a quadratic Bézier curve" setup={this.setupQuadratic} draw={this.draw} onClick={this.onClick}/>
<Graphic inline={true} preset="abc" title="Projections in a cubic Bézier curve" setup={this.setupCubic} draw={this.draw} onClick={this.onClick}/>
</div>
<p>So, what exactly do we see in these graphics? First off, there's the three points <i>A</i>, <i>B</i> and <i>C</i>.</p>
<p>Point <i>B</i> is our "on curve" point, A is the first "strut" point when running de Casteljau's
algorithm in reverse; for quadratic curves, this happens to also be the curve's control point. For cubic
curves, it's the "top of the triangle" for the struts that lead to point <i>B</i>. Point <i>C</i>, finally,
is the intersection of the line that goes through <i>A</i> and <i>B</i> and the baseline,
between our start and end points.</p>
<p>There is some important identity information here: as long as we don't pick a new <i>t</i> coordinate,
the location of point <i>C</i> on the line <i>start-end</i> represents a fixed ratio distance. We can drag
around the control points as much as we like, that point won't move at all, and if we can drag around
the start or end point, C will stay at the same ratio-value. For instance, if it was located midway between
start and end, it'll stay midway between start and end, even if the line segment between start and end
becomes longer or shorter.</p>
<p>We can also see that the distances for the lines <i>d1 = A-B</i> and <i>d2 = B-C</i> may vary, but the
ratio between them, <i>d1/d2</i>, is a constant value. We can drag any of the start, end, or control points
around as much as we like, but that value also stays the same.</p>
<div className="note">
<p>In fact, because the distance ratio is a fixed value for each point <i>B</i>, which we get by picking
some <i>t</i> value on our curve, the distance ratio is actually an identity function for Bézier curves.
If we were to plot all the ratio values for all possible <i>t</i> values for quadratic and cubic curves,
we'd see two very interesting functions: asymptotic at <i>t=0</i> and <i>t=1</i>, tending towards positive
infinity, with a zero-derivative minimum at <i>t=0.5</i>.</p>
<p>Since these are ratios, we can actually express the ratio values as a function of <i>t</i>. I actually
failed at coming up with the precise functions, but thanks to some help from
<a href="http://mathoverflow.net/questions/122257/finding-the-formula-for-Bézier-curve-ratios-hull-point-point-baseline">Boris
Zbarsky</a> we can see that the ratio functions are actually remarkably simple:</p>
<table style={{width:"100%", border:0}}>
<tbody>
<tr>
<td>
<p>Quadratic curves:\[
ratio(t)_2 = \left | \frac{2t^2 - 2t}{2t^2 - 2t + 1} \right |
\]</p>
</td><td>
<p>Cubic curves: \[
ratio(t)_3 = \left | \frac{t^3 + (1-t)^3 - 1}{t^3 + (1-t)^3} \right |
\]</p>
</td>
</tr>
</tbody>
</table>
<p>Unfortunately, this trick only works for quadratic and cubic curves. Once we hit higher order curves,
things become a lot less predictable; the "fixed point <i>C</i>" is no longer fixed, moving around as we
move the control points, and projections of <i>B</i> onto the line between start and end may actually
lie on that line before the start, or after the end, and there are no simple ratios that we can exploit.</p>
</div>
<p>So, with this knowledge, let's change a curve's shape by click-dragging some part of it. The follow
graphics let us click-drag somewhere on the curve, repositioning point <i>B</i> according to a simple
rule: we keep the original point <i>B</i>'s tangent:</p>
<div className="figure">
<Graphic inline={true} preset="moulding" title="Moulding a quadratic Bézier curve"
setup={this.setupQuadratic} draw={this.drawMould}
onClick={this.placeMouldPoint} onMouseDown={this.markQB} onMouseDrag={this.dragQB} onMouseUp={this.commit}/>
<Graphic inline={true} preset="moulding" title="Moulding a cubic Bézier curve"
setup={this.setupCubic} draw={this.drawMould}
onClick={this.placeMouldPoint} onMouseDown={this.markCB} onMouseDrag={this.dragCB} onMouseUp={this.commit}/>
</div>
</section>
);
}
});
module.exports = Moulding;

View File

@@ -2,10 +2,6 @@ var React = require("react");
var Graphic = require("../../Graphic.jsx"); var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx"); var SectionHeader = require("../../SectionHeader.jsx");
var map = function(v, ds,de, ts,te) {
return ts + (v-ds)/(de-ds) * (te-ts);
};
var Tracing = React.createClass({ var Tracing = React.createClass({
getDefaultProps: function() { getDefaultProps: function() {
return { return {
@@ -17,6 +13,7 @@ var Tracing = React.createClass({
var curve = api.getDefaultCubic(); var curve = api.getDefaultCubic();
api.setCurve(curve); api.setCurve(curve);
api.steps = 8; api.steps = 8;
this.map = curve.getUtils().map;
}, },
generate: function(api, curve, offset, pad, fwh) { generate: function(api, curve, offset, pad, fwh) {
@@ -28,8 +25,8 @@ var Tracing = React.createClass({
t = v/100; t = v/100;
d = curve.split(t).left.length(); d = curve.split(t).left.length();
pts.push({ pts.push({
x: map(t, 0,1, 0,fwh), x: this.map(t, 0,1, 0,fwh),
y: map(d, 0,len, 0,fwh), y: this.map(d, 0,len, 0,fwh),
d: d, d: d,
t: t t: t
}); });
@@ -111,8 +108,8 @@ var Tracing = React.createClass({
} }
ts.forEach(p => { ts.forEach(p => {
var pt = { x: map(p.t,0,1,0,fwh), y: 0 }; var pt = { x: this.map(p.t,0,1,0,fwh), y: 0 };
var pd = { x: 0, y: map(p.d,0,len,0,fwh) }; var pd = { x: 0, y: this.map(p.d,0,len,0,fwh) };
api.setColor("black"); api.setColor("black");
api.drawCircle(pt, 3, offset); api.drawCircle(pt, 3, offset);
api.drawCircle(pd, 3, offset); api.drawCircle(pd, 3, offset);

View File

@@ -1,52 +0,0 @@
<p>Using de Casteljau's algorithm to split the curve we can now implement curve/curve intersection
finding using a "divide and conquer" technique: take two curves <i>C<sub>1</sub></i> and <i>C<sub>2</sub></i>,
and treat them as a pair. If their bounding boxes overlap, split up each curve into two sub-curves,
<i>C<sub>1.1</sub></i>, <i>C<sub>1.2</sub></i>, <i>C<sub>2.1</sub></i> and <i>C<sub>2.2</sub></i>,
and form four new pairs (<i>C<sub>1.1</sub></i>,<i>C<sub>2.1</sub></i>), (<i>C<sub>1.1</sub></i>,
<i>C<sub>2.2</sub></i>), (<i>C<sub>1.2</sub></i>,<i>C<sub>2.1</sub></i>), and (<i>C<sub>1.2</sub></i>,
<i>C<sub>2.2</sub></i>). If their bounding boxes do not overlap, discard the pair, as there is no
intersection between this pair of curves. If there was overlap, for each of the newly formed pairs,
perform the same evaluation. Once the sub-curves we form are so small that they effectively occupy
sub-pixel areas, we consider an intersection found.</p>
<p>This algorithm will start with a single pair, "balloon" until it runs in parallel for a large
number of potential sub-pairs, and then taper back down as it homes in on intersection coordinates,
ending up with as many pairs as there are intersections.</p>
<p>The following graphic applies this algorithm to a pair of cubic curves, slowed down so that
you can see the algorithm in action. Click the button to run the algorithm, after setting up
your curves in some creative arrangement: <button id="clippingButton">detect</button></p>
<textarea class="sketch-code" data-sketch-preset="clipping" data-sketch-title="Curve/curve intersections">
void iterate() {
if(pairs.size()==0) {
iterated = false;
drawResult();
noAnimate();
return; }
fill(0);
text("iteration "+(iterationCount++), 10,20);
newPairs.clear();
for(CurvePair cp: pairs) {
cp.draw(getColor(random(999)));
if(cp.hasOverlap()) {
if(cp.smallEnough()) { finals.add(cp); }
else {
CurvePair[] expanded = cp.splitAndCombine();
for(CurvePair ncp: expanded) {
newPairs.add(ncp);
}
}
}
}
pairs.clear();
for(CurvePair cp: newPairs) { pairs.add(cp); }
}
</textarea>
<p>Self-intersection is dealt with in the same way, except we turn a curve into two or more curves first
based on the inflection points. We then form all possible curve pairs with the resultant segments, and
run exactly the same algorithm. All non-overlapping curve pairs will be removed after the first iteration,
and the remaining steps home in on the curve's self-intersection points.</p>

View File

@@ -0,0 +1,63 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="26.167ex" height="6ex" style="vertical-align: -2.333ex; margin-left: 0ex; margin-right: 0ex; margin-bottom: 1px; margin-top: 1px;" viewBox="0 -1531.3 11230.6 2556.3" xmlns="http://www.w3.org/2000/svg">
<defs>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45F" d="M436 377c0 -36 -28 -59 -55 -59s-38 19 -38 35c0 26 22 50 52 55c0 0 -16 12 -42 12c-43 0 -72 -26 -80 -33c-24 -22 -52 -69 -56 -82l-32 -130c-4 -18 -38 -154 -40 -158c-7 -20 -25 -28 -37 -28c-15 0 -29 9 -29 27c0 5 6 28 9 43l58 231c13 52 16 63 16 84 c0 38 -14 46 -31 46c-36 0 -56 -48 -73 -119c-6 -22 -7 -23 -17 -23c0 0 -12 0 -12 10c0 3 13 63 31 97c9 18 28 57 74 57c47 0 83 -32 91 -77c19 28 63 77 128 77c51 0 83 -30 83 -65Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D44E" d="M498 143c0 0 -13 -63 -30 -99c-16 -32 -39 -55 -74 -55c-48 0 -83 33 -91 75c-60 -71 -110 -75 -130 -75c-78 0 -133 66 -133 160c0 146 124 293 241 293c45 0 74 -27 92 -64c3 22 18 44 42 44c17 0 29 -10 29 -27c0 -4 0 -6 -7 -34l-36 -140l-22 -90 c-11 -44 -13 -52 -13 -74c0 -20 3 -46 30 -46c41 0 59 59 76 124c3 14 4 18 14 18c3 0 12 0 12 -10zM361 332c0 6 -14 88 -79 88c-40 0 -85 -37 -116 -96c-23 -46 -55 -169 -55 -219c0 -39 14 -94 64 -94c28 0 69 16 113 71c15 17 15 19 20 37l50 196c1 5 3 11 3 17Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D461" d="M330 420c0 -20 -10 -20 -30 -20h-94l-74 -295c-4 -17 -6 -24 -6 -48c0 -33 10 -46 31 -46c34 0 87 24 130 128c5 11 6 14 15 14c4 0 12 0 12 -10c0 -8 -57 -154 -159 -154c-54 0 -92 38 -92 92c0 18 4 35 76 319h-88c-20 0 -28 0 -28 12c0 19 10 19 30 19h94l39 159 c9 35 37 36 40 36c17 0 29 -10 29 -27c0 -6 -5 -26 -41 -168h88c18 0 28 0 28 -11Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D456" d="M284 625c0 -30 -30 -53 -53 -53c-24 0 -38 17 -38 36c0 27 27 53 54 53c23 0 37 -16 37 -36zM293 143c0 -9 -37 -154 -131 -154c-48 0 -82 35 -82 82c0 21 13 54 23 80c16 43 61 159 69 185c4 10 11 31 11 52c0 32 -17 32 -25 32c-34 0 -74 -30 -101 -124 c-5 -16 -6 -18 -16 -18c0 0 -12 0 -12 10c0 9 38 154 132 154c50 0 82 -37 82 -82c0 -19 -5 -33 -13 -53c-10 -27 -10 -29 -22 -58l-39 -105c-23 -61 -29 -75 -29 -100c0 -23 7 -33 24 -33c51 0 84 61 102 124c5 15 5 18 15 18c3 0 12 0 12 -10Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45C" d="M469 273c0 -146 -135 -284 -268 -284c-93 0 -160 70 -160 169c0 142 134 284 268 284c90 0 160 -65 160 -169zM396 312c0 60 -30 108 -88 108c-28 0 -85 -15 -135 -92c-32 -51 -58 -159 -58 -208c0 -78 44 -109 87 -109c46 0 101 34 136 92c38 65 58 170 58 209Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-28" d="M332 -238c0 -5 -5 -10 -10 -10c-2 0 -4 1 -6 2c-110 83 -215 283 -215 454v84c0 171 105 371 215 454c2 1 4 2 6 2c5 0 10 -5 10 -10c0 -3 -2 -6 -4 -8c-104 -78 -173 -278 -173 -438v-84c0 -160 69 -360 173 -438c2 -2 4 -5 4 -8Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-29" d="M288 208c0 -171 -105 -371 -215 -454c-2 -1 -4 -2 -6 -2c-5 0 -10 5 -10 10c0 3 2 6 4 8c104 78 173 278 173 438v84c0 160 -69 360 -173 438c-2 2 -4 5 -4 8c0 5 5 10 10 10c2 0 4 -1 6 -2c110 -83 215 -283 215 -454v-84Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-32" d="M449 174l-28 -174h-371c0 24 0 26 11 37l192 214c55 62 105 141 105 221c0 82 -43 163 -134 163c-58 0 -112 -37 -135 -102c3 1 5 1 13 1c35 0 53 -26 53 -52c0 -41 -35 -53 -52 -53c-3 0 -53 0 -53 56c0 89 74 181 187 181c122 0 212 -80 212 -194 c0 -100 -60 -154 -216 -292l-106 -103h180c22 0 88 0 95 8c10 15 17 59 22 89h25Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-3D" d="M722 347c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20zM722 153c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-7C" d="M159 -230c0 -11 -9 -20 -20 -20s-20 9 -20 20v960c0 11 9 20 20 20s20 -9 20 -20v-960Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2212" d="M722 250c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2B" d="M722 250c0 -11 -9 -20 -20 -20h-293v-293c0 -11 -9 -20 -20 -20s-20 9 -20 20v293h-293c-11 0 -20 9 -20 20s9 20 20 20h293v293c0 11 9 20 20 20s20 -9 20 -20v-293h293c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-31" d="M419 0c-35 3 -122 3 -162 3s-127 0 -162 -3v31h32c90 0 93 12 93 48v518c-52 -26 -111 -26 -131 -26v31c32 0 120 0 182 64c23 0 23 -2 23 -26v-561c0 -37 3 -48 93 -48h32v-31Z"></path>
<path stroke-width="10" id="E1-LATINMODERNSIZE5-7C" d="M172 -969c0 -18 -15 -32 -33 -32s-32 14 -32 32v2438c0 18 14 32 32 32s33 -14 33 -32v-2438Z"></path>
</defs>
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D45F" x="0" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D44E" x="456" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="990" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D456" x="1356" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D45C" x="1706" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2196" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="2590" y="0"></use>
<g transform="translate(2956,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-32" x="557" y="-213"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-3D" x="4084" y="0"></use>
<g transform="translate(5145,0)">
<use xlink:href="#E1-LATINMODERNSIZE5-7C"></use>
<g transform="translate(283,0)">
<g transform="translate(120,0)">
<rect stroke="none" width="5278" height="60" x="0" y="220"></rect>
<g transform="translate(926,676)">
<use xlink:href="#E1-LATINMODERNMAIN-32" x="0" y="0"></use>
<g transform="translate(505,0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-32" x="517" y="513"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="1550" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-32" x="2555" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="3060" y="0"></use>
</g>
<g transform="translate(60,-787)">
<use xlink:href="#E1-LATINMODERNMAIN-32" x="0" y="0"></use>
<g transform="translate(505,0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-32" x="517" y="408"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="1550" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-32" x="2555" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="3060" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="3648" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="4653" y="0"></use>
</g>
</g>
</g>
<use xlink:href="#E1-LATINMODERNSIZE5-7C" x="5801" y="0"></use>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,69 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="30.667ex" height="6.167ex" style="vertical-align: -2.5ex; margin-left: 0ex; margin-right: 0ex; margin-bottom: 1px; margin-top: 1px;" viewBox="0 -1632.2 13198.2 2690.5" xmlns="http://www.w3.org/2000/svg">
<defs>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45F" d="M436 377c0 -36 -28 -59 -55 -59s-38 19 -38 35c0 26 22 50 52 55c0 0 -16 12 -42 12c-43 0 -72 -26 -80 -33c-24 -22 -52 -69 -56 -82l-32 -130c-4 -18 -38 -154 -40 -158c-7 -20 -25 -28 -37 -28c-15 0 -29 9 -29 27c0 5 6 28 9 43l58 231c13 52 16 63 16 84 c0 38 -14 46 -31 46c-36 0 -56 -48 -73 -119c-6 -22 -7 -23 -17 -23c0 0 -12 0 -12 10c0 3 13 63 31 97c9 18 28 57 74 57c47 0 83 -32 91 -77c19 28 63 77 128 77c51 0 83 -30 83 -65Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D44E" d="M498 143c0 0 -13 -63 -30 -99c-16 -32 -39 -55 -74 -55c-48 0 -83 33 -91 75c-60 -71 -110 -75 -130 -75c-78 0 -133 66 -133 160c0 146 124 293 241 293c45 0 74 -27 92 -64c3 22 18 44 42 44c17 0 29 -10 29 -27c0 -4 0 -6 -7 -34l-36 -140l-22 -90 c-11 -44 -13 -52 -13 -74c0 -20 3 -46 30 -46c41 0 59 59 76 124c3 14 4 18 14 18c3 0 12 0 12 -10zM361 332c0 6 -14 88 -79 88c-40 0 -85 -37 -116 -96c-23 -46 -55 -169 -55 -219c0 -39 14 -94 64 -94c28 0 69 16 113 71c15 17 15 19 20 37l50 196c1 5 3 11 3 17Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D461" d="M330 420c0 -20 -10 -20 -30 -20h-94l-74 -295c-4 -17 -6 -24 -6 -48c0 -33 10 -46 31 -46c34 0 87 24 130 128c5 11 6 14 15 14c4 0 12 0 12 -10c0 -8 -57 -154 -159 -154c-54 0 -92 38 -92 92c0 18 4 35 76 319h-88c-20 0 -28 0 -28 12c0 19 10 19 30 19h94l39 159 c9 35 37 36 40 36c17 0 29 -10 29 -27c0 -6 -5 -26 -41 -168h88c18 0 28 0 28 -11Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D456" d="M284 625c0 -30 -30 -53 -53 -53c-24 0 -38 17 -38 36c0 27 27 53 54 53c23 0 37 -16 37 -36zM293 143c0 -9 -37 -154 -131 -154c-48 0 -82 35 -82 82c0 21 13 54 23 80c16 43 61 159 69 185c4 10 11 31 11 52c0 32 -17 32 -25 32c-34 0 -74 -30 -101 -124 c-5 -16 -6 -18 -16 -18c0 0 -12 0 -12 10c0 9 38 154 132 154c50 0 82 -37 82 -82c0 -19 -5 -33 -13 -53c-10 -27 -10 -29 -22 -58l-39 -105c-23 -61 -29 -75 -29 -100c0 -23 7 -33 24 -33c51 0 84 61 102 124c5 15 5 18 15 18c3 0 12 0 12 -10Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45C" d="M469 273c0 -146 -135 -284 -268 -284c-93 0 -160 70 -160 169c0 142 134 284 268 284c90 0 160 -65 160 -169zM396 312c0 60 -30 108 -88 108c-28 0 -85 -15 -135 -92c-32 -51 -58 -159 -58 -208c0 -78 44 -109 87 -109c46 0 101 34 136 92c38 65 58 170 58 209Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-28" d="M332 -238c0 -5 -5 -10 -10 -10c-2 0 -4 1 -6 2c-110 83 -215 283 -215 454v84c0 171 105 371 215 454c2 1 4 2 6 2c5 0 10 -5 10 -10c0 -3 -2 -6 -4 -8c-104 -78 -173 -278 -173 -438v-84c0 -160 69 -360 173 -438c2 -2 4 -5 4 -8Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-29" d="M288 208c0 -171 -105 -371 -215 -454c-2 -1 -4 -2 -6 -2c-5 0 -10 5 -10 10c0 3 2 6 4 8c104 78 173 278 173 438v84c0 160 -69 360 -173 438c-2 2 -4 5 -4 8c0 5 5 10 10 10c2 0 4 -1 6 -2c110 -83 215 -283 215 -454v-84Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-33" d="M457 171c0 -102 -91 -193 -213 -193c-109 0 -202 66 -202 157c0 44 32 58 56 58c29 0 56 -20 56 -56c0 -38 -31 -60 -66 -55c35 -59 110 -76 153 -76c44 0 113 29 113 165c0 98 -37 166 -119 166h-44c-17 0 -24 0 -24 11c0 10 7 11 15 12c7 0 31 2 39 3c25 1 59 4 89 52 c26 44 28 102 28 114c0 90 -55 112 -96 112c-36 0 -102 -13 -133 -62c15 0 62 0 62 -50c0 -29 -20 -51 -51 -51c-29 0 -51 19 -51 52c0 76 76 136 177 136c96 0 184 -56 184 -138c0 -79 -58 -149 -140 -176c104 -21 167 -99 167 -181Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-3D" d="M722 347c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20zM722 153c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-7C" d="M159 -230c0 -11 -9 -20 -20 -20s-20 9 -20 20v960c0 11 9 20 20 20s20 -9 20 -20v-960Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2B" d="M722 250c0 -11 -9 -20 -20 -20h-293v-293c0 -11 -9 -20 -20 -20s-20 9 -20 20v293h-293c-11 0 -20 9 -20 20s9 20 20 20h293v293c0 11 9 20 20 20s20 -9 20 -20v-293h293c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-31" d="M419 0c-35 3 -122 3 -162 3s-127 0 -162 -3v31h32c90 0 93 12 93 48v518c-52 -26 -111 -26 -131 -26v31c32 0 120 0 182 64c23 0 23 -2 23 -26v-561c0 -37 3 -48 93 -48h32v-31Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2212" d="M722 250c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNSIZE5-7C" d="M172 -969c0 -18 -15 -32 -33 -32s-32 14 -32 32v2438c0 18 14 32 32 32s33 -14 33 -32v-2438Z"></path>
</defs>
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D45F" x="0" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D44E" x="456" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="990" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D456" x="1356" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D45C" x="1706" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2196" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="2590" y="0"></use>
<g transform="translate(2956,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="-213"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-3D" x="4084" y="0"></use>
<g transform="translate(5145,0)">
<use xlink:href="#E1-LATINMODERNSIZE5-7C"></use>
<g transform="translate(283,0)">
<g transform="translate(120,0)">
<rect stroke="none" width="7246" height="60" x="0" y="220"></rect>
<g transform="translate(926,777)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="517" y="513"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="1045" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2050" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="2444" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="3171" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="4176" y="0"></use>
<g transform="translate(4542,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="513"></use>
</g>
</g>
<g transform="translate(60,-787)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="517" y="408"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="1045" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2050" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="2444" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="3171" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="4176" y="0"></use>
<g transform="translate(4542,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="408"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="5616" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="6621" y="0"></use>
</g>
</g>
</g>
<use xlink:href="#E1-LATINMODERNSIZE5-7C" x="7769" y="0"></use>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -0,0 +1,63 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="26.167ex" height="6ex" style="vertical-align: -2.333ex; margin-left: 0ex; margin-right: 0ex; margin-bottom: 1px; margin-top: 1px;" viewBox="0 -1531.3 11230.6 2556.3" xmlns="http://www.w3.org/2000/svg">
<defs>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45F" d="M436 377c0 -36 -28 -59 -55 -59s-38 19 -38 35c0 26 22 50 52 55c0 0 -16 12 -42 12c-43 0 -72 -26 -80 -33c-24 -22 -52 -69 -56 -82l-32 -130c-4 -18 -38 -154 -40 -158c-7 -20 -25 -28 -37 -28c-15 0 -29 9 -29 27c0 5 6 28 9 43l58 231c13 52 16 63 16 84 c0 38 -14 46 -31 46c-36 0 -56 -48 -73 -119c-6 -22 -7 -23 -17 -23c0 0 -12 0 -12 10c0 3 13 63 31 97c9 18 28 57 74 57c47 0 83 -32 91 -77c19 28 63 77 128 77c51 0 83 -30 83 -65Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D44E" d="M498 143c0 0 -13 -63 -30 -99c-16 -32 -39 -55 -74 -55c-48 0 -83 33 -91 75c-60 -71 -110 -75 -130 -75c-78 0 -133 66 -133 160c0 146 124 293 241 293c45 0 74 -27 92 -64c3 22 18 44 42 44c17 0 29 -10 29 -27c0 -4 0 -6 -7 -34l-36 -140l-22 -90 c-11 -44 -13 -52 -13 -74c0 -20 3 -46 30 -46c41 0 59 59 76 124c3 14 4 18 14 18c3 0 12 0 12 -10zM361 332c0 6 -14 88 -79 88c-40 0 -85 -37 -116 -96c-23 -46 -55 -169 -55 -219c0 -39 14 -94 64 -94c28 0 69 16 113 71c15 17 15 19 20 37l50 196c1 5 3 11 3 17Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D461" d="M330 420c0 -20 -10 -20 -30 -20h-94l-74 -295c-4 -17 -6 -24 -6 -48c0 -33 10 -46 31 -46c34 0 87 24 130 128c5 11 6 14 15 14c4 0 12 0 12 -10c0 -8 -57 -154 -159 -154c-54 0 -92 38 -92 92c0 18 4 35 76 319h-88c-20 0 -28 0 -28 12c0 19 10 19 30 19h94l39 159 c9 35 37 36 40 36c17 0 29 -10 29 -27c0 -6 -5 -26 -41 -168h88c18 0 28 0 28 -11Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D456" d="M284 625c0 -30 -30 -53 -53 -53c-24 0 -38 17 -38 36c0 27 27 53 54 53c23 0 37 -16 37 -36zM293 143c0 -9 -37 -154 -131 -154c-48 0 -82 35 -82 82c0 21 13 54 23 80c16 43 61 159 69 185c4 10 11 31 11 52c0 32 -17 32 -25 32c-34 0 -74 -30 -101 -124 c-5 -16 -6 -18 -16 -18c0 0 -12 0 -12 10c0 9 38 154 132 154c50 0 82 -37 82 -82c0 -19 -5 -33 -13 -53c-10 -27 -10 -29 -22 -58l-39 -105c-23 -61 -29 -75 -29 -100c0 -23 7 -33 24 -33c51 0 84 61 102 124c5 15 5 18 15 18c3 0 12 0 12 -10Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45C" d="M469 273c0 -146 -135 -284 -268 -284c-93 0 -160 70 -160 169c0 142 134 284 268 284c90 0 160 -65 160 -169zM396 312c0 60 -30 108 -88 108c-28 0 -85 -15 -135 -92c-32 -51 -58 -159 -58 -208c0 -78 44 -109 87 -109c46 0 101 34 136 92c38 65 58 170 58 209Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-28" d="M332 -238c0 -5 -5 -10 -10 -10c-2 0 -4 1 -6 2c-110 83 -215 283 -215 454v84c0 171 105 371 215 454c2 1 4 2 6 2c5 0 10 -5 10 -10c0 -3 -2 -6 -4 -8c-104 -78 -173 -278 -173 -438v-84c0 -160 69 -360 173 -438c2 -2 4 -5 4 -8Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-29" d="M288 208c0 -171 -105 -371 -215 -454c-2 -1 -4 -2 -6 -2c-5 0 -10 5 -10 10c0 3 2 6 4 8c104 78 173 278 173 438v84c0 160 -69 360 -173 438c-2 2 -4 5 -4 8c0 5 5 10 10 10c2 0 4 -1 6 -2c110 -83 215 -283 215 -454v-84Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-32" d="M449 174l-28 -174h-371c0 24 0 26 11 37l192 214c55 62 105 141 105 221c0 82 -43 163 -134 163c-58 0 -112 -37 -135 -102c3 1 5 1 13 1c35 0 53 -26 53 -52c0 -41 -35 -53 -52 -53c-3 0 -53 0 -53 56c0 89 74 181 187 181c122 0 212 -80 212 -194 c0 -100 -60 -154 -216 -292l-106 -103h180c22 0 88 0 95 8c10 15 17 59 22 89h25Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-3D" d="M722 347c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20zM722 153c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-7C" d="M159 -230c0 -11 -9 -20 -20 -20s-20 9 -20 20v960c0 11 9 20 20 20s20 -9 20 -20v-960Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2212" d="M722 250c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2B" d="M722 250c0 -11 -9 -20 -20 -20h-293v-293c0 -11 -9 -20 -20 -20s-20 9 -20 20v293h-293c-11 0 -20 9 -20 20s9 20 20 20h293v293c0 11 9 20 20 20s20 -9 20 -20v-293h293c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-31" d="M419 0c-35 3 -122 3 -162 3s-127 0 -162 -3v31h32c90 0 93 12 93 48v518c-52 -26 -111 -26 -131 -26v31c32 0 120 0 182 64c23 0 23 -2 23 -26v-561c0 -37 3 -48 93 -48h32v-31Z"></path>
<path stroke-width="10" id="E1-LATINMODERNSIZE5-7C" d="M172 -969c0 -18 -15 -32 -33 -32s-32 14 -32 32v2438c0 18 14 32 32 32s33 -14 33 -32v-2438Z"></path>
</defs>
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D45F" x="0" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D44E" x="456" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="990" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D456" x="1356" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D45C" x="1706" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2196" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="2590" y="0"></use>
<g transform="translate(2956,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-32" x="557" y="-213"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-3D" x="4084" y="0"></use>
<g transform="translate(5145,0)">
<use xlink:href="#E1-LATINMODERNSIZE5-7C"></use>
<g transform="translate(283,0)">
<g transform="translate(120,0)">
<rect stroke="none" width="5278" height="60" x="0" y="220"></rect>
<g transform="translate(926,676)">
<use xlink:href="#E1-LATINMODERNMAIN-32" x="0" y="0"></use>
<g transform="translate(505,0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-32" x="517" y="513"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="1550" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-32" x="2555" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="3060" y="0"></use>
</g>
<g transform="translate(60,-787)">
<use xlink:href="#E1-LATINMODERNMAIN-32" x="0" y="0"></use>
<g transform="translate(505,0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-32" x="517" y="408"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="1550" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-32" x="2555" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="3060" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="3648" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="4653" y="0"></use>
</g>
</g>
</g>
<use xlink:href="#E1-LATINMODERNSIZE5-7C" x="5801" y="0"></use>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,69 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="30.667ex" height="6.167ex" style="vertical-align: -2.5ex; margin-left: 0ex; margin-right: 0ex; margin-bottom: 1px; margin-top: 1px;" viewBox="0 -1632.2 13198.2 2690.5" xmlns="http://www.w3.org/2000/svg">
<defs>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45F" d="M436 377c0 -36 -28 -59 -55 -59s-38 19 -38 35c0 26 22 50 52 55c0 0 -16 12 -42 12c-43 0 -72 -26 -80 -33c-24 -22 -52 -69 -56 -82l-32 -130c-4 -18 -38 -154 -40 -158c-7 -20 -25 -28 -37 -28c-15 0 -29 9 -29 27c0 5 6 28 9 43l58 231c13 52 16 63 16 84 c0 38 -14 46 -31 46c-36 0 -56 -48 -73 -119c-6 -22 -7 -23 -17 -23c0 0 -12 0 -12 10c0 3 13 63 31 97c9 18 28 57 74 57c47 0 83 -32 91 -77c19 28 63 77 128 77c51 0 83 -30 83 -65Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D44E" d="M498 143c0 0 -13 -63 -30 -99c-16 -32 -39 -55 -74 -55c-48 0 -83 33 -91 75c-60 -71 -110 -75 -130 -75c-78 0 -133 66 -133 160c0 146 124 293 241 293c45 0 74 -27 92 -64c3 22 18 44 42 44c17 0 29 -10 29 -27c0 -4 0 -6 -7 -34l-36 -140l-22 -90 c-11 -44 -13 -52 -13 -74c0 -20 3 -46 30 -46c41 0 59 59 76 124c3 14 4 18 14 18c3 0 12 0 12 -10zM361 332c0 6 -14 88 -79 88c-40 0 -85 -37 -116 -96c-23 -46 -55 -169 -55 -219c0 -39 14 -94 64 -94c28 0 69 16 113 71c15 17 15 19 20 37l50 196c1 5 3 11 3 17Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D461" d="M330 420c0 -20 -10 -20 -30 -20h-94l-74 -295c-4 -17 -6 -24 -6 -48c0 -33 10 -46 31 -46c34 0 87 24 130 128c5 11 6 14 15 14c4 0 12 0 12 -10c0 -8 -57 -154 -159 -154c-54 0 -92 38 -92 92c0 18 4 35 76 319h-88c-20 0 -28 0 -28 12c0 19 10 19 30 19h94l39 159 c9 35 37 36 40 36c17 0 29 -10 29 -27c0 -6 -5 -26 -41 -168h88c18 0 28 0 28 -11Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D456" d="M284 625c0 -30 -30 -53 -53 -53c-24 0 -38 17 -38 36c0 27 27 53 54 53c23 0 37 -16 37 -36zM293 143c0 -9 -37 -154 -131 -154c-48 0 -82 35 -82 82c0 21 13 54 23 80c16 43 61 159 69 185c4 10 11 31 11 52c0 32 -17 32 -25 32c-34 0 -74 -30 -101 -124 c-5 -16 -6 -18 -16 -18c0 0 -12 0 -12 10c0 9 38 154 132 154c50 0 82 -37 82 -82c0 -19 -5 -33 -13 -53c-10 -27 -10 -29 -22 -58l-39 -105c-23 -61 -29 -75 -29 -100c0 -23 7 -33 24 -33c51 0 84 61 102 124c5 15 5 18 15 18c3 0 12 0 12 -10Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45C" d="M469 273c0 -146 -135 -284 -268 -284c-93 0 -160 70 -160 169c0 142 134 284 268 284c90 0 160 -65 160 -169zM396 312c0 60 -30 108 -88 108c-28 0 -85 -15 -135 -92c-32 -51 -58 -159 -58 -208c0 -78 44 -109 87 -109c46 0 101 34 136 92c38 65 58 170 58 209Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-28" d="M332 -238c0 -5 -5 -10 -10 -10c-2 0 -4 1 -6 2c-110 83 -215 283 -215 454v84c0 171 105 371 215 454c2 1 4 2 6 2c5 0 10 -5 10 -10c0 -3 -2 -6 -4 -8c-104 -78 -173 -278 -173 -438v-84c0 -160 69 -360 173 -438c2 -2 4 -5 4 -8Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-29" d="M288 208c0 -171 -105 -371 -215 -454c-2 -1 -4 -2 -6 -2c-5 0 -10 5 -10 10c0 3 2 6 4 8c104 78 173 278 173 438v84c0 160 -69 360 -173 438c-2 2 -4 5 -4 8c0 5 5 10 10 10c2 0 4 -1 6 -2c110 -83 215 -283 215 -454v-84Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-33" d="M457 171c0 -102 -91 -193 -213 -193c-109 0 -202 66 -202 157c0 44 32 58 56 58c29 0 56 -20 56 -56c0 -38 -31 -60 -66 -55c35 -59 110 -76 153 -76c44 0 113 29 113 165c0 98 -37 166 -119 166h-44c-17 0 -24 0 -24 11c0 10 7 11 15 12c7 0 31 2 39 3c25 1 59 4 89 52 c26 44 28 102 28 114c0 90 -55 112 -96 112c-36 0 -102 -13 -133 -62c15 0 62 0 62 -50c0 -29 -20 -51 -51 -51c-29 0 -51 19 -51 52c0 76 76 136 177 136c96 0 184 -56 184 -138c0 -79 -58 -149 -140 -176c104 -21 167 -99 167 -181Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-3D" d="M722 347c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20zM722 153c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-7C" d="M159 -230c0 -11 -9 -20 -20 -20s-20 9 -20 20v960c0 11 9 20 20 20s20 -9 20 -20v-960Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2B" d="M722 250c0 -11 -9 -20 -20 -20h-293v-293c0 -11 -9 -20 -20 -20s-20 9 -20 20v293h-293c-11 0 -20 9 -20 20s9 20 20 20h293v293c0 11 9 20 20 20s20 -9 20 -20v-293h293c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-31" d="M419 0c-35 3 -122 3 -162 3s-127 0 -162 -3v31h32c90 0 93 12 93 48v518c-52 -26 -111 -26 -131 -26v31c32 0 120 0 182 64c23 0 23 -2 23 -26v-561c0 -37 3 -48 93 -48h32v-31Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2212" d="M722 250c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNSIZE5-7C" d="M172 -969c0 -18 -15 -32 -33 -32s-32 14 -32 32v2438c0 18 14 32 32 32s33 -14 33 -32v-2438Z"></path>
</defs>
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D45F" x="0" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D44E" x="456" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="990" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D456" x="1356" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D45C" x="1706" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2196" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="2590" y="0"></use>
<g transform="translate(2956,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="-213"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-3D" x="4084" y="0"></use>
<g transform="translate(5145,0)">
<use xlink:href="#E1-LATINMODERNSIZE5-7C"></use>
<g transform="translate(283,0)">
<g transform="translate(120,0)">
<rect stroke="none" width="7246" height="60" x="0" y="220"></rect>
<g transform="translate(60,777)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="517" y="513"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="1045" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2050" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="2444" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="3171" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="4176" y="0"></use>
<g transform="translate(4542,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="513"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="5616" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="6621" y="0"></use>
</g>
<g transform="translate(926,-787)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="517" y="408"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="1045" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2050" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="2444" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="3171" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="4176" y="0"></use>
<g transform="translate(4542,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="408"></use>
</g>
</g>
</g>
</g>
<use xlink:href="#E1-LATINMODERNSIZE5-7C" x="7769" y="0"></use>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -0,0 +1,69 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="30.667ex" height="6.167ex" style="vertical-align: -2.5ex; margin-left: 0ex; margin-right: 0ex; margin-bottom: 1px; margin-top: 1px;" viewBox="0 -1632.2 13198.2 2690.5" xmlns="http://www.w3.org/2000/svg">
<defs>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45F" d="M436 377c0 -36 -28 -59 -55 -59s-38 19 -38 35c0 26 22 50 52 55c0 0 -16 12 -42 12c-43 0 -72 -26 -80 -33c-24 -22 -52 -69 -56 -82l-32 -130c-4 -18 -38 -154 -40 -158c-7 -20 -25 -28 -37 -28c-15 0 -29 9 -29 27c0 5 6 28 9 43l58 231c13 52 16 63 16 84 c0 38 -14 46 -31 46c-36 0 -56 -48 -73 -119c-6 -22 -7 -23 -17 -23c0 0 -12 0 -12 10c0 3 13 63 31 97c9 18 28 57 74 57c47 0 83 -32 91 -77c19 28 63 77 128 77c51 0 83 -30 83 -65Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D44E" d="M498 143c0 0 -13 -63 -30 -99c-16 -32 -39 -55 -74 -55c-48 0 -83 33 -91 75c-60 -71 -110 -75 -130 -75c-78 0 -133 66 -133 160c0 146 124 293 241 293c45 0 74 -27 92 -64c3 22 18 44 42 44c17 0 29 -10 29 -27c0 -4 0 -6 -7 -34l-36 -140l-22 -90 c-11 -44 -13 -52 -13 -74c0 -20 3 -46 30 -46c41 0 59 59 76 124c3 14 4 18 14 18c3 0 12 0 12 -10zM361 332c0 6 -14 88 -79 88c-40 0 -85 -37 -116 -96c-23 -46 -55 -169 -55 -219c0 -39 14 -94 64 -94c28 0 69 16 113 71c15 17 15 19 20 37l50 196c1 5 3 11 3 17Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D461" d="M330 420c0 -20 -10 -20 -30 -20h-94l-74 -295c-4 -17 -6 -24 -6 -48c0 -33 10 -46 31 -46c34 0 87 24 130 128c5 11 6 14 15 14c4 0 12 0 12 -10c0 -8 -57 -154 -159 -154c-54 0 -92 38 -92 92c0 18 4 35 76 319h-88c-20 0 -28 0 -28 12c0 19 10 19 30 19h94l39 159 c9 35 37 36 40 36c17 0 29 -10 29 -27c0 -6 -5 -26 -41 -168h88c18 0 28 0 28 -11Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D456" d="M284 625c0 -30 -30 -53 -53 -53c-24 0 -38 17 -38 36c0 27 27 53 54 53c23 0 37 -16 37 -36zM293 143c0 -9 -37 -154 -131 -154c-48 0 -82 35 -82 82c0 21 13 54 23 80c16 43 61 159 69 185c4 10 11 31 11 52c0 32 -17 32 -25 32c-34 0 -74 -30 -101 -124 c-5 -16 -6 -18 -16 -18c0 0 -12 0 -12 10c0 9 38 154 132 154c50 0 82 -37 82 -82c0 -19 -5 -33 -13 -53c-10 -27 -10 -29 -22 -58l-39 -105c-23 -61 -29 -75 -29 -100c0 -23 7 -33 24 -33c51 0 84 61 102 124c5 15 5 18 15 18c3 0 12 0 12 -10Z"></path>
<path stroke-width="10" id="E1-LATINMODERNNORMAL-1D45C" d="M469 273c0 -146 -135 -284 -268 -284c-93 0 -160 70 -160 169c0 142 134 284 268 284c90 0 160 -65 160 -169zM396 312c0 60 -30 108 -88 108c-28 0 -85 -15 -135 -92c-32 -51 -58 -159 -58 -208c0 -78 44 -109 87 -109c46 0 101 34 136 92c38 65 58 170 58 209Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-28" d="M332 -238c0 -5 -5 -10 -10 -10c-2 0 -4 1 -6 2c-110 83 -215 283 -215 454v84c0 171 105 371 215 454c2 1 4 2 6 2c5 0 10 -5 10 -10c0 -3 -2 -6 -4 -8c-104 -78 -173 -278 -173 -438v-84c0 -160 69 -360 173 -438c2 -2 4 -5 4 -8Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-29" d="M288 208c0 -171 -105 -371 -215 -454c-2 -1 -4 -2 -6 -2c-5 0 -10 5 -10 10c0 3 2 6 4 8c104 78 173 278 173 438v84c0 160 -69 360 -173 438c-2 2 -4 5 -4 8c0 5 5 10 10 10c2 0 4 -1 6 -2c110 -83 215 -283 215 -454v-84Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-33" d="M457 171c0 -102 -91 -193 -213 -193c-109 0 -202 66 -202 157c0 44 32 58 56 58c29 0 56 -20 56 -56c0 -38 -31 -60 -66 -55c35 -59 110 -76 153 -76c44 0 113 29 113 165c0 98 -37 166 -119 166h-44c-17 0 -24 0 -24 11c0 10 7 11 15 12c7 0 31 2 39 3c25 1 59 4 89 52 c26 44 28 102 28 114c0 90 -55 112 -96 112c-36 0 -102 -13 -133 -62c15 0 62 0 62 -50c0 -29 -20 -51 -51 -51c-29 0 -51 19 -51 52c0 76 76 136 177 136c96 0 184 -56 184 -138c0 -79 -58 -149 -140 -176c104 -21 167 -99 167 -181Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-3D" d="M722 347c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20zM722 153c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-7C" d="M159 -230c0 -11 -9 -20 -20 -20s-20 9 -20 20v960c0 11 9 20 20 20s20 -9 20 -20v-960Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2B" d="M722 250c0 -11 -9 -20 -20 -20h-293v-293c0 -11 -9 -20 -20 -20s-20 9 -20 20v293h-293c-11 0 -20 9 -20 20s9 20 20 20h293v293c0 11 9 20 20 20s20 -9 20 -20v-293h293c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-31" d="M419 0c-35 3 -122 3 -162 3s-127 0 -162 -3v31h32c90 0 93 12 93 48v518c-52 -26 -111 -26 -131 -26v31c32 0 120 0 182 64c23 0 23 -2 23 -26v-561c0 -37 3 -48 93 -48h32v-31Z"></path>
<path stroke-width="10" id="E1-LATINMODERNMAIN-2212" d="M722 250c0 -11 -9 -20 -20 -20h-626c-11 0 -20 9 -20 20s9 20 20 20h626c11 0 20 -9 20 -20Z"></path>
<path stroke-width="10" id="E1-LATINMODERNSIZE5-7C" d="M172 -969c0 -18 -15 -32 -33 -32s-32 14 -32 32v2438c0 18 14 32 32 32s33 -14 33 -32v-2438Z"></path>
</defs>
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D45F" x="0" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D44E" x="456" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="990" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D456" x="1356" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D45C" x="1706" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2196" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="2590" y="0"></use>
<g transform="translate(2956,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="-213"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-3D" x="4084" y="0"></use>
<g transform="translate(5145,0)">
<use xlink:href="#E1-LATINMODERNSIZE5-7C"></use>
<g transform="translate(283,0)">
<g transform="translate(120,0)">
<rect stroke="none" width="7246" height="60" x="0" y="220"></rect>
<g transform="translate(926,777)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="517" y="513"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="1045" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2050" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="2444" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="3171" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="4176" y="0"></use>
<g transform="translate(4542,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="513"></use>
</g>
</g>
<g transform="translate(60,-787)">
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="517" y="408"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2B" x="1045" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-28" x="2050" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="2444" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="3171" y="0"></use>
<use xlink:href="#E1-LATINMODERNNORMAL-1D461" x="4176" y="0"></use>
<g transform="translate(4542,0)">
<use xlink:href="#E1-LATINMODERNMAIN-29" x="0" y="0"></use>
<use transform="scale(0.707)" xlink:href="#E1-LATINMODERNMAIN-33" x="557" y="408"></use>
</g>
<use xlink:href="#E1-LATINMODERNMAIN-2212" x="5616" y="0"></use>
<use xlink:href="#E1-LATINMODERNMAIN-31" x="6621" y="0"></use>
</g>
</g>
</g>
<use xlink:href="#E1-LATINMODERNSIZE5-7C" x="7769" y="0"></use>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.3 KiB