Я пытаюсь выполнить логические операции на SVG-контурах (которые содержат безье, как квадратичные, так и кубические), используя JS Clipper.Преобразование SVG-пути в полигоны для использования в Javascript Clipper
JS Clipper начинается с полигонов, затем выполняет операцию, а затем, похоже, преобразует их обратно в пути SVG.
В приведенной ниже функции показан путь SVG, но приведенный ниже пример начинается с двух полигонов.
Пример функции:
// Polygon Arrays are expanded for better readability
function clip() {
var subj_polygons = [
[{
X: 10,
Y: 10
}, {
X: 110,
Y: 10
}, {
X: 110,
Y: 110
}, {
X: 10,
Y: 110
}],
[{
X: 20,
Y: 20
}, {
X: 20,
Y: 100
}, {
X: 100,
Y: 100
}, {
X: 100,
Y: 20
}]
];
var clip_polygons = [
[{
X: 50,
Y: 50
}, {
X: 150,
Y: 50
}, {
X: 150,
Y: 150
}, {
X: 50,
Y: 150
}],
[{
X: 60,
Y: 60
}, {
X: 60,
Y: 140
}, {
X: 140,
Y: 140
}, {
X: 140,
Y: 60
}]
];
var scale = 100;
subj_polygons = scaleup(subj_polygons, scale);
clip_polygons = scaleup(clip_polygons, scale);
var cpr = new ClipperLib.Clipper();
cpr.AddPolygons(subj_polygons, ClipperLib.PolyType.ptSubject);
cpr.AddPolygons(clip_polygons, ClipperLib.PolyType.ptClip);
var subject_fillType = ClipperLib.PolyFillType.pftNonZero;
var clip_fillType = ClipperLib.PolyFillType.pftNonZero;
var clipTypes = [ClipperLib.ClipType.ctUnion];
var clipTypesTexts = "Union";
var solution_polygons, svg, cont = document.getElementById('svgcontainer');
var i;
for (i = 0; i < clipTypes.length; i++) {
solution_polygons = new ClipperLib.Polygons();
cpr.Execute(clipTypes[i], solution_polygons, subject_fillType, clip_fillType);
console.log(polys2path(solution_polygons, scale));
}
}
// helper function to scale up polygon coordinates
function scaleup(poly, scale) {
var i, j;
if (!scale) scale = 1;
for (i = 0; i < poly.length; i++) {
for (j = 0; j < poly[i].length; j++) {
poly[i][j].X *= scale;
poly[i][j].Y *= scale;
}
}
return poly;
}
// converts polygons to SVG path string
function polys2path(poly, scale) {
var path = "",
i, j;
if (!scale) scale = 1;
for (i = 0; i < poly.length; i++) {
for (j = 0; j < poly[i].length; j++) {
if (!j) path += "M";
else path += "L";
path += (poly[i][j].X/scale) + ", " + (poly[i][j].Y/scale);
}
path += "Z";
}
return path;
}
Будет ли это решение работать в ЛЮБОЙ форме независимо от сложности? Я отказался от попыток использовать вашу библиотеку из-за перехода к преобразованию многоугольника. Мне действительно удалось использовать этот метод из Phrogz: https://gist.github.com/Phrogz/845901 для преобразования в многоугольники с одной большой проблемой. Мои пользователи должны нарисовать очень и очень сложные фигуры, которые должны быть булевыми, БЕЗ ПОТЕРИ верности на любых кривых. Для этого требуется более 800 выборок, необходимых для полигонирования, которые в большинстве случаев не работают с решением Phrogz. Считаете ли вы, что Raphael + AG будет работать намного лучше? –
Мое решение предназначено только для svg-paths, поэтому вам нужно сначала преобразовать другие формы в пути (см. Https://github.com/johan/svg-js-utils/blob/master/paths.js, pathify() -функции). Я считаю, что качество конверсии очень хорошее (потому что вы можете настроить точность с помощью порога угла, а также общий масштабный параметр), используя предлагаемое мной решение. И я также опробовал решение Phrogz, которое является типичным методом грубой силы, и оно медленное, когда формы сложны и производят слишком много или слишком мало очков. Решение Antigrain дает оптимальное количество точек. Что такое AG? –
Я могу попытаться помочь, если увижу достаточно вашего кода. Вы можете связаться со мной, используя [email protected] Возможно, нам лучше продолжить эту дискуссию по электронной почте, и когда решение будет найдено, для публикации необходимых шагов или функций здесь. –