package org.geogebra.common.geogebra3D.euclidian3D.draw;
import java.util.ArrayList;
import org.geogebra.common.euclidian.EuclidianConstants;
import org.geogebra.common.euclidian.Hits;
import org.geogebra.common.euclidian.Previewable;
import org.geogebra.common.geogebra3D.euclidian3D.EuclidianController3D;
import org.geogebra.common.geogebra3D.euclidian3D.EuclidianView3D;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.Renderer;
import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoForExtrusion;
import org.geogebra.common.geogebra3D.kernel3D.algos.ExtrusionComputer;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoNumberValue;
import org.geogebra.common.kernel.geos.GeoNumeric;
import org.geogebra.common.kernel.geos.GeoPolygon;
import org.geogebra.common.kernel.kernelND.GeoConicND;
import org.geogebra.common.main.App;
import org.geogebra.common.util.AsyncOperation;
/**
* Class for drawing extrusions.
*
* @author matthieu
*
*/
public abstract class DrawExtrusionOrConify3D extends Drawable3DSurfaces
implements Previewable {
/** basis */
private ArrayList<GeoPolygon> selectedPolygons;
private ArrayList<GeoConicND> selectedConics;
/** extrusion computer */
protected ExtrusionComputer extrusionComputer;
private GeoNumeric height;
private GeoElement basis;
// drawing
@Override
protected void drawSurfaceGeometry(Renderer renderer) {
// nothing to do
}
@Override
public void drawGeometry(Renderer renderer) {
// nothing to do
}
@Override
public void drawGeometryHiding(Renderer renderer) {
drawGeometry(renderer);
}
@Override
public void drawGeometryHidden(Renderer renderer) {
// nothing to do
}
@Override
public void drawOutline(Renderer renderer) {
// no outline
}
@Override
public int getPickOrder() {
return DRAW_PICK_ORDER_SURFACE;
}
@Override
public void addToDrawable3DLists(Drawable3DLists lists) {
addToDrawable3DLists(lists, DRAW_TYPE_CLOSED_SURFACES_CURVED);
}
@Override
public void removeFromDrawable3DLists(Drawable3DLists lists) {
removeFromDrawable3DLists(lists, DRAW_TYPE_CLOSED_SURFACES_CURVED);
}
@Override
protected boolean updateForItSelf() {
return true;
}
// //////////////////////////////
// Previewable interface
/**
* Constructor for previewable
*
* @param a_view3D
* view
* @param selectedPolygons
* polygons
* @param selectedConics
* conics
*/
public DrawExtrusionOrConify3D(EuclidianView3D a_view3D,
ArrayList<GeoPolygon> selectedPolygons,
ArrayList<GeoConicND> selectedConics) {
super(a_view3D);
this.selectedPolygons = selectedPolygons;
this.selectedConics = selectedConics;
updatePreview();
}
@Override
public void updateMousePos(double xRW, double yRW) {
// TODO Auto-generated method stub
}
/**
*
* @param extBasis
* polygon
* @param extHeight
* altitude
* @return new algo from polygon and height
*/
abstract protected AlgoForExtrusion getAlgo(GeoPolygon extBasis,
GeoNumeric extHeight);
/**
*
* @param extBasis
* conic
* @param extHeight
* altitude
* @return new algo from polygon and height
*/
abstract protected AlgoForExtrusion getAlgo(GeoConicND extBasis,
GeoNumeric extHeight);
@Override
public void updatePreview() {
if (extrusionComputer == null) {
if (selectedPolygons.size() == 1) {
basis = selectedPolygons.get(0);
// create the height
height = new GeoNumeric(
getView3D().getKernel().getConstruction(), 0.0001);
// create the algo
extrusionComputer = new ExtrusionComputer(
getAlgo((GeoPolygon) basis, height));
} else if (selectedConics.size() == 1) {
basis = selectedConics.get(0);
// create the height
height = new GeoNumeric(
getView3D().getKernel().getConstruction(), 0.0001);
// create the algo
extrusionComputer = new ExtrusionComputer(
getAlgo((GeoConicND) basis, height));
}
if (extrusionComputer != null) {
extrusionComputer.getAlgo().removeOutputFromAlgebraView();
extrusionComputer.getAlgo().removeOutputFromPicking();
extrusionComputer.getAlgo()
.setOutputPointsEuclidianVisible(false);
extrusionComputer.getAlgo().notifyUpdateOutputPoints();
// sets the top face to be handled
((EuclidianController3D) getView3D().getEuclidianController())
.setHandledGeo(
extrusionComputer.getAlgo().getGeoToHandle());
// ensure correct drawing of visible parts of the previewable
extrusionComputer.getAlgo()
.setOutputOtherEuclidianVisible(true);
extrusionComputer.getAlgo().notifyUpdateOutputOther();
}
}
}
@Override
public void disposePreview() {
super.disposePreview();
((EuclidianController3D) getView3D().getEuclidianController())
.setHandledGeo(null);
if (extrusionComputer != null) {
// remove the algo
extrusionComputer.getAlgo().remove();
extrusionComputer = null;
}
}
/**
* Creates the polyhedron
*/
public void createPolyhedron() {
((EuclidianController3D) getView3D().getEuclidianController())
.setHandledGeo(null);
if (extrusionComputer != null) {
// add current height to selected numeric (will be used on next
// EuclidianView3D::rightPrism() call)
Hits hits = new Hits();
if (extrusionComputer.getComputed() == 0) {// if height has not been
// set by dragging, ask
// one
App app = getView3D().getApplication();
if (callback == null) {
callback = new CreatePolyhedronCallback();
}
callback.set(basis, getView3D(), extrusionComputer);
app.getDialogManager().showNumberInputDialog(
// app.getMenu(getView3D().getKernel().getModeText(EuclidianConstants.MODE_RIGHT_PRISM)),
extrusionComputer.getAlgo().getOutput(0)
.translatedTypeString(),
app.getLocalization().getMenu("Altitude"), "",
// check basis direction / view direction to say if the
// sign has to be forced
basis.getMainDirection()
.dotproduct(getView3D().getViewDirection()) > 0,
app.getLocalization().getMenu(
"PositiveValuesFollowTheView"),
callback);
} else {
hits.add(height);
getView3D().getEuclidianController()
.addSelectedNumberValue(hits, 1, false, false);
}
if (extrusionComputer != null) {
// remove the algo
extrusionComputer.getAlgo().remove();
extrusionComputer = null;
}
}
}
private CreatePolyhedronCallback callback;
/**
* Callback after height is entered
*
*/
static class CreatePolyhedronCallback
extends AsyncOperation<GeoNumberValue> {
private GeoElement basis;
private EuclidianView3D view;
private ExtrusionComputer extrusionComputer;
/**
* @param basis
* polyhedron / quadric basis
* @param view
* view
* @param extrusionComputer
* conifier / extruder
*/
public void set(GeoElement basis, EuclidianView3D view,
ExtrusionComputer extrusionComputer) {
this.basis = basis;
this.view = view;
this.extrusionComputer = extrusionComputer;
}
@Override
public void callback(GeoNumberValue obj) {
GeoNumberValue num = obj;
// Log.debug("callback : "+num + "," + basis + " ,
// "+extrusionComputer);
if (extrusionComputer != null) {
// remove the algo
extrusionComputer.getAlgo().remove();
extrusionComputer = null;
}
GeoElement ret;
if (basis.isGeoPolygon()) {
if (view.getEuclidianController()
.getMode() == EuclidianConstants.MODE_EXTRUSION) {
// prism
ret = basis.getKernel().getManager3D().Prism(null,
(GeoPolygon) basis, num)[0];
} else {
// pyramid
ret = basis.getKernel().getManager3D().Pyramid(null,
(GeoPolygon) basis, num)[0];
}
} else { // basis.isGeoConic()
if (view.getEuclidianController()
.getMode() == EuclidianConstants.MODE_EXTRUSION) {
// cylinder
ret = basis.getKernel().getManager3D().CylinderLimited(null,
(GeoConicND) basis, num)[0];
} else {
// cone
ret = basis.getKernel().getManager3D().ConeLimited(null,
(GeoConicND) basis, num)[0];
}
}
view.getEuclidianController().setDialogOccurred();
view.getApplication().getSelectionManager().clearLists();
view.getApplication().getSelectionManager().clearSelectedGeos(false,
false);
view.getApplication().getSelectionManager().addSelectedGeo(ret,
true, true);
}
}
}