[AI CC-CC2022] Скрипт для коррекции углов под 90 градусов

  • Автор темы Автор темы Alexey_Nik
  • Дата начала Дата начала

Alexey_Nik

Топикстартер
12 лет на форуме
Сообщения
37
Реакции
42
Добрый день. Подскажите, есть ли скрипт для выравнивания углов у элементов под 90 градусов?
degrees Correction.png
 
Задача, как вы понимаете, не всегда имеет решение. Скажем, для треугольника его нету. И где та грань, начиная с которой угол можно приводить к прямому без ущерба для формы?
 
Это я все понимаю. Мне надо для прямоугольника.
 
Ну даже если так. Вовсе не любой четырехугольник без ущерба формы можно до прямоугольника деформировать, причем, неоднозначно. Это ж фактически, задача распознавания образов.
 
Опишите алгоритм. Например для паралеллограмма.
 
Четырехугольники бывают и невыпуклые ;)
ТС начнёт составлять ТЗ на самый простой случай и поймёт, что их бесконечное количество. После чего ыормалищует ТЗ до приемлемого. Я так надеюсь. ;)
 
Вопрос решен.
Может кому пригодится:
JavaScript:
// ----------------------------------------------
function main(){
    var paths = [];
    if(documents.length < 1) return;   
    var paths = activeDocument.selection;
    var paths2 = [];
    for(var i = 0; i < paths.length; i++){
        var dup = paths[i].duplicate();     
        if(convertToDegress_90(dup)){         
            paths2.push(dup);
            paths[i].remove();
        } else {
            dup.remove();
        }
    }
    if(paths2.length > 0){
        activeDocument.selection = paths2;
    }
}

// ----------------------------------------------
function convertToDegress_90(pi) {
    // количество точек
    if (pi.typename == "PathItem") {
        var p = pi.pathPoints;
        // 4 точки
        if (p.length == 4) {
            // первая точка
            var a0 = p[0].anchor;
            p[0].pointType = PointType.CORNER;
            p[0].leftDirection = a0;
            p[0].rightDirection = a0;
            // вторая точка
            var a1 = p[1].anchor;
            p[1].pointType = PointType.CORNER;
            p[1].leftDirection = a1;
            p[1].rightDirection = a1;

            var a2 = p[2].anchor;

            var l1 = dist(a0, a1);
            var l2 = dist(a1, a2);

            var r01 = [];
            r01[0] = a1[0] + ((l2 * (a1[1] - a0[1]) / l1));
            r01[1] = a1[1] + ((l2 * (a0[0] - a1[0]) / l1));

            // третья точка
            p[2].anchor = r01;
            p[2].pointType = PointType.CORNER;
            p[2].leftDirection = r01;
            p[2].rightDirection = r01;

            a2 = p[2].anchor;
            l2 = dist(a1, a2);

            r01[0] = a2[0] + ((l1 * (a2[1] - a1[1]) / l2));
            r01[1] = a2[1] + ((l1 * (a1[0] - a2[0]) / l2));

            // четвертая точка
            p[3].anchor = r01;
            p[3].pointType = PointType.CORNER;
            p[3].leftDirection = r01;
            p[3].rightDirection = r01;
            
            return true
        }
    }
    return false;
}

// ----------------------------------------------
// расстояние между точками p1 [x,y], p2 [x,y]
function dist(p1, p2) {
    return Math.sqrt(Math.pow(p1[0] - p2[0],2) + Math.pow(p1[1] - p2[1],2));
  }

main();
 
  • Спасибо
Реакции: Gad и ~RA~
Вопрос решен.
Может кому пригодится:
JavaScript:
// ----------------------------------------------
function main(){
    var paths = [];
    if(documents.length < 1) return;
    var paths = activeDocument.selection;
    var paths2 = [];
    for(var i = 0; i < paths.length; i++){
        var dup = paths[i].duplicate();  
        if(convertToDegress_90(dup)){      
            paths2.push(dup);
            paths[i].remove();
        } else {
            dup.remove();
        }
    }
    if(paths2.length > 0){
        activeDocument.selection = paths2;
    }
}

