Nano Hash - криптовалюты, майнинг, программирование

Отражение объекта PShape (проблема вращения/перемещения) с обработкой

Я хотел бы «отзеркалить» объект PShape, как показано на рисунке ниже:

https://i.imgur.com/kwTQ7vA.png

Я знаю, как отображать несколько фигур и как их инвертировать (скриншот ниже), но все усложняется, когда мне приходится их вращать (и, возможно, переводить), чтобы они «прилипали» к предыдущим фигурам (первое изображение).

введите здесь описание изображения

Я пытался вычислить угол с первыми двумя вершинами исходной формы (неправильный четырехугольник) и функцией atan2(), но безрезультатно.

Я был бы очень признателен, если бы кто-то помог понять, как решить эту проблему.

int W = 20;
int H = 20;
int D = 20; 

PShape object;


void setup(){
    size(600, 600, P2D);
    smooth();

}


void draw(){
    background(255);

    pushMatrix();
    translate(width/2, height/1.3);

    int td = -1;
    for (int i = 0; i < 6; i++){
        translate(0, td*H*2);
        scale(-1, 1);
        rotate(PI);
        object();
        td *= -1;
    }


    popMatrix();

}


void object() {
    beginShape(QUADS);

    vertex(-20,  20);
    vertex(20,  0);
    vertex(20, -20);
    vertex(-20, -20);

    endShape();
}

  • Если это возможно для вашего проекта, я бы предложил другой подход. Создайте окончательную форму для рисования без поворотов, но с обычным исчислением. 03.01.2019
  • @Дж.Д. Пожалуйста, любые предложения приветствуются. 03.01.2019

Ответы:


1

Чтобы сделать то, что вы хотите, вы должны создать фигуру с двумя заданными углами для вершины и низа фигуры angleT и `угол B`. Начало (0,0) находится в центре фигуры. Это приводит к тому, что точки поворота находятся в середине наклонов формы:

int W = 40;
int H = 40;
float angleT = -PI/18;
float angleB = PI/15;

PShape object;

void object() {

    float H1 = -H/2 + W*tan(angleB);
    float H2 = H/2 + W*tan(angleT);

    beginShape(QUADS);

    vertex(-W/2,  -H/2);
    vertex(W/2, H1);
    vertex(W/2, H2);
    vertex(-W/2, H/2);

    endShape();
}

Когда вы рисуете части, вы должны различать четные и нечетные части. Детали должны быть отражены горизонтально, инвертируя ось Y (scale(1, -1)). Четные части должны быть повернуты на удвоение angleB, а нечетные части должны быть повернуты на удвоение angleT. Для поворота центр наклонов (поворотов) необходимо перевести в начало координат:

void setup(){
    size(600, 600, P2D);
    smooth();
}

void draw(){

    background(255);

    translate(width/2, height/2);

    float HC1 = -H/2 + W*tan(angleB)/2;
    float HC2 = H/2 + W*tan(angleT)/2;

    for (int i = 0; i < 15; i++){

        float angle = (i % 2 == 0) ? -angleB : -angleT;
        float HC    = (i % 2 == 0) ? HC1 : HC2; 

        translate(0, -HC);
        rotate(angle*2);
        translate(0, -HC);

        object();
        scale(1, -1);
    }
}

Алгоритм работает для любого угла, положительного и отрицательного, включая 0.


Этот алгоритм можно еще улучшить. Предположим, у вас есть четырехугольник, определяемый 4 точками (p0, p1, p2, p3):

float[] p0 = {10, 0};
float[] p1 = {40, 10};
float[] p2 = {60, 45};
float[] p3 = {0, 60};

PShape object;

void object() {
    beginShape(QUADS);
    vertex(p0[0], p0[1]);
    vertex(p1[0], p1[1]);
    vertex(p2[0], p2[1]);
    vertex(p3[0], p3[1]);
    endShape();
}

Рассчитайте минимум, максимум, центральную точку, точки поворота и углы:

float minX = min( min(p0[0], p1[0]), min(p2[0], p3[0]) );
float maxX = max( max(p0[0], p1[0]), max(p2[0], p3[0]) );
float minY = min( min(p0[1], p1[1]), min(p2[1], p3[1]) );
float maxY = max( max(p0[1], p1[1]), max(p2[1], p3[1]) );

float cptX = (minX+maxX)/2;
float cptY = (minY+maxY)/2;

float angleB = atan2(p1[1]-p0[1], p1[0]-p0[0]);
float angleT = atan2(p2[1]-p3[1], p2[0]-p3[0]);

float HC1 = p0[1] + (p1[1]-p0[1])*(cptX-p0[0])/(p1[0]-p0[0]);
float HC2 = p3[1] + (p2[1]-p3[1])*(cptX-p3[0])/(p2[0]-p3[0]);

Нарисуйте форму, как раньше:

for (int i = 0; i < 6; i++){

    float angle = (i % 2 == 0) ? -angleB : -angleT;
    float HC    = (i % 2 == 0) ? HC1 : HC2; 

    translate(cptX, -HC);
    rotate(angle*2);
    translate(-cptX, -HC);

    object();
    scale(1, -1);
}


Другой подход состоит в том, чтобы сложить фигуру с обеих сторон:

Для этого вам нужно знать высоты точек вращения (HC1, HC2) и углы (angleB, angleT). Таким образом, это может быть реализовано на основе обоих вышеперечисленных подходов.

Определите точки поворота и направления верхнего и нижнего края:

PVector dir1 = new PVector(cos(angleB), sin(angleB));
PVector dir2 = new PVector(cos(angleT), sin(angleT));
PVector pv1  = new PVector(0, HC1); // or PVector(cptX, HC1)
PVector pv2  = new PVector(0, HC2); // or PVector(cptX, HC2)

Вычислите точку пересечения (X) обоих ребер. Конечно, это будет работать только в том случае, если края
не параллельны:

PVector v12  = pv2.copy().sub(pv1);
PVector nDir = new PVector(dir2.y, -dir2.x);
float   d    = v12.dot(nDir) / dir1.dot(nDir);
PVector X    = pv1.copy().add( dir1.copy().mult(d) );

Алгоритм стека работает следующим образом:

for (int i = 0; i < 8; i++){

    float fullAngle = angleT-angleB;

    float angle = fullAngle * floor(i/2);
    if ((i/2) % 2 != 0)
       angle += fullAngle; 
    if (i % 2 != 0)
        angle = -angle; 

    float flip = 1.0;
    if (i % 2 != 0)
        flip *= -1.0;
    if ((i/2) % 2 != 0)
        flip *= -1.0;

    pushMatrix();  

    translate(X.x, X.y);
    rotate(angle);
    scale(1, flip);
    rotate(-angleB);
    translate(-X.x, -X.y); 

    object();

    popMatrix();
}
03.01.2019
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..