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

@roymacdonald thanks for the suggestion. i’ve implemented, and switched to ofPath because i wanted to draw a filled path. with an outline this works verry well, but with filled path i get the error shown in the picture… any suggestions how to fix this?

screenshot

Hi @makakken ,
ofPath works internally in a slightly different way as ofPolyline does, yet the the curve to thing should be the same. The issue seen here is that when you close the shape it will throw a straight line from the end to the begining, and since you had to add more points at the end it is just throwing these two points are not the same.
The big difference between ofPath and ofPolyline is that the former stores commands, as which then it renders into ofPolylines and then into a mesh that is rendered.
Take a look inside ofPath.cpp.
I guess that you need to fiddle a bit with how you add the first and last points.
or maybe the addon taht @ayruos mentions can do the job.