Organic Shapes without Edges

Hello, i try to create a Circular Shape which can be distorted, so i calculate some Vertex of the Circle and Connect the with curveTo(). I have an Edge in the Shape like in the Screenshot. How to calculate a shape without any Edge (organic Blob)? Is there a good way to do it? I know i can fix in some special cases, but i want a solution that works in every case :wink:

Screenshots added


my current code can be found here: https://github.com/makakken/jitteredCircle/blob/master/src/ofApp.cpp#L100

@zach is the master of blobs and shapes like that. Probably he can give you a good advice.
On the mean while, ofPolyline’s curveTo uses a curve algorithm which need 4 points in order to draw a line between two of these (the middle ones). So in order to close your line smoothly you need to add the first 3 points you added to the line at the end of it.
Take a look at this modified version of your code

#pragma once

#include "ofMain.h"
#include "ofxGui.h"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void keyPressed(int key);
		void mousePressed(int x, int y, int button);

	ofxPanel gui;
	
	ofParameter<float> diameter;
	ofParameter<float> jitter;
	ofParameter<float> jitter_percent;
     
	
	vector<ofPolyline> lines;
	
	ofPolyline noiseCircle(int cx, int cy, int r, int num) ;

	vector<glm::vec3> points;
	ofPolyline poly;
	
}
;
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
     ofBackground(128);
     
     gui.setup();
     gui.add(diameter.set("Element Diameter",70,1,500));
     gui.add(jitter.set("Jitter",.15,.01,1));
     gui.add(jitter_percent.set("JitterPercent",0.001,0,1));
     
     
}
//--------------------------------------------------------------
void ofApp::draw(){
    
    ofEnableAlphaBlending();
    ofBackground(0);
    ofSetColor( ofColor(255));
    for(auto &line : lines) {
        line.draw();
		
		ofPushStyle();
		ofNoFill();
		ofSetColor(ofColor::red);
		ofDrawCircle(line.getVertices().front(), 40);
		ofSetColor(ofColor::yellow);
		ofDrawCircle(line.getVertices().back(), 50);
		ofPopStyle();
		
    }
    
	ofPushStyle();
	ofNoFill();
	ofSetColor(ofColor::cyan);
	poly.draw();
	ofSetColor(ofColor::white);
	for(auto& p: points)
	{
		ofDrawCircle(p, 30);
	}
	ofPopStyle();

	
	
    gui.draw();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    
    if(key == 'c') {
        lines.clear();
    }
    if(key == 'a') {
        lines.push_back(noiseCircle(300, 300, diameter, 24));
    }
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
	points.push_back(glm::vec3(x,y,0));
	poly.curveTo(x, y);
}
//--------------------------------------------------------------
ofPolyline ofApp::noiseCircle(int cx, int cy, int r, int num) {
    ofPolyline line;
    float a = TWO_PI / num;
	vector<ofVec3f> linePoints;
    for (int i = 0; i < num; i++) {
        float rand = ofRandom(-1 * jitter, jitter);
        int x = r * (1-rand) * cos(a*(i+rand));
        int y = r * (1-rand) * sin(a*(i+rand));
        ofVec3f v = ofVec3f(x,y,0);
        // line.addVertex(v);
		line.curveTo(v);
		linePoints.push_back(v);
    }
	if(num > 4)
	{
		for(int i = 0 ; i < 3; i++)
		{
			
			line.curveTo(linePoints[i]);
		}
	}
    line.close();
    float s = ofRandom(0,jitter_percent) + 1;
    line.scale(s,s-0.01);
    line.rotateDeg(45, ofVec3f(0,0,1));
    line.translate(ofVec3f(cx,cy,0));
    return line;
}

you can clearly see the behavior of the curveTo function by clicking with the mouse. After adding a some points, if you clic over the first 3 added points you will see how it closes smoothly.
hope this helps

On top of what @roymacdonald said, this might be useful, I use this all the time for my own projects.

1 Like