Twisted quads vs. Expressive quads

Hi there!

These days i have been working with quads and some Users have gave me different solutions for my problems.

One of my biggest problems is that some of my random quads are twisted. With new ways of drawing quads learned this week that is solved, but I lose the expressivity of these shapes.

Fixing number 1 and number 2 I don’t get any more shapes as number 3 and number 4, and it is Big Lost for a designer. How could I avoid twisted quads without losing these dynamic quads?

Thank you so much for your help!

1 Like

I have not seen your previous posts so I don’t know what solutions have been provided so there might be some duplication here.

Twisted Quads
When drawing a quad we have to provide the coordinates for the 4 vertices. For a human that would be enough but for a computer we must specify the order they should be processed. Traditionally the approach is to start with one vertex and then order them by tracing the shape anticlockwise. In this picture we use the same coordinates for the vertices but change the order they are processed.
quad_vertex_order
The wrong order can cause two sides to intersect creating a twisted quad.

Convex vs concave polygons
In your picture you call shapes 3 and 4 expressive / dynamic quads but the correct description is ‘concave polygons’. A quad is simply a 4 sided polygon and what I say applies to any polygon of 4 or more sides.
This picture shows a convex polygon on the left and a concave polygon on the right.
quad_convex_concave
A polygon is concave if at least one internal angle is greater than 180 degrees and is convex if all internal angles are less than 180 degrees.
Now how the convex polygon is drawn depends on the renderer, for instance the above picture was drawn using Java2D (default option in Processing) whilst the following picture uses OpenGL (P2D mode in Processing), notice the difference.
quad_convex_concave
I don’t know if there is a setting in OpenGL to change its behaviour but I have provided the sketch code below for you to play with.

Another way to render concave polygons is to split it into triangles and render them instead. I use this approach in the Shapes3D library but the code is fairly complex.

// Convex versus concave quads
// Drawing with OpenGL and Java2D
PVector[] convex = {
  new PVector(30, 30), 
  new PVector(60, 280), 
  new PVector(250, 270), 
  new PVector(220, 60)
};
PVector[] concave = {
  new PVector(30, 30), 
  new PVector(160, 280), 
  new PVector(250, 90), 
  new PVector(140, 200)
};

void setup() {
  size(600, 300, P2D);
  textSize(24);
  background(255);
  fill(255, 255, 0);
  stroke(128, 128, 0);
  strokeWeight(2);
  drawQuad(convex);
  translate(width/2, 0);
  drawQuad(concave);
  save("quad_convex_concave.png");
}

void drawQuad(PVector[] v) {
  beginShape(QUADS);
  fill(255, 255, 0);
  for (int i = 0; i < 4; i++) {
    vertex(v[i].x, v[i].y);
  }
  endShape(CLOSE);
}
2 Likes

As discussed in your previous post

there are multiple ways to add randomness to a set of points that are not twisted. If you are growing out in four quadrant directions, you won’t give you every possible random quad – but it has a lot of variation, but concave shapes will be quite rare.

One way to get more frequent and “expressive” concave shapes is to do random points (or a random walk of points) and test for line-line intersection to detect invalid crossings.

I see what you’re after. Setting the minSize to 0 and using this adapted version of the method we showed you in the other thread, where here the angle is increased randomly again, like @jb4x initially did for you gets an effect that’s pretty close I think?

void drawMoreRandomQuad(float x, float y, float minSize, float maxSize) 
{  
  float startAngle = random(HALF_PI); // random start angle for each quad
  float angle = startAngle;
  
  beginShape();
  for (int i = 0; i < 4; i++) {
    // imagine that we're going round a circle, stopping at 4 points along the circle
    float r = random(minSize, maxSize); // choose a different distance from the centre for each point
    float vx = x + r * cos(angle); // look up trigonometry on wikipedia
    float vy = y + r * sin(angle);
    vertex(vx, vy);
    
    // increment angle with a random amount
    angle += random(0, min(startAngle + TWO_PI - angle, PI));
  }
  endShape(CLOSE);
}
2 Likes

Consider the following image:

It represents all the possible order/configuration your points can have (minus edge cases with colinear points).

Based on this you can check the following intersection:

  • [1, 2] and [3, 4]
    They intersect in cases C and D
    Swap points 2 and 3 to untwist the quad
  • [1, 4] and [2, 3]
    They intersect in cases B and F
    Swap points 1 and 2 to untwist the quad

For segment/segment intersection, you can have a look here.

I let you figure out how to deal with the edge cases.

Again, you’ve made three topics around the same subject. It’s better to keep related questions in one thread, rather than make different ones where people are answering very similar things.

Sorry, some questions were appearing while i was trying different ways, but I will try to do It better Next time