// ----------------------------------------------
function convertToDegress_90(pi) {
    // количество точек
    if (pi.typename == "PathItem") {
        var p = pi.pathPoints;
        // 4 точки
        if (p.length == 4) {
            // первая точка
            var a0 = p[0].anchor;
            p[0].pointType = PointType.CORNER;
            p[0].leftDirection = a0;
            p[0].rightDirection = a0;
            // вторая точка
            var a1 = p[1].anchor;
            p[1].pointType = PointType.CORNER;
            p[1].leftDirection = a1;
            p[1].rightDirection = a1;

            var a2 = p[2].anchor;

            var l1 = dist(a0, a1);
            var l2 = dist(a1, a2);

            var r01 = [];
            r01[0] = a1[0] + ((l2 * (a1[1] - a0[1]) / l1));
            r01[1] = a1[1] + ((l2 * (a0[0] - a1[0]) / l1));

            // третья точка
            p[2].anchor = r01;
            p[2].pointType = PointType.CORNER;
            p[2].leftDirection = r01;
            p[2].rightDirection = r01;

            a2 = p[2].anchor;
            l2 = dist(a1, a2);

            r01[0] = a2[0] + ((l1 * (a2[1] - a1[1]) / l2));
            r01[1] = a2[1] + ((l1 * (a1[0] - a2[0]) / l2));

            // четвертая точка
            p[3].anchor = r01;
            p[3].pointType = PointType.CORNER;
            p[3].leftDirection = r01;
            p[3].rightDirection = r01;
         
            return true
        }
    }
    return false;
}

// ----------------------------------------------
// расстояние между точками p1 [x,y], p2 [x,y]
function dist(p1, p2) {
    return Math.sqrt(Math.pow(p1[0] - p2[0],2) + Math.pow(p1[1] - p2[1],2));
  }

main();

а для чего это надо с практической стороны....? непонятно.. 'otbline'
 
Последнее редактирование:
Вопрос решен.
Может кому пригодится:
JavaScript:
// ----------------------------------------------
function main(){
    var paths = [];
    if(documents.length < 1) return; 
    var paths = activeDocument.selection;
    var paths2 = [];
    for(var i = 0; i < paths.length; i++){
        var dup = paths[i].duplicate();   
        if(convertToDegress_90(dup)){       
            paths2.push(dup);
            paths[i].remove();
        } else {
            dup.remove();
        }
    }
    if(paths2.length > 0){
        activeDocument.selection = paths2;
    }
}

// ----------------------------------------------
function convertToDegress_90(pi) {
    // количество точек
    if (pi.typename == "PathItem") {
        var p = pi.pathPoints;
        // 4 точки
        if (p.length == 4) {
            // первая точка
            var a0 = p[0].anchor;
            p[0].pointType = PointType.CORNER;
            p[0].leftDirection = a0;
            p[0].rightDirection = a0;
            // вторая точка
            var a1 = p[1].anchor;
            p[1].pointType = PointType.CORNER;
            p[1].leftDirection = a1;
            p[1].rightDirection = a1;

            var a2 = p[2].anchor;

            var l1 = dist(a0, a1);
            var l2 = dist(a1, a2);

            var r01 = [];
            r01[0] = a1[0] + ((l2 * (a1[1] - a0[1]) / l1));
            r01[1] = a1[1] + ((l2 * (a0[0] - a1[0]) / l1));

            // третья точка
            p[2].anchor = r01;
            p[2].pointType = PointType.CORNER;
            p[2].leftDirection = r01;
            p[2].rightDirection = r01;

            a2 = p[2].anchor;
            l2 = dist(a1, a2);

            r01[0] = a2[0] + ((l1 * (a2[1] - a1[1]) / l2));
            r01[1] = a2[1] + ((l1 * (a1[0] - a2[0]) / l2));

            // четвертая точка
            p[3].anchor = r01;
            p[3].pointType = PointType.CORNER;
            p[3].leftDirection = r01;
            p[3].rightDirection = r01;
          
            return true
        }
    }
    return false;
}

// ----------------------------------------------
// расстояние между точками p1 [x,y], p2 [x,y]
function dist(p1, p2) {
    return Math.sqrt(Math.pow(p1[0] - p2[0],2) + Math.pow(p1[1] - p2[1],2));
  }

main();
Это мухлеж и надувательство! '))' с таким же успехом можно по двум точкам достраивать прямоугольник
 
