Unify the precision management of geometries
This commit is contained in:
parent
15c7381673
commit
84a8cb809c
6 changed files with 45 additions and 39 deletions
|
@ -98,19 +98,16 @@ function simplifyContours(source) {
|
||||||
TypoGeom.Boolean.removeOverlap(
|
TypoGeom.Boolean.removeOverlap(
|
||||||
CurveUtil.convertShapeToArcs(source),
|
CurveUtil.convertShapeToArcs(source),
|
||||||
TypoGeom.Boolean.PolyFillType.pftNonZero,
|
TypoGeom.Boolean.PolyFillType.pftNonZero,
|
||||||
1 << 17
|
CurveUtil.BOOLE_RESOLUTION
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
sink,
|
sink,
|
||||||
FINAL_SIMPLIFY_TOLERANCE
|
CurveUtil.GEOMETRY_PRECISION
|
||||||
);
|
);
|
||||||
|
|
||||||
return sink.contours;
|
return sink.contours;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FINAL_SIMPLIFY_RESOLUTION = 16;
|
|
||||||
const FINAL_SIMPLIFY_TOLERANCE = 2 / FINAL_SIMPLIFY_RESOLUTION;
|
|
||||||
|
|
||||||
class FairizedShapeSink {
|
class FairizedShapeSink {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.contours = [];
|
this.contours = [];
|
||||||
|
@ -133,7 +130,7 @@ class FairizedShapeSink {
|
||||||
this.lineTo(x, y);
|
this.lineTo(x, y);
|
||||||
}
|
}
|
||||||
lineTo(x, y) {
|
lineTo(x, y) {
|
||||||
const z = Point.cornerFromXY(x, y).round(FINAL_SIMPLIFY_RESOLUTION);
|
const z = Point.cornerFromXY(x, y).round(CurveUtil.RECIP_GEOMETRY_PRECISION);
|
||||||
while (this.lastContour.length >= 2) {
|
while (this.lastContour.length >= 2) {
|
||||||
const a = this.lastContour[this.lastContour.length - 2],
|
const a = this.lastContour[this.lastContour.length - 2],
|
||||||
b = this.lastContour[this.lastContour.length - 1];
|
b = this.lastContour[this.lastContour.length - 1];
|
||||||
|
@ -146,10 +143,10 @@ class FairizedShapeSink {
|
||||||
this.lastContour.push(z);
|
this.lastContour.push(z);
|
||||||
}
|
}
|
||||||
arcTo(arc, x, y) {
|
arcTo(arc, x, y) {
|
||||||
const offPoints = TypoGeom.Quadify.auto(arc, FINAL_SIMPLIFY_TOLERANCE);
|
const offPoints = TypoGeom.Quadify.auto(arc, CurveUtil.GEOMETRY_PRECISION);
|
||||||
if (offPoints) {
|
if (offPoints) {
|
||||||
for (const z of offPoints)
|
for (const z of offPoints)
|
||||||
this.lastContour.push(Point.offFrom(z).round(FINAL_SIMPLIFY_RESOLUTION));
|
this.lastContour.push(Point.offFrom(z).round(CurveUtil.RECIP_GEOMETRY_PRECISION));
|
||||||
}
|
}
|
||||||
this.lineTo(x, y);
|
this.lineTo(x, y);
|
||||||
}
|
}
|
||||||
|
@ -162,8 +159,14 @@ function isLineExtend(a, b, c) {
|
||||||
(aligned(a.y, b.y, c.y) && between(a.x, b.x, c.x)))
|
(aligned(a.y, b.y, c.y) && between(a.x, b.x, c.x)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
function geometryPrecisionEqual(a, b) {
|
||||||
|
return (
|
||||||
|
Math.round(a * CurveUtil.RECIP_GEOMETRY_PRECISION) ===
|
||||||
|
Math.round(b * CurveUtil.RECIP_GEOMETRY_PRECISION)
|
||||||
|
);
|
||||||
|
}
|
||||||
function aligned(a, b, c) {
|
function aligned(a, b, c) {
|
||||||
return Math.round(a) === Math.round(b) && Math.round(b) === Math.round(c);
|
return geometryPrecisionEqual(a, b) && geometryPrecisionEqual(b, c);
|
||||||
}
|
}
|
||||||
function between(a, b, c) {
|
function between(a, b, c) {
|
||||||
return (a <= b && b <= c) || (a >= b && b >= c);
|
return (a <= b && b <= c) || (a >= b && b >= c);
|
||||||
|
|
|
@ -15,7 +15,12 @@ export : define [SetupBuilders args] : begin
|
||||||
set g1.gizmo : this.gizmo || globalTransform
|
set g1.gizmo : this.gizmo || globalTransform
|
||||||
g1.include item
|
g1.include item
|
||||||
set g1.contours : g1.contours.map CurveUtil.convertContourToCubic
|
set g1.contours : g1.contours.map CurveUtil.convertContourToCubic
|
||||||
local c1 : TypoGeom.Boolean.combine operator [CurveUtil.convertShapeToArcs g.contours] [CurveUtil.convertShapeToArcs g1.contours] TypoGeom.Boolean.PolyFillType.pftNonZero TypoGeom.Boolean.PolyFillType.pftNonZero 16384
|
local c1 : TypoGeom.Boolean.combine operator
|
||||||
|
CurveUtil.convertShapeToArcs g.contours
|
||||||
|
CurveUtil.convertShapeToArcs g1.contours
|
||||||
|
begin TypoGeom.Boolean.PolyFillType.pftNonZero
|
||||||
|
begin TypoGeom.Boolean.PolyFillType.pftNonZero
|
||||||
|
begin CurveUtil.BOOLE_RESOLUTION
|
||||||
local ctx : new CurveUtil.BezToContoursSink
|
local ctx : new CurveUtil.BezToContoursSink
|
||||||
TypoGeom.transferBezArcShape c1 ctx
|
TypoGeom.transferBezArcShape c1 ctx
|
||||||
set g.contours ctx.contours
|
set g.contours ctx.contours
|
||||||
|
|
|
@ -151,9 +151,12 @@ export : define [SetupBuilders args] : begin
|
||||||
if closed : knots.pop
|
if closed : knots.pop
|
||||||
return {.knots [flatten knots] .closed closed .lastafs lastafs}
|
return {.knots [flatten knots] .closed closed .lastafs lastafs}
|
||||||
|
|
||||||
define QUAD false
|
define [convertSpiroToBezier knots closed ctx] : begin
|
||||||
define PRECISION 0.5
|
define CUBIC false
|
||||||
|
return : SpiroJs.spiroToBezierOnContext knots closed ctx CUBIC CurveUtil.GEOMETRY_PRECISION
|
||||||
|
|
||||||
define [dispiro] : let [args : {}.slice.call arguments 0] : lambda [dontinc] : begin
|
define [dispiro] : let [args : {}.slice.call arguments 0] : lambda [dontinc] : begin
|
||||||
|
define CLOSED true
|
||||||
local s : new SpiroExpansionContext
|
local s : new SpiroExpansionContext
|
||||||
set s.gizmo : this.gizmo || globalTransform
|
set s.gizmo : this.gizmo || globalTransform
|
||||||
local {.knots knots .closed closed .lastafs lastafs} : prepareSpiroKnots [{}.slice.call args 0] s
|
local {.knots knots .closed closed .lastafs lastafs} : prepareSpiroKnots [{}.slice.call args 0] s
|
||||||
|
@ -167,16 +170,16 @@ export : define [SetupBuilders args] : begin
|
||||||
local {.lhs lhs .rhs rhs} : s.expand [fallback s.contrast Contrast]
|
local {.lhs lhs .rhs rhs} : s.expand [fallback s.contrast Contrast]
|
||||||
if closed : then
|
if closed : then
|
||||||
local g : new CurveUtil.BezToContoursSink
|
local g : new CurveUtil.BezToContoursSink
|
||||||
SpiroJs.spiroToBezierOnContext [lhs.slice 0 (-1)] true g QUAD PRECISION
|
# CurveUtil.BezToContoursSink::beginShape won't clear the contours
|
||||||
local lhsContour g.contours.0
|
# We will get two contours at last
|
||||||
set g.contours {}
|
convertSpiroToBezier [lhs.slice 0 (-1)] CLOSED g
|
||||||
SpiroJs.spiroToBezierOnContext [rhs.reverse :.slice 0 (-1)] true g QUAD PRECISION
|
convertSpiroToBezier [rhs.reverse :.slice 0 (-1)] CLOSED g
|
||||||
local rhsContour g.contours.0
|
set g.contours { [g.contours.0.concat g.contours.1] }
|
||||||
set g.contours {[lhsContour.concat rhsContour]}
|
|
||||||
: else : begin
|
: else : begin
|
||||||
local g : new CurveUtil.BezToContoursSink
|
local g : new CurveUtil.BezToContoursSink
|
||||||
lhs.0.type = rhs.0.type = lhs.(lhs.length - 1).type = rhs.(rhs.length - 1).type = 'corner'
|
lhs.0.type = lhs.(lhs.length - 1).type = 'corner'
|
||||||
SpiroJs.spiroToBezierOnContext [lhs.concat : rhs.reverse] true g QUAD PRECISION
|
rhs.0.type = rhs.(rhs.length - 1).type = 'corner'
|
||||||
|
convertSpiroToBezier [lhs.concat : rhs.reverse] CLOSED g
|
||||||
|
|
||||||
set g.knots knots
|
set g.knots knots
|
||||||
set g.lhsKnots lhs
|
set g.lhsKnots lhs
|
||||||
|
@ -187,7 +190,7 @@ export : define [SetupBuilders args] : begin
|
||||||
define [spiro-outline] : let [k : {}.slice.call arguments 0] : lambda [dontinc] : begin
|
define [spiro-outline] : let [k : {}.slice.call arguments 0] : lambda [dontinc] : begin
|
||||||
local g : new CurveUtil.BezToContoursSink (this.gizmo || globalTransform)
|
local g : new CurveUtil.BezToContoursSink (this.gizmo || globalTransform)
|
||||||
local {.knots knots .closed closed .lastafs lastafs} : prepareSpiroKnots k g
|
local {.knots knots .closed closed .lastafs lastafs} : prepareSpiroKnots k g
|
||||||
SpiroJs.spiroToBezierOnContext knots closed g QUAD PRECISION
|
convertSpiroToBezier knots closed g
|
||||||
foreach af [items-of lastafs] : if af : af.call g
|
foreach af [items-of lastafs] : if af : af.call g
|
||||||
this.includeGeometry g 0 0
|
this.includeGeometry g 0 0
|
||||||
return g
|
return g
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
$$include '../meta/macros.ptl'
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
import [OffsetCurve BezToContoursSink] from '../support/curve-util'
|
import [OffsetCurve BezToContoursSink GEOMETRY_PRECISION] from '../support/curve-util'
|
||||||
import [mix linreg clamp fallback] from '../support/utils'
|
import [mix linreg clamp fallback] from '../support/utils'
|
||||||
import [designParameters] from '../meta/aesthetics'
|
import [designParameters] from '../meta/aesthetics'
|
||||||
import [Arcs Quadify transferGenericShapeAsBezier] from "typo-geom"
|
import [Arcs Quadify transferGenericShapeAsBezier] from "typo-geom"
|
||||||
|
@ -230,7 +230,7 @@ glyph-block Overmarks : begin
|
||||||
define outer : new Arcs.Reverted : new OffsetCurve bone (-hs) HVContrast
|
define outer : new Arcs.Reverted : new OffsetCurve bone (-hs) HVContrast
|
||||||
|
|
||||||
define cs : new BezToContoursSink
|
define cs : new BezToContoursSink
|
||||||
transferGenericShapeAsBezier {{inner outer}} cs (1 / 4)
|
transferGenericShapeAsBezier {{inner outer}} cs GEOMETRY_PRECISION
|
||||||
include cs
|
include cs
|
||||||
|
|
||||||
sketch # tildeAbove
|
sketch # tildeAbove
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
const TypoGeom = require("typo-geom");
|
const TypoGeom = require("typo-geom");
|
||||||
const Point = require("./point");
|
const Point = require("./point");
|
||||||
const { mix } = require("./utils");
|
|
||||||
const Transform = require("./transform");
|
const Transform = require("./transform");
|
||||||
|
|
||||||
|
exports.GEOMETRY_PRECISION = 1 / 4;
|
||||||
|
exports.RECIP_GEOMETRY_PRECISION = 4;
|
||||||
|
exports.BOOLE_RESOLUTION = 0x4000;
|
||||||
|
|
||||||
exports.OffsetCurve = class OffsetCurve {
|
exports.OffsetCurve = class OffsetCurve {
|
||||||
constructor(bone, offset, contrast) {
|
constructor(bone, offset, contrast) {
|
||||||
this.bone = bone;
|
this.bone = bone;
|
||||||
|
@ -31,7 +34,7 @@ exports.OffsetCurve = class OffsetCurve {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function convertContourToCubic(contour) {
|
exports.convertContourToCubic = function convertContourToCubic(contour) {
|
||||||
if (!contour || !contour.length) return [];
|
if (!contour || !contour.length) return [];
|
||||||
|
|
||||||
const newContour = [];
|
const newContour = [];
|
||||||
|
@ -70,7 +73,11 @@ function convertContourToCubic(contour) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return newContour;
|
return newContour;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
exports.convertShapeToArcs = function convertShapeToArcs(shape) {
|
||||||
|
return shape.map(convertContourToArcs);
|
||||||
|
};
|
||||||
|
|
||||||
function convertContourToArcs(contour) {
|
function convertContourToArcs(contour) {
|
||||||
if (!contour || !contour.length) return [];
|
if (!contour || !contour.length) return [];
|
||||||
|
@ -124,13 +131,6 @@ function convertContourToArcs(contour) {
|
||||||
return newContour;
|
return newContour;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertShapeToArcs(shape) {
|
|
||||||
return shape.map(convertContourToArcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.convertContourToCubic = convertContourToCubic;
|
|
||||||
exports.convertShapeToArcs = convertShapeToArcs;
|
|
||||||
|
|
||||||
exports.BezToContoursSink = class BezToContoursSink {
|
exports.BezToContoursSink = class BezToContoursSink {
|
||||||
constructor(gizmo) {
|
constructor(gizmo) {
|
||||||
this.gizmo = gizmo || Transform.Id();
|
this.gizmo = gizmo || Transform.Id();
|
||||||
|
|
|
@ -116,11 +116,6 @@ module.exports = class SpiroExpansionContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function zeroes(n) {
|
|
||||||
let a = new Array(n);
|
|
||||||
for (let i = 0; i < n; ++i) a[i] = 0;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
function normalX(angle, contrast) {
|
function normalX(angle, contrast) {
|
||||||
return Math.cos(angle) * contrast;
|
return Math.cos(angle) * contrast;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue