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

Alexey_Nik

Топикстартер
12 лет на форуме
Сообщения
37
Реакции
41
Добрый день. Подскажите, есть ли скрипт для выравнивания углов у элементов под 90 градусов?
degrees Correction.png
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
Задача, как вы понимаете, не всегда имеет решение. Скажем, для треугольника его нету. И где та грань, начиная с которой угол можно приводить к прямому без ущерба для формы?
 

Alexey_Nik

Топикстартер
12 лет на форуме
Сообщения
37
Реакции
41
Это я все понимаю. Мне надо для прямоугольника.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
Ну даже если так. Вовсе не любой четырехугольник без ущерба формы можно до прямоугольника деформировать, причем, неоднозначно. Это ж фактически, задача распознавания образов.
 

~RA~

Одарённая.
12 лет на форуме
Сообщения
11 808
Реакции
3 434
Опишите алгоритм. Например для паралеллограмма.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835

~RA~

Одарённая.
12 лет на форуме
Сообщения
11 808
Реакции
3 434
Четырехугольники бывают и невыпуклые ;)
ТС начнёт составлять ТЗ на самый простой случай и поймёт, что их бесконечное количество. После чего ыормалищует ТЗ до приемлемого. Я так надеюсь. ;)
 

Alexey_Nik

Топикстартер
12 лет на форуме
Сообщения
37
Реакции
41
Вопрос решен.
Может кому пригодится:
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~

NatalieRedFox_333

Чего мне бояться? - подумала Красная Шапочка...)))
Сообщения
2 089
Реакции
145
Вопрос решен.
Может кому пригодится:
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'
 
Последнее редактирование:

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
Вопрос решен.
Может кому пригодится:
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();
Это мухлеж и надувательство! '))' с таким же успехом можно по двум точкам достраивать прямоугольник
 

Alexey_Nik

Топикстартер
12 лет на форуме
Сообщения
37
Реакции
41
Это мухлеж и надувательство! '))' с таким же успехом можно по двум точкам достраивать прямоугольник
Достроить не получится, к сожалению. Все уже нарисовано. Надо просто выровнять прямоугольники.
Вот для чего это надо:
есть более 100 карт с нарисованными не совсем ровно домиками, заказчик просит их поправить.
02.png
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
Этот скрипт вам в этом не поможет. Его смысл - выровнять два последних узла по двум первым. Поскольку порядок узлов случаен, то если хотя бы один из первых двух узлов стоит неправильно, то ваши домики после применения скрипта сильно поменяют ориентацию.
 
  • Спасибо
Реакции: Gad

Alexey_Nik

Топикстартер
12 лет на форуме
Сообщения
37
Реакции
41
Этот скрипт вам в этом не поможет. Его смысл - выровнять два последних узла по двум первым. Поскольку порядок узлов случаен, то если хотя бы один из первых двух узлов стоит неправильно, то ваши домики после применения скрипта сильно поменяют ориентацию.
Могу не согласиться. Прямоугольники стали с прямыми углами. Единственный недостаток - немного меняется угол расположения домиков, но это ручками не долго делать.
Добавил пару строк.
Код:
// ----------------------------------------------
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

_MBK_

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