export function fillet()

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;
    }