Hi all - first post.
My name is Nick Taylor - and I am an the ultimate newbie when it comes to JScad, although I did start programming in 1979, have the degree, and a couple of decades of commercial experience... which is a fancy way of saying I am a recovering web-dev.
I now do manufacturing and design etc... and am building an electric guitar which is based on a flattened egg shape.
So.... this is what i have so far, which generates the egg.... it is basically a parabola sitting upside down on top of a circle, joined then rotated into a 3D shape.
I am experiencing all sorts of weirdness to do with unexpected boolean behaviour (eg: intersect does what a union should do), and I look at this code and despair.... there has GOT to be a more concise way of doing this.
If anyone has any help or advice, I would be most eternally, tearfully grateful.
If there is a better way of presenting this code (eg: giving it a main function), let me know.
//
// egg_shape
// ---------------------------------------------------------------------------------
function egg_shape(resolution, radius, parabola_top) {
const a = findTangentA(radius, parabola_top, resolution);
const tangentPoints = findTangentPoints(a, parabola_top, radius, resolution);
const circlePoints = [];
const rSquared = radius * radius;
const xMax = Math.sqrt(rSquared);
const step = 0.5;
// Top half of circle
for (let x = -xMax; x <= xMax; x += step) {
const y = Math.sqrt(rSquared - x * x);
circlePoints.push([x, y]);
}
// Bottom half of circle (reverse direction)
for (let x = xMax; x >= -xMax; x -= step) {
const y = -Math.sqrt(rSquared - x * x);
circlePoints.push([x, y]);
}
const circleGeom = polygon({ points: circlePoints });
const { xLeft, xRight } = tangentPoints;
const parabolaPoints = [];
for (let x = xLeft; x <= xRight; x += step) {
const y = -a * x * x + parabola_top;
parabolaPoints.push([x, y]);
}
const parabolaGeom = polygon({ points: parabolaPoints });
// intersect does what a union should do
const eggProfile = intersect(circleGeom, parabolaGeom);
// Create 3D egg by rotating the 2D profile
return extrudeRotate({
segments: resolution,
angle: Math.PI * 2
}, eggProfile);
}
//
// findTangentA
// ---------------------------------------------------------------------------------
function findTangentA(radius, h, resolution) {
const R2 = radius * radius
const stepA = 0.00001
const tolerance = 0.1
const searchStep = 0.5
for (let a = 0.005; a < 0.02; a += stepA) {
let count = 0
for (let x = -radius; x <= radius; x += searchStep) {
const y = -a * x * x + h
const dist = x * x + y * y
if (Math.abs(dist - R2) < tolerance) count++
}
if (count === 2) return a
}
return 0.0095 // Fallback value
}
//
// findTangentPoints
// ---------------------------------------------------------------------------------
function findTangentPoints(a, h, radius, resolution) {
const R2 = radius * radius
const points = []
const dx = 0.01
const tolerance = 0.001
for (let x = -radius; x <= radius; x += dx) {
const y = -a * x * x + h
const d = x * x + y * y
if (Math.abs(d - R2) < tolerance) points.push(x)
}
if (points.length >= 2) {
return { xLeft: Math.min(...points), xRight: Math.max(...points) }
}
return { xLeft: -radius * 0.8, xRight: radius * 0.8 }
}