/**
* SlicePlane
* ___________________
* / / / /
* / / /_____ /
* / / ___ / /
* / / / / / /
* / /_/ /_/ /
* /__________________/
*/
package cc.sketchchair.geometry;
import java.util.ArrayList;
import java.util.List;
import nu.xom.Attribute;
import nu.xom.Element;
import ShapePacking.BezierControlNode;
import ShapePacking.spShape;
import cc.sketchchair.core.CrossSliceSelection;
import cc.sketchchair.core.GLOBAL;
import cc.sketchchair.core.LOGGER;
import cc.sketchchair.core.PickBuffer;
import cc.sketchchair.core.SETTINGS;
import cc.sketchchair.core.UITools;
import cc.sketchchair.functions.functions;
import cc.sketchchair.sketch.SETTINGS_SKETCH;
import cc.sketchchair.sketch.Sketch;
import cc.sketchchair.sketch.SketchOutline;
import cc.sketchchair.sketch.SketchPath;
import cc.sketchchair.sketch.SketchPoint;
import cc.sketchchair.sketch.SketchShape;
import cc.sketchchair.sketch.SketchSpline;
import cc.sketchchair.sketch.SliceSlot;
import cc.sketchchair.triangulate.Delaunay;
import com.bulletphysics.collision.shapes.IndexedMesh;
import com.bulletphysics.collision.shapes.TriangleIndexVertexArray;
import processing.core.PApplet;
import processing.core.PGraphics;
import toxi.geom.Plane;
import toxi.geom.Ray3D;
import toxi.geom.Vec2D;
import toxi.geom.Vec3D;
/**
* SlicePlanes are the planes that contain a Sketch. A Sliceplane is made for each part of the design.
* @author gregsaul
*
*/
public class SlicePlane {
SketchSpline sketchSpline = null;
private Sketch sketch;
Vec3D offset = null;
Vec3D planeNormal = null;
private Plane plane = null;
SliceSlot constraintSlot = null;
transient IndexedMesh indexedMesh;
transient TriangleIndexVertexArray indexVertexArray;
private boolean selected = false;
public Vec2D debugPoint = new Vec2D();
public boolean destroy = false;
public float profileHeight;
public float profileMinY;
public float profileMaxY;
public SketchPath coverPath;
public boolean tiedToLeg = false;
public float thickness = SETTINGS_SKETCH.plane_thickness;
//public float thickness_pixels = SETTINGS_SKETCH.plane_thickness_mm*SETTINGS_SKETCH.pixels_per_mm;
public boolean guide = false;
private Vec2D debugMousePoint = null;
public List<Vec2D> debugIntersectionPoints = new ArrayList();
public List<Vec2D> debugIntersectionPointsTop = new ArrayList();
public List<Vec2D> debugIntersectionPointsBottom = new ArrayList();
public Vec2D debugIntersetStart = null;
private CrossSliceSelection crossSliceSelection = null;
int id;
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public SlicePlane(Element element) {
//wrong type
if (!element.getLocalName().equals("SlicePlane"))
return;
if (element.getAttributeValue("id") != null)
this.setId(Integer.parseInt(element.getAttributeValue("id")));
if (element.getAttributeValue("guide") != null)
this.guide = true;
this.setSelected(true);
for (int i = 0; i < element.getChildCount(); i++) {
Element child = (Element) element.getChild(i);
if (child != null && child.getLocalName().equals("Sketch")) {
this.setSketch(new Sketch(GLOBAL.uiTools.SketchTools,
GLOBAL.SketchGlobals, child));
this.getSketch().setOnSlicePlane(this);
}
if (child != null && child.getLocalName().equals("SketchShapes")) {
this.setSketch(new Sketch(GLOBAL.uiTools.SketchTools,
GLOBAL.SketchGlobals, child));
this.getSketch().setOnSlicePlane(this);
}
if (child != null && child.getLocalName().equals("Plane")) {
if (child.getAttributeValue("x") != null
&& child.getAttributeValue("y") != null
&& child.getAttributeValue("z") != null
&& child.getAttributeValue("nx") != null
&& child.getAttributeValue("ny") != null
&& child.getAttributeValue("nz") != null) {
float xmlX = Float.valueOf(child.getAttributeValue("x"));
float xmlY = Float.valueOf(child.getAttributeValue("y"));
float xmlZ = Float.valueOf(child.getAttributeValue("z"));
float xmlNX = Float.valueOf(child.getAttributeValue("nx"));
float xmlNY = Float.valueOf(child.getAttributeValue("ny"));
float xmlNZ = Float.valueOf(child.getAttributeValue("nz"));
Plane pl = new Plane(new Vec3D(xmlX, xmlY, xmlZ),
new Vec3D(xmlNX, xmlNY, xmlNZ));
this.setPlane(pl);
} else {
LOGGER.warning("requred data not found in XML file");
return;
}
}
}
if (this.getPlane() == null) {
this.setPlane(new Plane());
LOGGER.warning("no Plane def found in XML making a defaul plane");
}
}
public SlicePlane(Plane plane) {
this.setId(GLOBAL.planeID++);
setSketch(new Sketch(GLOBAL.uiTools.SketchTools, GLOBAL.SketchGlobals,
this));
this.setPlane(plane);
this.getSketch().setOnSlicePlane(this);
this.select();
}
public SlicePlane(Sketch parentSketch, Plane plane) {
this.setId(GLOBAL.planeID++);
this.setSketch(parentSketch);
this.getSketch().setOnSlicePlane(this);
this.setPlane(plane);
coverPath = new SketchPath(getSketch());
//this.build();
this.select();
// GLOBAL.undo.addOperation(new UndoAction(this, UndoAction.ADD_PLANE));
}
public SlicePlane(Sketch Sketch, SliceSlot slot) {
this.setId(GLOBAL.planeID++);
//setSketch( new Sketch(GLOBAL.uiTools.SketchTools, GLOBAL.SketchGlobals,this));
this.constraintSlot = slot;
this.setSketch(Sketch);
this.setPlane(this.constraintSlot.constrainPlane);
this.getSketch().setOnSlicePlane(this);
this.build();
this.select();
// this.Sketch.add(linkedSpline);
}
public boolean addPointAlongPath(float x, float y) {
return this.getSketch().addPointAlongPath(x, y);
}
public void applyRotationMatrix(PGraphics g) {
g.translate(this.getPlane().x, this.getPlane().y, this.getPlane().z);
// g.rotateX(this.plane.normal.headingXY());
g.rotateY((float) (functions.angleOf(new Vec2D(
this.getPlane().normal.x, this.getPlane().normal.z)) - (Math.PI / 2)));
// g.rotateY((float) Math.PI/2);
float rotateAn = (functions.angleOf(new Vec2D(this.getPlane().normal.x,
this.getPlane().normal.y)));
// rotateAn = this.testAn;
if (rotateAn < Math.PI / 2 || rotateAn > (Math.PI / 2) * 3)
rotateAn = (float) ((Math.PI * 2) - Math.abs(rotateAn));
g.rotateX(rotateAn);
}
void build() {
this.getSketch().build();
}
public void buildCoverPath() {
if (this.getSketch().getSketchShapes().sketchOutlines
.getOutterOutline() != null)
this.coverPath = this.getSketch().getSketchShapes().sketchOutlines
.getOutterOutline().getPath();
}
public void checkForCollisions() {
//remove slots that don't pierce the edge at all.
this.getSketch().getSlots().removeNonPiercing(this.getSketch());
//remove slots that collide with others
this.getSketch().getSlots().removeIntersecting();
//remove slots that are impossible to put in
this.getSketch().getSlots().removeTrappedSlots(this.getSketch());
//First check if slots are colliding if they are remove one plane
// this.getSketch().getSlots().checkForSlotCollisions();
}
@Override
public SlicePlane clone() {
SlicePlane copiedPlane = new SlicePlane(
this.getSketch().clone(),
new Plane(this.getPlane().copy(), this.getPlane().normal.copy()));
return copiedPlane;
}
public SlicePlane copy() {
SlicePlane newSlicePlane = new SlicePlane(new Plane(this.plane.copy(),
this.plane.normal.copy()));
newSlicePlane.guide = this.guide;
newSlicePlane.setSketch(this.getSketch().copy());
newSlicePlane.selected = this.selected;
newSlicePlane.getSketch().setOnSketchPlane(newSlicePlane);
newSlicePlane.setId(this.getId());
return newSlicePlane;
}
public void destroy() {
this.destroy = true;
}
public void flipHorizontal(Vec3D centre) {
this.getSketch().flipHorizontal(centre);
}
public void generate() {
this.profileHeight = this.getSketch().getHeight();
this.profileMinY = this.getSketch().getMinY();
this.profileMaxY = this.getSketch().getMaxY();
}
public float getArea() {
return this.getSketch().getArea();
}
public Vec3D getCentreOfMass() {
Vec2D centre = this.getSketch().getCentreOfMass();
if (centre != null)
return new Vec3D(GLOBAL.jBullet.scaleVal(centre.x),
GLOBAL.jBullet.scaleVal(centre.y),
GLOBAL.jBullet.scaleVal(this.getPlane().z));
else
return null;
}
public SketchPoint getClosestPathVertex(Vec2D pointOnPlan) {
return this.getSketch().getClosestPathVertex(pointOnPlan);
}
public IndexedMesh getIndexedMesh(float offsetX, float offsetY,
float offsetZ) {
IndexedMesh indexedMesh = new IndexedMesh();
// Vec2D centre = this.sketchSpline.getCentreOfMass();
this.getSketch().buildOutline();
if (this.getSketch().getSketchShapes().sketchOutlines
.getOutterOutline() != null) {
this.getSketch().getSketchShapes().sketchOutlines
.getOutterOutline().optimizeForCollision();
ArrayList loop = this.getSketch().getSketchShapes().sketchOutlines
.getOutterOutline().getVector2DLoop();
Delaunay triangulate = new Delaunay();
if (loop == null || loop.size() < 3)
return null;
triangulate.triangulate_main(loop);
int vertNum = triangulate.vertexs.size() * 3;
float[] gVertices = new float[vertNum];
for (int i = 0; i < triangulate.vertexs.size(); i++) {
Delaunay.Vertex v = (Delaunay.Vertex) triangulate.vertexs
.get(i);
Vec3D pointOnePlane = new Vec3D(new Float(v.x), new Float(v.y),
0);
if (this.getPlane().normal.z == -1) {
pointOnePlane.z = this.getPlane().z;
} else {
pointOnePlane = pointOnePlane.rotateY(PApplet.PI / 2);
float planeAngle = functions.angleOf(new Vec2D(this
.getPlane().normal.x, this.getPlane().normal.y));
pointOnePlane = pointOnePlane.rotateZ(-planeAngle);
pointOnePlane.x += this.getPlane().x;
pointOnePlane.y += this.getPlane().y;
pointOnePlane.z += this.getPlane().z;
}
gVertices[(3 * v.getIndex()) + 0] = GLOBAL.jBullet
.scaleVal((float) pointOnePlane.x) - offsetX;
gVertices[(3 * v.getIndex()) + 1] = GLOBAL.jBullet
.scaleVal((float) -pointOnePlane.y) + offsetY;
gVertices[(3 * v.getIndex()) + 2] = GLOBAL.jBullet
.scaleVal(pointOnePlane.z) - offsetZ;
}
int indNum = (triangulate.triangles.size() * 3);
int triNum = triangulate.triangles.size();
int indDiffNum = (triangulate.triangles.size());
int[] gIndices = new int[indNum];
for (int i = 0; i < triangulate.triangles.size(); i++) {
Delaunay.Triangle t = (Delaunay.Triangle) triangulate.triangles
.get(i);
gIndices[(i * 3) + 0] = (t.get_vertex(0).getIndex());
gIndices[(i * 3) + 1] = (t.get_vertex(1).getIndex());
gIndices[(i * 3) + 2] = (t.get_vertex(2).getIndex());
}
indexVertexArray = new TriangleIndexVertexArray(triNum,
functions.getIndexBuffer(gIndices), 4 * 3, vertNum / 3,
functions.getVertexBuffer(gVertices), 4 * 3);
// System.out.println("size" +
// indexVertexArray.getIndexedMeshArray().size());
indexedMesh = indexVertexArray.getIndexedMeshArray().get(0);
} else {
return null;
}
return indexedMesh;
}
/**
*
* @param slicePlane (Plane to intersect)
* @param constrain (Should we crop to the current shape?)
* @param cropToSketch (What is the current shape)
* @return
*
*
*/
public List<List<Vec2D>> getIntersection(SlicePlane slicePlane,
boolean constrain, SketchShape cropToSketch) {
List<List<Vec2D>> returnList = new ArrayList<List<Vec2D>>();
List<SketchShape> ShetchShapesIntersect = new ArrayList<SketchShape>(); //shapes to check for intersections
if (constrain) {
Object object = cropToSketch;
if (object instanceof SketchSpline) {
SketchSpline spline = (SketchSpline) object;
ShetchShapesIntersect.add(spline.getPath());
}
if (object instanceof SketchPath) {
//TODO: we need to make the crop to shop the correct one on each plane.
SketchPath spline = (SketchPath) object;
ShetchShapesIntersect.add(spline);
}
} else {
SketchOutline outline = this.getSketch().getSketchShapes().sketchOutlines
.getOutterOutline();
for (int o = 0; o < this.getSketch().getSketchShapes().sketchOutlines
.getList().size(); o++) {
SketchPath outline2 = this.getSketch().getSketchShapes().sketchOutlines
.getList().get(o).getPath();
ShetchShapesIntersect.add(outline2);
}
//ShetchShapesIntersect.add(this.getSketch().getSketchShapes().sketchOutlines.getOutterOutline().getPath());
//path = outline.getPath();
}
if (ShetchShapesIntersect.size() == 0)
return null;
for (int sh = 0; sh < ShetchShapesIntersect.size(); sh++) {
SketchPath path = (SketchPath) ShetchShapesIntersect.get(sh);
for (int i = 1; i <= path.size(); i++) {
Vec3D p1 = null;
Vec3D p2 = null;
if (i != 0) {
p1 = this.getWorldPos((Vec2D) path.get(i - 1));
} else {
p1 = this.getWorldPos((Vec2D) path.get(path.size() - 1));
}
if (i != path.size()) {
p2 = this.getWorldPos((Vec2D) path.get(i));
} else {
p2 = this.getWorldPos((Vec2D) path.get(0));
}
//
// if one point is on one side of the plane and the other point is
// on the other side !
if (slicePlane.getPlane().classifyPoint(p1) != slicePlane
.getPlane().classifyPoint(p2)) {
//we found a intersect
SketchPoint vec2D1 = null;
if (i != 0) {
vec2D1 = (SketchPoint) path.get(i - 1);
} else {
vec2D1 = (SketchPoint) path.get(path.size() - 1);
}
SketchPoint vec2D2 = null;
if (i < path.size()) {
vec2D2 = (SketchPoint) path.get(i);
} else {
vec2D2 = (SketchPoint) path.get(0);
}
if (vec2D1 == null || vec2D2 == null)
break;
if (vec2D1.containsBezier() || vec2D2.containsBezier()) {
for (float t = 0; t < 1 - GLOBAL.SketchGlobals.BEZIER_DETAIL_CALCULATIONS; t += GLOBAL.SketchGlobals.BEZIER_DETAIL_CALCULATIONS) {
Vec2D bez1 = vec2D1;
Vec2D bez2 = vec2D2;
if (vec2D1.controlPoint2 != null) {
bez1 = vec2D1.controlPoint2;
}
if (vec2D2.controlPoint1 != null) {
bez2 = vec2D2.controlPoint1;
}
float x = GLOBAL.g.bezierPoint(vec2D1.x, bez1.x,
bez2.x, vec2D2.x, t);
float y = GLOBAL.g.bezierPoint(vec2D1.y, bez1.y,
bez2.y, vec2D2.y, t);
float x2 = GLOBAL.g
.bezierPoint(
vec2D1.x,
bez1.x,
bez2.x,
vec2D2.x,
t
+ (GLOBAL.SketchGlobals.BEZIER_DETAIL_CALCULATIONS));
float y2 = GLOBAL.g
.bezierPoint(
vec2D1.y,
bez1.y,
bez2.y,
vec2D2.y,
t
+ (GLOBAL.SketchGlobals.BEZIER_DETAIL_CALCULATIONS));
Vec2D curveP1 = new Vec2D(x, y);
Vec2D curveP2 = new Vec2D(x2, y2);
Vec3D p1b = this.getWorldPos(curveP1);
Vec3D p2b = this.getWorldPos(curveP2);
if (slicePlane.getPlane().classifyPoint(p1b) != slicePlane
.getPlane().classifyPoint(p2b)) {
Vec3D intersect = null;
intersect = (Vec3D) slicePlane.getPlane()
.getIntersectionWithRay(
new Ray3D(p2b, p1b.sub(p2b)));
if (intersect == null)
intersect = (Vec3D) slicePlane
.getPlane()
.getIntersectionWithRay(
new Ray3D(p1b, p2b.sub(p1b)));
Vec2D intexsecX = new Vec2D(intersect.x,
intersect.y);
if (intersect != null) {
intersect.subSelf(slicePlane.getPlane());
intersect
.rotateY((float) (functions.angleOf(new Vec2D(
slicePlane.getPlane().normal.x,
slicePlane.getPlane().normal.z)) - (Math.PI / 2)));
float rotateAn = (functions
.angleOf(new Vec2D(
slicePlane.getPlane().normal.x,
slicePlane.getPlane().normal.y)));
if (rotateAn < Math.PI / 2
|| rotateAn > (Math.PI / 2) * 3)
rotateAn = (float) ((Math.PI * 2) - Math
.abs(rotateAn));
intersect.rotateX(rotateAn);
List<Vec2D> listItem = new ArrayList<Vec2D>();
listItem.add(new Vec2D(intersect.x,
intersect.y));
listItem.add(intexsecX);
returnList.add(listItem);
//t = 2;
}
}
}
} else {
Vec3D intersect = null;
intersect = (Vec3D) slicePlane.getPlane()
.getIntersectionWithRay(
new Ray3D(p2, p1.sub(p2)));
if (intersect == null)
intersect = (Vec3D) slicePlane.getPlane()
.getIntersectionWithRay(
new Ray3D(p1, p2.sub(p1)));
if (intersect != null) {
Vec2D intexsecX = new Vec2D(intersect.x,
intersect.y);
intersect.subSelf(slicePlane.getPlane());
intersect
.rotateY((float) (functions.angleOf(new Vec2D(
slicePlane.getPlane().normal.x,
slicePlane.getPlane().normal.z)) - (Math.PI / 2)));
float rotateAn = (functions.angleOf(new Vec2D(
slicePlane.getPlane().normal.x, slicePlane
.getPlane().normal.y)));
if (rotateAn < Math.PI / 2
|| rotateAn > (Math.PI / 2) * 3)
rotateAn = (float) ((Math.PI * 2) - Math
.abs(rotateAn));
intersect.rotateX(rotateAn);
List<Vec2D> listItem = new ArrayList<Vec2D>();
listItem.add(new Vec2D(intersect.x, intersect.y));
listItem.add(intexsecX);
returnList.add(listItem);
}
}
}
}
}
return returnList;
}
/**
* getIntersectionCentre
* @param slicePlane
* @param spline
* @param externalCurvePercent
* @param percentReturn
* @param intersectXReturn
* Return information about a intersection between a slicePlane and a spline
*/
public void getIntersectionCentre(SlicePlane slicePlane,
SketchSpline spline, float externalCurvePercent,
Vec2D percentReturn, Vec2D intersectXReturn) {
//LOGGER.info("");
//LOGGER.info("");
float neartestDist = -1;
Vec3D returnVec3D = null;
int collisionsFound = 0;
float lenToNext = 0;
//return if spline is too short
if (spline.getCentrePath().size() < 2)
return;
spline.getCentrePath().cacheLength(true);
Vec3D p1 = null, p2 = null;
Vec2D p12D = null, p22D = null;
for (int i = 0; i < spline.getCentrePath().size() - 1; i++) {
SketchPoint point1 = spline.getCentrePath().get(i);
SketchPoint point2 = spline.getCentrePath().get(i + 1);
float step = 1;
if (point1.containsBezier() || point2.containsBezier())
step = GLOBAL.SketchGlobals.BEZIER_DETAIL_CALCULATIONS;
float offset = 0;
if (step != 1)
offset = step;
p22D = (Vec2D) point1.copy();
spline.getCentrePath().resetPosStep();
for (float i2 = 0; i2 < 1; i2 += step) {
//If we are on a curve step though the curve
if (step == 1) {
p12D = (Vec2D) spline.getCentrePath().get(i);
p22D = (Vec2D) spline.getCentrePath().get(i + 1);
p1 = this.getWorldPos(p12D);
p2 = this.getWorldPos(p22D);
} else {
p12D = p22D.copy();//get the previous point// (Vec2D) spline.getCentrePath().getPosStep(step);
Vec2D p22dTemp = (Vec2D) spline.getCentrePath().getPosStep(
point1, point2, step);//step to the next point
if (p22dTemp != null) {
p22D = p22dTemp;
}
p1 = this.getWorldPos(p12D);
p2 = this.getWorldPos(p22D);
// LOGGER.info("p1" + p1.x + ":" + p1.y);
// LOGGER.info("p2" + p2.x + ":" + p2.y);
}
if (p2 != null) {
/*
if(p12D.distanceTo(p22D) > 100)
LOGGER.info("-------------------------------------------------------");
LOGGER.info("p12D.distanceTo(p22D); " + p12D.distanceTo(p22D) + " i2 " + i2);
LOGGER.info(" p1 " + p1 + " p2 " + p2);
LOGGER.info("");
*/
//if(p12D.distanceTo(p22D) < 100)
//
lenToNext += p12D.distanceTo(p22D);
// if one point is on one side of the plane and the other point is
// on the other side !
if ((slicePlane.getPlane().classifyPoint(p1) != slicePlane
.getPlane().classifyPoint(p2))) {
//LOGGER.info("i2 on p"+i2 );
Vec3D intersect = null;
//try intersecting ray in one direction
intersect = (Vec3D) slicePlane.getPlane()
.getIntersectionWithRay(
new Ray3D(p1, p2.sub(p1)));
//if we do not find a point try the other direction
if (intersect == null)
intersect = (Vec3D) slicePlane.getPlane()
.getIntersectionWithRay(
new Ray3D(p2, p1.sub(p2)));
//if we do not find a point try the other direction
if (intersect == null)
intersect = (Vec3D) slicePlane.getPlane()
.getIntersectionWithRay(
new Ray3D(p2.sub(p1.sub(p2)), p1
.sub(p2)));
//if we do not find a point try the other direction
if (intersect == null)
intersect = (Vec3D) slicePlane.getPlane()
.getIntersectionWithRay(
new Ray3D(p2.add(p1.sub(p2)), p1
.sub(p2)));
collisionsFound++;
//we found a intersection with the plane
if (intersect != null) {
float distToP1 = intersect.distanceTo(p1); //dist to intersection
float distToP2 = intersect.distanceTo(p2); //dist to intersection
float distBetweenP1P2 = p1.distanceTo(p2);
float percentBetween = distToP1 / distBetweenP1P2; //distBetweenP1P2;
float percent = 0;
//special case for 2 point lines
float splneLen = (spline.getCentrePath()
.getlength());
percent = ((lenToNext - distToP2) / splneLen);
// System.out.println(percentBetween + "in");
// for (int k = 0; k < points.size(); k++) {
// float percent = (Float) points.get(k);
float deltaPercent = Math.abs(percent
- externalCurvePercent);
/*
LOGGER.info("distToP1 " + distToP1 +
" distToP2 "+distToP2 +
" lenToNext " + lenToNext +
" percentBetween " + percentBetween +
" percent" + percent +
" splneLen " + splneLen +
" i " + i + " i2 " + i2 +
" externalCurvePercent "+externalCurvePercent +
" deltaPercent "+ deltaPercent +
" neartestDist " + neartestDist);
*/
if (deltaPercent < neartestDist
|| neartestDist == -1) {
// if ( collisionsFound == 3){
neartestDist = deltaPercent;
percentReturn.x = (p12D.x * (1 - percentBetween))
+ (p22D.x * (percentBetween));
percentReturn.y = (p12D.y * (1 - percentBetween))
+ (p22D.y * (percentBetween));
returnVec3D = intersect.copy();
//if(neartestDist > .2f)
// returnVec3D = null;
// System.out.println(percent +" P");
//LOGGER.info("percent "+percentBetween);
}
// }
// returnList.add(new Float(percent));
}
// System.out.println(p1);
// System.out.println(p2);
}
}
}
//.info("returnVec3D " + returnVec3D);
}
if (returnVec3D != null) {
returnVec3D.subSelf(slicePlane.getPlane());
returnVec3D
.rotateY((float) (functions.angleOf(new Vec2D(slicePlane
.getPlane().normal.x,
slicePlane.getPlane().normal.z)) - (Math.PI / 2)));
float rotateAn = (functions.angleOf(new Vec2D(
slicePlane.getPlane().normal.x,
slicePlane.getPlane().normal.y)));
if (rotateAn < Math.PI / 2 || rotateAn > (Math.PI / 2) * 3){
rotateAn = (float) ((Math.PI * 2) - Math.abs(rotateAn));
}
//LOGGER.info("GRAVITY");
returnVec3D.rotateX(rotateAn);
//LOGGER.info("slicePlane.getPlane().normal.x " +slicePlane.getPlane().normal.x + "slicePlane.getPlane().normal.y " +slicePlane.getPlane().normal.y);
// intersectXReturn = new Vec2D(returnVec3D.x,returnVec3D.y);
intersectXReturn.x = returnVec3D.x;
intersectXReturn.y = returnVec3D.y;
}else{
}
spline.getCentrePath().cacheLength(false);
}
public SketchShape getLastSketch() {
return this.getSketch().getLast();
}
public SketchPoint getOverSelectPoint(float x, float y) {
return this.getSketch().getOverSelectPoint(x, y);
}
public List<SketchShape> getOverShape(float x, float y) {
return this.getSketch().getOverShape(x, y);
}
/**
* @return the plane
*/
public Plane getPlane() {
return plane;
}
/**
* @return the Sketch
*/
public Sketch getSketch() {
return sketch;
}
public SketchShape getSketchShapeById(int linkedSketchId) {
return this.getSketch().getSketchShapeById(linkedSketchId);
}
public spShape getspShape() {
return this.getSketch().getspShape();
}
Vec3D getWorldPos(Vec2D vec) {
if (vec == null)
return null;
Vec3D returnVec = new Vec3D(vec.x, vec.y, 0);
// returnVec.rotateX(this.plane.x);
// returnVec.rotateY(this.plane.y);
// returnVec.rotateZ(this.plane.z);
returnVec.addSelf(this.getPlane());
return returnVec;
}
public Vec3D getWorldPosIntersect(Vec3D vec) {
vec.subSelf(this.getPlane());
vec.rotateY((float) (functions.angleOf(new Vec2D(getPlane().normal.x,
this.getPlane().normal.z)) - (Math.PI / 2)));
float rotateAn = (functions.angleOf(new Vec2D(this.getPlane().normal.x,
this.getPlane().normal.y)));
if (rotateAn < Math.PI / 2 || rotateAn > (Math.PI / 2) * 3)
rotateAn = (float) ((Math.PI * 2) - Math.abs(rotateAn));
vec.rotateX(rotateAn);
return vec;
}
public boolean intersects(SlicePlane otherSlice) {
Vec2D pminYThis = new Vec2D(0, this.profileMinY);
Vec2D pmaxYThis = new Vec2D(0, this.profileMaxY);
float pangleThis = functions.angleOf(new Vec2D(
this.getPlane().normal.x, this.getPlane().normal.y));
Vec2D pposThis = new Vec2D(this.getPlane().x, this.getPlane().y);
pminYThis.rotate(pangleThis);
pmaxYThis.rotate(pangleThis);
pminYThis.addSelf(pposThis);
pmaxYThis.addSelf(pposThis);
Vec2D pminYThat = new Vec2D(0, otherSlice.profileMinY);
Vec2D pmaxYThat = new Vec2D(0, otherSlice.profileMaxY);
float pangleThat = functions
.angleOf(new Vec2D(otherSlice.getPlane().normal.x, otherSlice
.getPlane().normal.y));
Vec2D pposThat = new Vec2D(otherSlice.getPlane().x,
otherSlice.getPlane().y);
pminYThat.rotate(pangleThat);
pmaxYThat.rotate(pangleThat);
pminYThat.addSelf(pposThat);
pmaxYThat.addSelf(pposThat);
if (functions
.intersect(pminYThis.x, pminYThis.y, pmaxYThis.x, pmaxYThis.y,
pminYThat.x, pminYThat.y, pmaxYThat.x, pmaxYThat.y) == functions.DO_INTERSECT) {
return true;
}
return false;
}
/**
* @return the selected
*/
public boolean isSelected() {
return selected;
}
public boolean lastSketchOverlaps() {
return this.getSketch().lastSketchOverlaps();
}
public IndexedMesh loftCollisonMeshBetween(SketchPath coverPath,
SlicePlane planeOther, SketchPath coverPathOther, float stepRes,
Vec3D offset) {
IndexedMesh vertexArray = new IndexedMesh();
if (coverPath == null || coverPath.size() < 2 || coverPathOther == null
|| coverPathOther.size() < 2) {
//System.out.println("cover wrong");
return null;
}
Vec3D prevHere = null;
Vec3D prevThere = null;
int vertNum = ((int) (1 / stepRes) * 3 * 2);
int indNum = (int) (1 / stepRes) * 6;
float[] gVertices = new float[vertNum];
int[] gIndices = new int[indNum];
int SideLen = (int) (1 / stepRes) - 1;
int trigCount = 0;
int step = 0;
for (float i = 0; i <= 1 - stepRes; i += stepRes) {
Vec2D pHere2D = coverPath.getPos(i);
Vec3D pHere = new Vec3D(pHere2D.x, pHere2D.y, this.getPlane().z);
Vec2D pThere2D = coverPathOther.getPos(i);
Vec3D pThere = new Vec3D(pHere2D.x, pHere2D.y,
planeOther.getPlane().z);
if (pHere != null && pThere != null) {
gVertices[((3 * step) + 0)] = GLOBAL.jBullet.scaleVal(pHere.x)
- offset.x;
gVertices[((3 * step) + 1)] = GLOBAL.jBullet.scaleVal(-pHere.y)
+ offset.y;
gVertices[((3 * step) + 2)] = GLOBAL.jBullet.scaleVal(-pHere.z)
- offset.z;
gVertices[((3 * step) + 0) + (SideLen * 3)] = GLOBAL.jBullet
.scaleVal(pThere.x) - offset.x;
gVertices[((3 * step) + 1) + (SideLen * 3)] = GLOBAL.jBullet
.scaleVal(-pThere.y) + offset.y;
gVertices[((3 * step) + 2) + (SideLen * 3)] = GLOBAL.jBullet
.scaleVal(-pThere.z) - offset.z;
// System.out.println("here" + pHere);
// System.out.println("there" + pThere);
//
//
if (prevHere != null && prevThere != null) {
gIndices[((step * 6) + 0)] = (((step - 1)) + 0);
gIndices[((step * 6) + 1)] = (((SideLen + step - 1)) + 0);
gIndices[((step * 6) + 2)] = ((step) + 0);
gIndices[((step * 6) + 3)] = ((step) + 0);
gIndices[((step * 6) + 4)] = (((SideLen + step - 1)) + 0);
gIndices[((step * 6) + 5)] = (((SideLen + step)) + 0);
trigCount++;
trigCount++;
}
prevHere = pHere;
prevThere = pThere;
step++;
} else {
// System.out.println("NULL");
}
}
// System.out.println("start");
// for(float i : gVertices){
// System.out.println(i);
// }
// System.out.println("end");
// System.out.println("steps" + step + " : " + vertNum/6);
//
indexVertexArray = new TriangleIndexVertexArray(trigCount,
functions.getIndexBuffer(gIndices), 4 * 3, step / 3,
functions.getVertexBuffer(gVertices), 4 * 3);
//System.out
// .println(indexVertexArray.getIndexedMeshArray().get(0).numVertices);
indexedMesh = indexVertexArray.getIndexedMeshArray().get(0);
// System.out.println("made");
return indexedMesh;
}
/*
public void loftFelt(SlicePlane nextSlice, FeltCover felt) {
SketchPath thisPath = this.getSketch().getFirst().getPath();
SketchPath thatPath = this.getSketch().getFirst().getPath();
for (int i = 0; i <= 1 - SETTINGS_SKETCH.feltResolution; i += SETTINGS_SKETCH.feltResolution) {
// Vec3D thisPathp1 = thisPathp1.g
}
}
*/
public void mouseDragged(float mouseX, float mouseY) {
Vec2D v = GLOBAL.uiTools.getPointOnPlane(new Vec2D(mouseX, mouseY),
this.getPlane());
this.getSketch().mouseDragged(v.x, v.y);
if (SETTINGS.DEBUG) {
debugMousePoint = v.copy();
}
}
public void mousePressed(float mouseX, float mouseY) {
Vec2D v = GLOBAL.uiTools.getPointOnPlane(new Vec2D(mouseX, mouseY),
this.getPlane());
this.getSketch().mousePressed(v.x, v.y);
}
public void mouseReleased(float mouseX, float mouseY) {
Vec2D v = GLOBAL.uiTools.getPointOnPlane(new Vec2D(mouseX, mouseY),
this.getPlane());
this.getSketch().mouseReleased(v.x, v.y);
}
public void mouseDoubleClick(int mouseX, int mouseY) {
Vec2D v = GLOBAL.uiTools.getPointOnPlane(new Vec2D(mouseX, mouseY),
this.getPlane());
this.getSketch().mouseDoubleClick(v.x, v.y);
}
public boolean overSelectPoint(float mouseX, float mouseY) {
if (this.getSketch().overSelectPoint(mouseX, mouseY))
return true;
else
return false;
}
void recordCollision() {
}
public void removeVertex(SketchPoint v) {
this.getSketch().removeVertex(v);
}
public void render(PGraphics g) {
g.pushMatrix();
this.applyRotationMatrix(g);
//render debug point
if (SETTINGS.DEBUG && debugMousePoint != null) {
g.noFill();
g.stroke(255,0,0);
g.ellipse(debugMousePoint.x, debugMousePoint.y, 30, 30);
}
//optimize so that we do not draw the side view unless we need to.
//currently is only relative to camera rotation, if a model rotates side view will not be drawn
g.bezierDetail(SETTINGS_SKETCH.BEZIER_DETAIL_EDIT);
if (this.getPlane().normal.z == -1) {
this.getSketch().render(g);
} else {
g.bezierDetail(SETTINGS_SKETCH.BEZIER_DETAIL_3D_PREVIEW);
if(getSketch().getRenderMode() == Sketch.RENDER_3D_DIAGRAM)
g.bezierDetail(SETTINGS_SKETCH.BEZIER_DETAIL_3D_DIAGRAM);
if (GLOBAL.rotateModelsX == 0 && GLOBAL.rotateModelsY == 0
&& !GLOBAL.screenshot && this.getSketch().getRenderMode() != Sketch.RENDER_3D_DIAGRAM
&& this.getSketch().getRenderMode() != Sketch.RENDER_3D_PREVIW) {
this.getSketch().renderSide(g);
} else{
this.getSketch().render(g);
}
}
if (SETTINGS.DEBUG) {
g.stroke(255, 0, 0);
for (int i = 0; i < this.debugIntersectionPoints.size(); i++) {
Vec2D p = this.debugIntersectionPoints.get(i);
float crossWidth = 20;
g.line(p.x - (crossWidth / 2), p.y + (crossWidth / 2), p.x
+ (crossWidth / 2), p.y - (crossWidth / 2));
g.line(p.x + (crossWidth / 2), p.y + (crossWidth / 2), p.x
- (crossWidth / 2), p.y - (crossWidth / 2));
//g.ellipse(p.x,p.y,0,20);
}
g.stroke(0, 0, 255);
for (int i = 0; i < this.debugIntersectionPointsTop.size(); i++) {
Vec2D p = this.debugIntersectionPointsTop.get(i);
float tWidth = 20;
float hover = 20;
if (p != null) {
g.line(p.x, p.y - hover, p.x, p.y - (tWidth + hover));
g.line(p.x - (tWidth / 2), p.y - (tWidth + hover), p.x
+ (tWidth / 2), p.y - (tWidth + hover));
}
}
g.stroke(0, 0, 255);
for (int i = 0; i < this.debugIntersectionPointsBottom.size(); i++) {
Vec2D p = this.debugIntersectionPointsBottom.get(i);
float bHeight = 20;
float bWidth = 10;
float hover = 20;
if (p != null) {
g.line(p.x - (bWidth / 2), p.y + hover, p.x - (bWidth / 2),
p.y + (bHeight + hover));
g.ellipse(p.x, p.y + (bHeight + hover - bWidth / 2),
bWidth, bWidth);
}
}
if (debugIntersetStart != null) {
g.stroke(0, 255, 0);
g.ellipse(debugIntersetStart.x, debugIntersetStart.y, 40, 40);
}
}
g.popMatrix();
}
public void renderPickBuffer(PGraphics pickBuffer) {
pickBuffer.fill(PickBuffer.getInstance().getPickColour(this));
pickBuffer.noStroke();
pickBuffer.pushMatrix();
this.applyRotationMatrix(pickBuffer);
pickBuffer.bezierDetail(SETTINGS_SKETCH.BEZIER_DETAIL_3D_PREVIEW);
this.getSketch().renderPickBuffer(pickBuffer);
pickBuffer.popMatrix();
}
public void renderSilhouette(PGraphics g) {
g.pushMatrix();
this.applyRotationMatrix(g);
g.fill(39, 35, 36);
g.noStroke();
this.getSketch().renderSilhouette(g);
g.popMatrix();
}
/*
* float[] gVertices = new float[vertNum]; for(int i = 0; i <
* triangulate.vertexs.size(); i++){ Delaunay.Vertex v =
* (Delaunay.Vertex)triangulate.vertexs.get(i);
* //System.out.println(this.offset.z); gVertices[(3*v.getIndex())+0] =
* GLOBAL.jBullet.scaleVal((float)v.x) - offsetX; gVertices[(3*v.getIndex())+1]
* = GLOBAL.jBullet.scaleVal((float)-v.y)+ offsetY;
* gVertices[(3*v.getIndex())+2] = GLOBAL.jBullet.scaleVal(this.plane.z) -
* offsetZ;
*
* // System.out.println((int)(3*v.getIndex()) + " x:" +
* gVertices[(3*v.getIndex())+0]+ "y:" + gVertices[(3*v.getIndex())+1]+ "z:" +
* gVertices[(3*v.getIndex())+2] );
*
* }
*
*
*
* int indNum = (triangulate.triangles.size()*3); int triNum =
* triangulate.triangles.size(); int indDiffNum =
* (triangulate.triangles.size()); int[] gIndices = new int[indNum];
*
* for(int i = 0; i < triangulate.triangles.size(); i++){ Delaunay.Triangle t =
* (Delaunay.Triangle)triangulate.triangles.get(i); gIndices[(i*3)+0] =
* (t.get_vertex(0).getIndex()); gIndices[(i*3)+1] =
* (t.get_vertex(1).getIndex()); gIndices[(i*3)+2] =
* (t.get_vertex(2).getIndex());
*
* }
*
*
* indexVertexArray = new TriangleIndexVertexArray(triNum, functions
* .getIndexBuffer(gIndices), 4 * 3, vertNum/3, functions
* .getVertexBuffer(gVertices), 4 * 3);
*/
void resetRecordedCollisions() {
}
public void scale(float scale, Vec3D centre) {
// scale z dir
this.getPlane().z += ((this.getPlane().z - centre.z) * scale);
this.getSketch().scale(scale, centre);
}
public void select() {
this.setSelected(true);
this.getSketch().select();
this.getSketch().setLayerSelected(true);
}
public void selectNodes(int mouseX, int mouseY) {
if (this.getPlane() != null && this.getSketch() != null) {
Vec2D transMouse = GLOBAL.uiTools.getPointOnPlane(new Vec2D(mouseX,
mouseY), this.getPlane());
if (transMouse != null)
this.getSketch().selectNodes(transMouse.x, transMouse.y);
}
}
public void setBrushCap(int cap) {
this.getSketch().setBrushCap(cap);
}
public void setBrushDia(float val) {
this.getSketch().setBrushDia(val);
}
/**
* @param plane the plane to set
*/
public void setPlane(Plane plane) {
this.plane = plane;
}
public void setRenderMode(int mode) {
this.getSketch().setRenderMode(mode);
}
/**
* @param selected the selected to set
*/
public void setSelected(boolean selected) {
this.selected = selected;
}
/**
* @param Sketch2 the Sketch to set
*/
public void setSketch(Sketch s) {
this.sketch = s;
}
public void toggleUnion() {
this.getSketch().toggleUnion();
}
public nu.xom.Element toXML() {
Element element = new Element("SlicePlane");
element.addAttribute(new Attribute("id", String.valueOf(this.getId())));
if (this.guide)
element.addAttribute(new Attribute("guide", String
.valueOf(this.guide)));
Element plane = new Element("Plane");
plane.addAttribute(new Attribute("x", String.valueOf(this.getPlane().x)));
plane.addAttribute(new Attribute("y", String.valueOf(this.getPlane().y)));
plane.addAttribute(new Attribute("z", String.valueOf(this.getPlane().z)));
plane.addAttribute(new Attribute("nx",
String.valueOf(this.getPlane().normal.x)));
plane.addAttribute(new Attribute("ny",
String.valueOf(this.getPlane().normal.y)));
plane.addAttribute(new Attribute("nz",
String.valueOf(this.getPlane().normal.z)));
element.appendChild(plane);
element.appendChild(getSketch().toXML());
return element;
}
public void unselect() {
this.setSelected(false);
this.getSketch().unselect();
this.getSketch().setLayerSelected(false);
if(this.getCrossSliceSelection() != null)
this.getCrossSliceSelection().selected = false;
}
public void update() {
if(thickness <= 0)
thickness = .1f;
this.getSketch().update();
this.generate();
this.getSketch().getSlots().update();
if (this.constraintSlot != null) {
}
//this.Sketch.buildOutline();
}
public void buildOutline(boolean includeSlot, boolean addToPath) {
this.getSketch().buildOutline(includeSlot, addToPath);
}
public void importSVG(String path) {
this.getSketch().importSVG(path);
}
public void setEditable(boolean editable) {
this.getSketch().setEditable(editable);
}
/**
* @return the crossSliceSelection
*/
public CrossSliceSelection getCrossSliceSelection() {
return crossSliceSelection;
}
/**
* @param crossSliceSelection the crossSliceSelection to set
*/
public void setCrossSliceSelection(CrossSliceSelection crossSliceSelection) {
this.crossSliceSelection = crossSliceSelection;
crossSliceSelection.planes.add(this);
}
public void setRender3D(boolean b) {
this.getSketch().setRender3D(b);
}
public void unselectShapes() {
this.getSketch().unselectShapes();
}
}