“Mirroring” a PShape object (rotation / translation issue) with Processing












1















I would like to "mirror" a PShape object like in the picture below:



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



I know how to display multiple shapes and how to invert them (screenshot below) but things get complicated when I have to rotate them (and probably translating them) so as they "stick" to the preceding shapes (first picture).



enter image description here



I've been trying to compute an angle with the first 2 vertices of the original shape (irregular quadrilateral) and the atan2() function but to no avail.



I would really appreciate if someone could help figuring how to solve this problem.



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









share|improve this question

























  • If it is possible for your project I would suggest a different approach. Create the final shape to be draw without rotations, but with regular calculus.

    – J.D.
    Jan 2 at 23:41













  • @J.D. Please do, any suggestion is welcomed.

    – solub
    Jan 2 at 23:44
















1















I would like to "mirror" a PShape object like in the picture below:



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



I know how to display multiple shapes and how to invert them (screenshot below) but things get complicated when I have to rotate them (and probably translating them) so as they "stick" to the preceding shapes (first picture).



enter image description here



I've been trying to compute an angle with the first 2 vertices of the original shape (irregular quadrilateral) and the atan2() function but to no avail.



I would really appreciate if someone could help figuring how to solve this problem.



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









share|improve this question

























  • If it is possible for your project I would suggest a different approach. Create the final shape to be draw without rotations, but with regular calculus.

    – J.D.
    Jan 2 at 23:41













  • @J.D. Please do, any suggestion is welcomed.

    – solub
    Jan 2 at 23:44














1












1








1








I would like to "mirror" a PShape object like in the picture below:



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



I know how to display multiple shapes and how to invert them (screenshot below) but things get complicated when I have to rotate them (and probably translating them) so as they "stick" to the preceding shapes (first picture).



enter image description here



I've been trying to compute an angle with the first 2 vertices of the original shape (irregular quadrilateral) and the atan2() function but to no avail.



I would really appreciate if someone could help figuring how to solve this problem.



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









share|improve this question
















I would like to "mirror" a PShape object like in the picture below:



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



I know how to display multiple shapes and how to invert them (screenshot below) but things get complicated when I have to rotate them (and probably translating them) so as they "stick" to the preceding shapes (first picture).



enter image description here



I've been trying to compute an angle with the first 2 vertices of the original shape (irregular quadrilateral) and the atan2() function but to no avail.



I would really appreciate if someone could help figuring how to solve this problem.



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






rotation geometry processing translation






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 0:41







solub

















asked Jan 2 at 23:28









solubsolub

424319




424319













  • If it is possible for your project I would suggest a different approach. Create the final shape to be draw without rotations, but with regular calculus.

    – J.D.
    Jan 2 at 23:41













  • @J.D. Please do, any suggestion is welcomed.

    – solub
    Jan 2 at 23:44



















  • If it is possible for your project I would suggest a different approach. Create the final shape to be draw without rotations, but with regular calculus.

    – J.D.
    Jan 2 at 23:41













  • @J.D. Please do, any suggestion is welcomed.

    – solub
    Jan 2 at 23:44

















If it is possible for your project I would suggest a different approach. Create the final shape to be draw without rotations, but with regular calculus.

– J.D.
Jan 2 at 23:41







If it is possible for your project I would suggest a different approach. Create the final shape to be draw without rotations, but with regular calculus.

– J.D.
Jan 2 at 23:41















@J.D. Please do, any suggestion is welcomed.

– solub
Jan 2 at 23:44





@J.D. Please do, any suggestion is welcomed.

– solub
Jan 2 at 23:44












1 Answer
1






active

oldest

votes


















3














To do what you want you have to create a shape by 2 given angles for the top and the bottom of the shape angleT and `angleB´. The origin (0,0) is in the center of the shape. This causes that the pivots for the rotations are in the middle of the slopes of the shape :





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


When you draw the parts, then you should distinguish between even and odd parts. The parts have to be flipped horizontal by inverting the y axis (scale(1, -1)). The even parts have to be rotated by the double of angleB and the odd parts have to be rotated by the doubled of angleT. For the rotation, the center of the slopes (pivots) have to be translated to the origin:



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


The algorithm works for any angle, positive and negative including 0.







This algorithm can be further improved. Let's assume you have a quad, defined by 4 points (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();
}


Calculate the the minimum, maximum, centerpoint, pivots and angles:





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]);


Draw the shape like before:



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






Another approach would be to stack the shape on both sides:





For this you have to know the heights of the pivots (HC1, HC2) and the angles (angleB, angleT). So this can be implemented based on both of the above approaches.



Define the pivot points and the directions of the top and bottom edge:



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)


Calculate the intersection point (X) of the both edges. Of course this will work only if the

edges are not parallel:





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


The stack algorithm works as follows:



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





share|improve this answer


























  • Hi @Rabbid76, happy new year thanks for the reply. Unfortunately this answer implies that the angle between the 2 irregular vertices of the quadrilateral is fixed, and as a result, that the geometry of the PShape object is not flexible. I should have been more specific but the question is about mirroring any kind of quadrilateral with various angles. See a live example here: vimeo.com/34121761

    – solub
    Jan 3 at 13:23











  • @solub I added a new approach to the answer.

    – Rabbid76
    Jan 5 at 15:48












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54014527%2fmirroring-a-pshape-object-rotation-translation-issue-with-processing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














To do what you want you have to create a shape by 2 given angles for the top and the bottom of the shape angleT and `angleB´. The origin (0,0) is in the center of the shape. This causes that the pivots for the rotations are in the middle of the slopes of the shape :





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


When you draw the parts, then you should distinguish between even and odd parts. The parts have to be flipped horizontal by inverting the y axis (scale(1, -1)). The even parts have to be rotated by the double of angleB and the odd parts have to be rotated by the doubled of angleT. For the rotation, the center of the slopes (pivots) have to be translated to the origin:



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


The algorithm works for any angle, positive and negative including 0.







This algorithm can be further improved. Let's assume you have a quad, defined by 4 points (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();
}


Calculate the the minimum, maximum, centerpoint, pivots and angles:





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]);


Draw the shape like before:



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






Another approach would be to stack the shape on both sides:





For this you have to know the heights of the pivots (HC1, HC2) and the angles (angleB, angleT). So this can be implemented based on both of the above approaches.



Define the pivot points and the directions of the top and bottom edge:



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)


Calculate the intersection point (X) of the both edges. Of course this will work only if the

edges are not parallel:





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


The stack algorithm works as follows:



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





share|improve this answer


























  • Hi @Rabbid76, happy new year thanks for the reply. Unfortunately this answer implies that the angle between the 2 irregular vertices of the quadrilateral is fixed, and as a result, that the geometry of the PShape object is not flexible. I should have been more specific but the question is about mirroring any kind of quadrilateral with various angles. See a live example here: vimeo.com/34121761

    – solub
    Jan 3 at 13:23











  • @solub I added a new approach to the answer.

    – Rabbid76
    Jan 5 at 15:48
















3














To do what you want you have to create a shape by 2 given angles for the top and the bottom of the shape angleT and `angleB´. The origin (0,0) is in the center of the shape. This causes that the pivots for the rotations are in the middle of the slopes of the shape :





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


When you draw the parts, then you should distinguish between even and odd parts. The parts have to be flipped horizontal by inverting the y axis (scale(1, -1)). The even parts have to be rotated by the double of angleB and the odd parts have to be rotated by the doubled of angleT. For the rotation, the center of the slopes (pivots) have to be translated to the origin:



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


The algorithm works for any angle, positive and negative including 0.







This algorithm can be further improved. Let's assume you have a quad, defined by 4 points (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();
}


Calculate the the minimum, maximum, centerpoint, pivots and angles:





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]);


Draw the shape like before:



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






Another approach would be to stack the shape on both sides:





For this you have to know the heights of the pivots (HC1, HC2) and the angles (angleB, angleT). So this can be implemented based on both of the above approaches.



Define the pivot points and the directions of the top and bottom edge:



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)


Calculate the intersection point (X) of the both edges. Of course this will work only if the

edges are not parallel:





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


The stack algorithm works as follows:



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





share|improve this answer


























  • Hi @Rabbid76, happy new year thanks for the reply. Unfortunately this answer implies that the angle between the 2 irregular vertices of the quadrilateral is fixed, and as a result, that the geometry of the PShape object is not flexible. I should have been more specific but the question is about mirroring any kind of quadrilateral with various angles. See a live example here: vimeo.com/34121761

    – solub
    Jan 3 at 13:23











  • @solub I added a new approach to the answer.

    – Rabbid76
    Jan 5 at 15:48














3












3








3







To do what you want you have to create a shape by 2 given angles for the top and the bottom of the shape angleT and `angleB´. The origin (0,0) is in the center of the shape. This causes that the pivots for the rotations are in the middle of the slopes of the shape :





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


