PShape

Data / Composite

Description

Datatype for storing shapes. Load with loadShape() or build programmatically with createShape().

Syntax

PShape* s = loadShape("file.svg") PShape s = createShape()

Parameters

None

Returns

PShape

Methods

getChild(int i)Get child shape by index
getChild(std::string name)Get child shape by name/id
getChildCount()Number of children
getVertex(int i)Get vertex by index as PVector
getVertexCount()Number of vertices
setVertex(int i, float x, float y)Set vertex position
disableStyle()Ignore the shape's own fill/stroke
enableStyle()Use the shape's own fill/stroke
setFill(float r, float g, float b)Set fill color
setStroke(float r, float g, float b)Set stroke color
widthBounding box width
heightBounding box height

Related

Under the Hood

From Processing.h:

class PShape { public: struct Vertex { float x,y,z,u,v; }; std::vector<Vertex> verts; std::vector<PShape> children; int kind = -1; bool closed = false; bool visible = true; float fillR=1,fillG=1,fillB=1,fillA=1; float strokeR=0,strokeG=0,strokeB=0,strokeA=1,strokeW=1; bool hasFill=true, hasStroke=false; PShape() = default; explicit PShape(int k) : kind(k) {} // Allow PShape bot = loadShape("file.svg") -- copies from pointer PShape(const PShape* p) { if(p) *this = *p; } PShape& operator=(const PShape* p) { if(p) *this = *p; return *this; } void beginShape(int k=-1) { kind=k; verts.clear(); } void endShape(bool close=false) { closed=close; } void vertex(float x,float y,float z=0,float u=0,float v=0) { verts.push_back({x,y,z,u,v}); } void addChild(const PShape& s) { children.push_back(s); } std::string name; // id/name attribute from SVG std::vector<int> subpathStarts; // subpath start indices for multi-part fills std::vector<Vertex> anchorVerts; // raw anchor points (M/L/C endpoints only) for getVertex() PShape* getChild(int i) { return i<(int)children.size()?&children[i]:nullptr; } PShape* getChild(const std::string& n) { for(auto& c:children) if(c.name==n) return &c; for(auto& c:children){ PShape* r=c.getChild(n); if(r) return r; } // Return a static empty shape rather than nullptr to prevent crashes static PShape _empty; fprintf(stderr,"[PShape] getChild('%s') not found\n", n.c_str()); return &_empty; } PShape* getChild(const char* n) { return getChild(std::string(n)); } int getChildCount() const { return (int)children.size(); } PVector getVertex(int i) const { if(i<0||i>=(int)verts.size()) return PVector(0,0,0); return PVector(verts[i].x, verts[i].y, verts[i].z); } void setVertex(int i, float x, float y) { if(i>=0&&i<(int)verts.size()){verts[i].x=x;verts[i].y=y;} } void setVertex(int i, float x, float y, float z) { if(i>=0&&i<(int)verts.size()){verts[i].x=x;verts[i].y=y;verts[i].z=z;} } // Bounding box (computed from verts + children) float width = 0; float height = 0; void computeBounds() { float minx=1e9,maxx=-1e9,miny=1e9,maxy=-1e9; for(auto& v:verts){minx=std::min(minx,v.x);maxx=std::max(maxx,v.x);miny=std::min(miny,v.y);maxy=std::max(maxy,v.y);} for(auto& c:children){const_cast<PShape&>(c).computeBounds();minx=std::min(minx,c.verts.empty()?minx:minx); if(!c.verts.empty()){for(auto& v:c.verts){minx=std::min(minx,v.x);maxx=std::max(maxx,v.x);miny=std::min(miny,v.y);maxy=std::max(maxy,v.y);}}} width =(maxx>-1e8)?(maxx-minx):0; height=(maxy>-1e8)?(maxy-miny):0; } int getVertexCount() const { return (int)verts.size(); } void setFill(float r,float g,float b,float a=1) { fillR=r;fillG=g;fillB=b;fillA=a;hasFill=true; } void setStroke(float r,float g,float b,float a=1) { strokeR=r;strokeG=g;strokeB=b;strokeA=a;hasStroke=true; } void setStrokeWeight(float w) { strokeW=w; } void setVisible(bool v) { visible=v; } void translate(float x,float y,float z=0) { for(auto& v:verts){ v.x+=x;v.y+=y;v.z+=z; } } void scale(float s) { for(auto& v:verts){ v.x*=s;v.y*=s;v.z*=s; } } void scale(float sx, float sy) { for(auto& v:verts){ v.x*=sx;v.y*=sy; } } // Style enable/disable -- controls whether shape uses its own fill/stroke // or inherits from the current Processing fill()/stroke() state bool styleEnabled = true; void disableStyle() { styleEnabled = false; } void enableStyle() { styleEnabled = true; } GLuint texId = 0; // OpenGL texture ID for OBJ material textures };

Under the Hood

From Processing.cpp:

PShape PApplet::createShape(int kind){ return PShape(kind); if(found.empty()){std::cerr<<"loadShape: file not found: "<<path<<"\n";return new PShape(); if(found.empty()){std::cerr<<"loadShape: OBJ not found: "<<path<<"\n";return new PShape(); return new PShape();