import java.awt.*; class Cone extends Biparam implements java.io.Serializable { static final long serialVersionUID = -2558098774090336324L; // -679715043452968126L; Cone() { inPnt = new cVector(); name = "Cone"; uDivs = 32; vDivs = 16; minUDivs = 3; minVDivs = 1; endcaps = true; retile(); base = LA.newVector(0, 0, 0); // -1); apex = LA.newVector(0, 1, 0); // 1); baseRadius = apexRadius = 1; // 0.125; //fromStandard = new double[4][4]; //toStandard = new double[4][4]; //LA.matIdentity(fromStandard); //LA.matIdentity(toStandard); //orient(); recalculate(); } void recalculate() { cVector axis = new cVector(); LA.vecSub(apex, base, axis); height = LA.vecLen(axis); super.recalculate(); } /* void orient() { cVector axis = new cVector(); LA.vecSub(apex, base, axis); height = LA.vecLen(axis); LA.matIdentity(fromStandard); LA.matIdentity(toStandard); if (Math.abs(base.x - apex.x) < 0.001 && Math.abs(base.y - apex.y) < 0.001) { if (apex.z < base.z) { LA.matXRotate(fromStandard, 180); LA.matXRotate(toStandard, 180); } } else { LA.vecNormalize(axis); cVector up = LA.newVector(0, 0, 1); cVector x = new cVector(); cVector y = new cVector(); LA.vecCross(up, axis, x); LA.vecNormalize(x); LA.vecCross(axis, x, y); LA.vecNormalize(y); for (int i=0; i < 3; i++) { fromStandard[0][i] = x.get(i); fromStandard[1][i] = y.get(i); fromStandard[2][i] = axis.get(i); toStandard[i][0] = x.get(i); toStandard[i][1] = y.get(i); toStandard[i][2] = axis.get(i); } } LA.matTranslate(fromStandard, base.x, base.y, base.z); double temp[][] = new double[4][4]; LA.matIdentity(temp); LA.matTranslate(temp, -base.x, -base.y, -base.z); LA.matConcat(temp, toStandard, toStandard); recalculate(); } */ Object3D deepCopy() { Cone cone = new Cone(); deepCopySelf(cone); return cone; } protected void deepCopyNode(Object3D other) { super.deepCopyNode(other); Cone c = (Cone)other; LA.vecCopy(base, c.base); c.baseRadius = baseRadius; LA.vecCopy(apex, c.apex); c.apexRadius = apexRadius; } void generatePOV(StringBuffer buffer) { generateNameComment(buffer); generateIndent(buffer); cVector temp = new cVector(); if (baseRadius == apexRadius) { buffer.append("cylinder { "); LA.toPOVRay(base, buffer); buffer.append(", "); LA.toPOVRay(apex, buffer); buffer.append(", "); buffer.append(baseRadius); buffer.append("\n"); } else { buffer.append("cone { "); LA.toPOVRay(base, buffer); buffer.append(", "); buffer.append(baseRadius); buffer.append(", "); LA.toPOVRay(apex, buffer); buffer.append(", "); buffer.append(apexRadius); buffer.append("\n"); } generateTransform(buffer); generateIndent(buffer); buffer.append("}\n"); } void getBounds(cVector minima, cVector maxima, boolean xform) { super.getBounds(minima, maxima, xform); // july 2014 /* // for (int i=0; i < 3; i++) // { // double amax = apex.get(i) + apexRadius; // double amin = apex.get(i) - apexRadius; // double bmax = base.get(i) + baseRadius; // double bmin = base.get(i) - baseRadius; // minima.set(i, amin >= bmin ? bmin : amin); // maxima.set(i, amax <= bmax ? bmax : amax); // } // // */ // double maxr = baseRadius; // if (maxr < apexRadius) // maxr = apexRadius; // // minima.set(0, -maxr); // -1); // minima.set(1, 0); // -1); // minima.set(2, -maxr); // -1); // maxima.set(0, maxr); // 1); // maxima.set(1, height); // 1); // maxima.set(2, maxr); // 1); // // if (xform) // transformBounds(minima, maxima); } boolean inside(double x, double y, double z, boolean xform) { if (xform) untransform(x, y, z, inPnt); else LA.setVector(inPnt, x, y, z); //LA.xformPos(inPnt, toStandard, inPnt); double rad1 = inPnt.x * inPnt.x + inPnt.z * inPnt.z; double t = inPnt.y / height; double rad2 = baseRadius + t * (apexRadius - baseRadius); rad2 *= rad2; double f = rad1 - rad2; boolean inside = f <= 0; if (inPnt.y < 0 || inPnt.y > 1) { f = 1; //super.height = 1; //return false; inside = false; } if (depth != -1 && (super.height <= 0 ^ inside)) { Simplex.atom = this; } depth = 0; super.height = f; return inside; } double uStretch() { return 6; // Actually 6.28 (I think) } double vFlip(double v) { return 1-v; } Vertex biparamFunction(double u, double v) { cVector tPos; cVector tNorm; if(bRep != null && bRep.trimmed) { tPos = cStatic.vertex1; tNorm = cStatic.vertex1.norm; if (u < 0) { tPos.set(0, v >= 0.5 ? height : 0, 0); // /2 : -height/2, 0); tNorm.set(0, v >= 0.5 ? 1 : -1, 0); } else { double angle = LA.toRadians(u * 360); double rad = baseRadius + v * (apexRadius - baseRadius); double z = Math.cos(angle); double x = Math.sin(angle); double y = v * height; tPos.set(rad * x, y /*- 1*/, rad * z); /* z = baseRadius * (double)Math.cos(angle); x = baseRadius * (double)Math.sin(angle); */ y = (baseRadius - apexRadius) / height; tNorm.set(x, y, z); } LA.vecNormalize(tNorm); return cStatic.vertex1; } else { if (u < 0) { tPos = LA.newVector(0, v >= 0.5 ? height : 0, 0); // /2 : -height/2, 0); tNorm = new cVector(0, v >= 0.5 ? 1 : -1, 0); } else { double angle = LA.toRadians(u * 360); double rad = baseRadius + v * (apexRadius - baseRadius); double z = rad * (double)Math.cos(angle); double x = rad * (double)Math.sin(angle); double y = v * height; tPos = LA.newVector(x, y /*- 1*/, z); z = baseRadius * (double)Math.cos(angle); x = baseRadius * (double)Math.sin(angle); y = (baseRadius - apexRadius) / height; tNorm = LA.newVector(x, y, z); } //LA.xformPos(tPos, fromStandard, tPos); //LA.xformDir(tNorm, fromStandard, tNorm); Vertex temp = new Vertex(tPos); //temp.pos = tPos; // useless new cVector() temp.norm = tNorm; LA.vecNormalize(temp.norm); return temp; } } void createEditWindow(GroupEditor callee, boolean newWindow) { if (newWindow) objectUI = new ConeEditor(this, deepCopy(), callee); else objectUI = new ConeEditor(this, callee); editWindow = objectUI.GetEditor(); } void drawEditHandles(//ClickInfo info, int level) { super.drawEditHandles(//info, level); if (level == 1) { return; } //else { cVector temp = new cVector(); LA.xformPos(base, toParent, temp); Rectangle baseSpot = calcHotSpot(temp); //, info); LA.xformPos(apex, toParent, temp); Rectangle apexSpot = calcHotSpot(temp); //, info); clickInfo.g.setColor(Color.green); clickInfo.g.fillRect(baseSpot.x, baseSpot.y, baseSpot.width, baseSpot.height); clickInfo.g.fillRect(apexSpot.x, apexSpot.y, apexSpot.width, apexSpot.height); return; } } boolean doEditClick(//ClickInfo info, int level) { //if (level == 0) //return false; hitSomething = 0; if (super.doEditClick(//info, level)) { hitSomething = 1; return true; } cVector temp = new cVector(); LA.xformPos(base, toParent, temp); Rectangle baseSpot = calcHotSpot(temp); //, info); LA.xformPos(apex, toParent, temp); Rectangle apexSpot = calcHotSpot(temp); //, info); if (baseSpot.contains(clickInfo.x, clickInfo.y)) { hitSomething = 2; startRad = baseRadius; } else if (apexSpot.contains(clickInfo.x, clickInfo.y)) { hitSomething = 3; startRad = apexRadius; } else { return false; } startX = clickInfo.x; return true; } void doEditDrag(//ClickInfo info, boolean opposite) { if (hitSomething == 0) return; if (hitSomething == 1) { super.doEditDrag(//info, opposite); return; } double deltaR = clickInfo.x - startX; double newRad = startRad + deltaR; if (newRad < 0) newRad = 0; if (hitSomething == 2) baseRadius = newRad; else apexRadius = newRad; recalculate(); clickInfo.pane.repaint(); } cVector base; cVector apex; double baseRadius; double apexRadius; double height; //double fromStandard[][]; //double toStandard[][]; protected cVector inPnt; private static final int hitStandard = 1; private static final int hitBase = 2; private static final int hitApex = 3; private static int hitSomething; private static int startX; private static double startRad; }