in packages/maker.js/src/core/fillet.ts [375:454]
export function fillet(pathA: IPath, pathB: IPath, filletRadius: number, options?: IPointMatchOptions): IPathArc {
if (pathA && pathB && filletRadius && filletRadius > 0) {
var opts: IPointMatchOptions = {
pointMatchingDistance: .005
};
extendObject(opts, options);
//first find the common point
var commonProperty = getMatchingPointProperties(pathA, pathB, options);
if (commonProperty) {
//since arcs can curl beyond, we need a local reference point.
//An intersection with a circle of the same radius as the desired fillet should suffice.
if (!populateShardPointsFromReferenceCircle(filletRadius, commonProperty[0].point, commonProperty, opts)) {
return null;
}
//get "parallel" guidelines
var guidePaths: IPath[] = [];
for (var i = 0; i < 2; i++) {
var otherPathShardPoint = commonProperty[1 - i].shardPoint;
if (!otherPathShardPoint) {
return null;
}
var guidePath = getGuidePath(commonProperty[i], filletRadius, otherPathShardPoint);
guidePaths.push(guidePath);
}
//the center of the fillet is the point where the guidelines intersect.
var intersectionPoint = intersection(guidePaths[0], guidePaths[1]);
if (intersectionPoint) {
var center: IPoint;
//if guidelines intersect in more than one place, choose the closest one.
if (intersectionPoint.intersectionPoints.length == 1) {
center = intersectionPoint.intersectionPoints[0];
} else {
center = point.closest(commonProperty[0].point, intersectionPoint.intersectionPoints);
}
//get the angles of the fillet and a function which clips the path to the fillet.
var results: IFilletResult[] = [];
for (var i = 0; i < 2; i++) {
var result = getFilletResult(commonProperty[i], filletRadius, center);
if (!result) {
return null;
}
results.push(result);
}
//the two paths may actually be on the same line
if (round(results[0].filletAngle - results[1].filletAngle) == 0) return null;
var filletArc = new paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle);
var filletSpan = angle.ofArcSpan(filletArc);
//the algorithm is only valid for fillet less than 180 degrees
if (filletSpan == 180) {
return null;
}
if (filletSpan > 180) {
//swap to make smallest angle
filletArc.startAngle = results[1].filletAngle;
filletArc.endAngle = results[0].filletAngle;
}
//clip the paths and return the fillet arc.
results[0].clipPath();
results[1].clipPath();
return filletArc;
}
}
}
return null;
}