Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solves issue #6787 #6809

Merged
merged 12 commits into from
Mar 13, 2024
109 changes: 109 additions & 0 deletions src/webgl/p5.Geometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ p5.Geometry = class Geometry {
//@type [p5.Vector]
this.vertices = [];

this.boundingBoxCache = null;


//an array containing every vertex for stroke drawing
this.lineVertices = new p5.DataArray();

Expand Down Expand Up @@ -75,6 +78,112 @@ p5.Geometry = class Geometry {
return this; // TODO: is this a constructor?
}

/**
* Custom bounding box calculation based on the object's vertices.
* The bounding box is a rectangular prism that encompasses the entire object.
* It is defined by the minimum and maximum coordinates along each axis, as well
* as the size and offset of the box.
*
* It returns an object containing the bounding box properties:
*
* - `min`: The minimum coordinates of the bounding box as a p5.Vector.
* - `max`: The maximum coordinates of the bounding box as a p5.Vector.
* - `size`: The size of the bounding box as a p5.Vector.
* - `offset`: The offset of the bounding box as a p5.Vector.
*
* @method calculateBoundingBox
* @memberof p5.Geometry.prototype
* @return {Object}
*
* @example
*
* <div>
* <code>
* let particles;
* let button;
* let resultParagraph;
*
* function setup() {
* createCanvas(100, 100, WEBGL);
* button = createButton('New');
* button.mousePressed(makeParticles);
*
* resultParagraph = createP('').style('width', '180px' );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* resultParagraph = createP('').style('width', '180px' );
* resultParagraph = createElement('pre').style('width', '180px' );

* resultParagraph.style('font-family', 'monospace');
* resultParagraph.style('font-size', '12px');
* makeParticles();
* }
*
* function makeParticles() {
* if (particles) freeGeometry(particles);
*
* particles = buildGeometry(() => {
* for (let i = 0; i < 60; i++) {
* push();
* translate(
* randomGaussian(0, 200),
* randomGaussian(0, 100),
* randomGaussian(0, 150)
* );
* sphere(10);
* pop();
* }
* });
*
* const boundingBox = particles.calculateBoundingBox();
* resultParagraph.html('Bounding Box: \n' + JSON.stringify(boundingBox));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* resultParagraph.html('Bounding Box: \n' + JSON.stringify(boundingBox));
* resultParagraph.html('Bounding Box: \n' + JSON.stringify(boundingBox, null, 2));

* }
*
* function draw() {
* background(255);
* noStroke();
* lights();
* orbitControl();
* model(particles);
* }
*
* </code>
* </div>
*
*/

calculateBoundingBox() {
if (this.boundingBoxCache) {
return this.boundingBoxCache; // Return cached result if available
}

let minVertex = new p5.Vector(
Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
let maxVertex = new p5.Vector(
Number.MIN_VALUE, Number.MIN_VALUE, Number.MIN_VALUE);

for (let i = 0; i < this.vertices.length; i++) {
let vertex = this.vertices[i];
minVertex.x = Math.min(minVertex.x, vertex.x);
minVertex.y = Math.min(minVertex.y, vertex.y);
minVertex.z = Math.min(minVertex.z, vertex.z);

maxVertex.x = Math.max(maxVertex.x, vertex.x);
maxVertex.y = Math.max(maxVertex.y, vertex.y);
maxVertex.z = Math.max(maxVertex.z, vertex.z);
}
// Calculate size and offset properties
let size = new p5.Vector(maxVertex.x - minVertex.x,
maxVertex.y - minVertex.y, maxVertex.z - minVertex.z);
let offset = new p5.Vector((minVertex.x + maxVertex.x) / 2,
(minVertex.y + maxVertex.y) / 2, (minVertex.z + maxVertex.z) / 2);

// Cache the result for future access
this.boundingBoxCache = {
min: minVertex,
max: maxVertex,
size: size,
offset: offset
};

return this.boundingBoxCache;
}

reset() {
this._hasFillTransparency = undefined;
this._hasStrokeTransparency = undefined;
Expand Down
14 changes: 14 additions & 0 deletions test/unit/webgl/p5.Geometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,20 @@ suite('p5.Geometry', function() {
assert.equal(geom._addJoin.callCount, 4);
});

test('calculateBoundingBox()', function() {
geom.vertices.push(
myp5.createVector(0, 0, 0),
myp5.createVector(10, 20, 30),
myp5.createVector(-5, 15, 25)
);
const boundingBox = geom.calculateBoundingBox();
assert.deepEqual(boundingBox.min.array(), [-5, 0, 0]);
assert.deepEqual(boundingBox.max.array(), [10, 20, 30]);
assert.deepEqual(boundingBox.size.array(), [15, 20, 30]);
assert.deepEqual(boundingBox.offset.array(), [2.5, 10, 15]);
});


test('degenerate edge in the middle', function() {
geom.vertices.push(
myp5.createVector(0, 0),
Expand Down
Loading