When you draw the parts, then you should distinguish between even and odd parts. The parts have to be flipped horizontal by inverting the y axis (scale(1, -1)). The even parts have to be rotated by the double of angleB and the odd parts have to be rotated by the doubled of angleT. For the rotation, the center of the slopes (pivots) have to be translated to the origin:



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


The algorithm works for any angle, positive and negative including 0.







This algorithm can be further improved. Let's assume you have a quad, defined by 4 points (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();
}


Calculate the the minimum, maximum, centerpoint, pivots and angles:





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]);


Draw the shape like before:



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






Another approach would be to stack the shape on both sides:





For this you have to know the heights of the pivots (HC1, HC2) and the angles (angleB, angleT). So this can be implemented based on both of the above approaches.



Define the pivot points and the directions of the top and bottom edge:



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)


Calculate the intersection point (X) of the both edges. Of course this will work only if the

edges are not parallel:





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


The stack algorithm works as follows:



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





share|improve this answer















To do what you want you have to create a shape by 2 given angles for the top and the bottom of the shape angleT and `angleB´. The origin (0,0) is in the center of the shape. This causes that the pivots for the rotations are in the middle of the slopes of the shape :





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


When you draw the parts, then you should distinguish between even and odd parts. The parts have to be flipped horizontal by inverting the y axis (scale(1, -1)). The even parts have to be rotated by the double of angleB and the odd parts have to be rotated by the doubled of angleT. For the rotation, the center of the slopes (pivots) have to be translated to the origin:



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


The algorithm works for any angle, positive and negative including 0.







This algorithm can be further improved. Let's assume you have a quad, defined by 4 points (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();
}


Calculate the the minimum, maximum, centerpoint, pivots and angles:





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]);


Draw the shape like before:



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






Another approach would be to stack the shape on both sides:





For this you have to know the heights of the pivots (HC1, HC2) and the angles (angleB, angleT). So this can be implemented based on both of the above approaches.



Define the pivot points and the directions of the top and bottom edge:



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)


Calculate the intersection point (X) of the both edges. Of course this will work only if the

edges are not parallel:





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


The stack algorithm works as follows:



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






share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 5 at 15:44

























answered Jan 3 at 8:05









Rabbid76Rabbid76

42.9k123354




42.9k123354













  • Hi @Rabbid76, happy new year thanks for the reply. Unfortunately this answer implies that the angle between the 2 irregular vertices of the quadrilateral is fixed, and as a result, that the geometry of the PShape object is not flexible. I should have been more specific but the question is about mirroring any kind of quadrilateral with various angles. See a live example here: vimeo.com/34121761

    – solub
    Jan 3 at 13:23











  • @solub I added a new approach to the answer.

    – Rabbid76
    Jan 5 at 15:48



















  • Hi @Rabbid76, happy new year thanks for the reply. Unfortunately this answer implies that the angle between the 2 irregular vertices of the quadrilateral is fixed, and as a result, that the geometry of the PShape object is not flexible. I should have been more specific but the question is about mirroring any kind of quadrilateral with various angles. See a live example here: vimeo.com/34121761

    – solub
    Jan 3 at 13:23











  • @solub I added a new approach to the answer.

    – Rabbid76
    Jan 5 at 15:48

















Hi @Rabbid76, happy new year thanks for the reply. Unfortunately this answer implies that the angle between the 2 irregular vertices of the quadrilateral is fixed, and as a result, that the geometry of the PShape object is not flexible. I should have been more specific but the question is about mirroring any kind of quadrilateral with various angles. See a live example here: vimeo.com/34121761

– solub
Jan 3 at 13:23





Hi @Rabbid76, happy new year thanks for the reply. Unfortunately this answer implies that the angle between the 2 irregular vertices of the quadrilateral is fixed, and as a result, that the geometry of the PShape object is not flexible. I should have been more specific but the question is about mirroring any kind of quadrilateral with various angles. See a live example here: vimeo.com/34121761

– solub
Jan 3 at 13:23













@solub I added a new approach to the answer.

– Rabbid76
Jan 5 at 15:48





@solub I added a new approach to the answer.

– Rabbid76
Jan 5 at 15:48




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54014527%2fmirroring-a-pshape-object-rotation-translation-issue-with-processing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

A Topological Invariant for $pi_3(U(n))$