Это мухлеж и надувательство! '))' с таким же успехом можно по двум точкам достраивать прямоугольник
Достроить не получится, к сожалению. Все уже нарисовано. Надо просто выровнять прямоугольники.
Вот для чего это надо:
есть более 100 карт с нарисованными не совсем ровно домиками, заказчик просит их поправить.
02.png
 
Этот скрипт вам в этом не поможет. Его смысл - выровнять два последних узла по двум первым. Поскольку порядок узлов случаен, то если хотя бы один из первых двух узлов стоит неправильно, то ваши домики после применения скрипта сильно поменяют ориентацию.
 
  • Спасибо
Реакции: Gad
Этот скрипт вам в этом не поможет. Его смысл - выровнять два последних узла по двум первым. Поскольку порядок узлов случаен, то если хотя бы один из первых двух узлов стоит неправильно, то ваши домики после применения скрипта сильно поменяют ориентацию.
Могу не согласиться. Прямоугольники стали с прямыми углами. Единственный недостаток - немного меняется угол расположения домиков, но это ручками не долго делать.
Добавил пару строк.
Код:
// ----------------------------------------------
function main(){
    var paths = [];
    if(documents.length < 1) return;   
    var paths = activeDocument.selection;
    var paths2 = [];
    for(var i = 0; i < paths.length; i++){
        var dup = paths[i].duplicate();     
        if(convertToDegress_90(dup)){         
            paths2.push(dup);
            paths[i].remove();
        } else {
            dup.remove();
        }
    }
    if(paths2.length > 0){
        activeDocument.selection = paths2;
    }
}

// ----------------------------------------------
function convertToDegress_90(pi) {
    // количество точек
    if (pi.typename == "PathItem") {
        var p = pi.pathPoints;
        // 4 точки
        if (p.length == 4) {
            var poz = pi.position;
            // первая точка
            var a0 = p[0].anchor;
            setPoint(p[0], a0);

            // вторая точка
            var a1 = p[1].anchor;
            setPoint(p[1], a1);

            var a2 = p[2].anchor;
            var l1 = dist(a0, a1);
            var l2 = dist(a1, a2);

            var r01 = [];
            r01[0] = a1[0] + ((l2 * (a1[1] - a0[1]) / l1));
            r01[1] = a1[1] + ((l2 * (a0[0] - a1[0]) / l1));

            // третья точка
            setPoint(p[2], r01);

            a2 = p[2].anchor;
            l2 = dist(a1, a2);

            r01[0] = a2[0] + ((l1 * (a2[1] - a1[1]) / l2));
            r01[1] = a2[1] + ((l1 * (a1[0] - a2[0]) / l2));

            // четвертая точка
            setPoint(p[3], r01);

            pi.position = poz;
            
            return true
        }
    }
    return false;
}
// ----------------------------------------------
// параметры точки
function setPoint(p, z){
    p.anchor = z;
    p.pointType = PointType.CORNER;
    p.leftDirection = z;
    p.rightDirection = z; 
}

// ----------------------------------------------
// расстояние между точками p1 [x,y], p2 [x,y]
function dist(p1, p2) {
    return Math.sqrt(Math.pow(p1[0] - p2[0],2) + Math.pow(p1[1] - p2[1],2));
  }

main();
 
  • Спасибо
Реакции: aporiy zenonov
По хорошему, формулировка вашей задачи сильно далека от топиковой и звучит она так: "построить прямоугольник максимально похожий на заданную фигуру"
И да, это задача распознавания образов. Алгоритм решения, в идеальном случае многошаговый итерационный, в самом упрощенном случае (ну, например, в качестве первого приближения для итераций) - построить среднюю линию, скажем, методом наименьших квадратов, затем достроить на базе нее прямоугольник заданной площади. Скорее всего, результат будет уже удовлетворительным (как минимум, не таким безумным, как после применения вышеописанного скрипта) если же нет - начать оптимизационный процесс, скажем, по среднеквадратичному отклонению между координатами вершин, хотя, для универсального случая (неЧетырехкгольника) это не годится. Ну тогда по площади разницы между исходной фигурой и полученным прямоугольником. Подобным образом можно хоть с растрового изображения прямоугольники счмтывать, почему бы и нет?