package org.geogebra.common.geogebra3D.euclidian3D.draw; import java.util.ArrayList; import java.util.Map.Entry; import org.geogebra.common.euclidian.Previewable; import org.geogebra.common.euclidian.draw.DrawPoint; import org.geogebra.common.geogebra3D.euclidian3D.EuclidianView3D; import org.geogebra.common.geogebra3D.euclidian3D.Hitting; import org.geogebra.common.geogebra3D.euclidian3D.openGL.Renderer; import org.geogebra.common.geogebra3D.euclidian3D.printer3D.ExportToPrinter3D; import org.geogebra.common.geogebra3D.euclidian3D.printer3D.ExportToPrinter3D.Type; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.arithmetic.Functional2Var; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.kernelND.GeoPointND; //TODO does not extend Drawable3DCurves /** * Class for drawing 3D points. * * @author matthieu * * */ public class DrawPoint3D extends Drawable3DCurves implements Previewable, Functional2Var { /** factor for drawing points */ public static final float DRAW_POINT_FACTOR = 1.5f; /** * common constructor * * @param view3D * @param point */ public DrawPoint3D(EuclidianView3D view3D, GeoPointND point) { super(view3D, (GeoElement) point); } @Override public void drawGeometry(Renderer renderer) { renderer.getGeometryManager().draw(getGeometryIndex(), center); } @Override public void exportToPrinter3D(ExportToPrinter3D exportToPrinter3D) { if (isVisible()) { exportToPrinter3D.export(this, Type.POINT); } } @Override public void drawGeometryHidden(Renderer renderer) { drawGeometry(renderer); } @Override protected void setLineTextureHidden(Renderer renderer) { // nothing to do here } private Coords center = new Coords(4); /** * * @return point center */ public Coords getCenter() { return center; } private Coords boundsMin = new Coords(3), boundsMax = new Coords(3); @Override protected boolean updateForItSelf() { GeoPointND point = (GeoPointND) getGeoElement(); // center.setValues(point.getInhomCoordsInD3(), 3); Coords c = point.getInhomCoordsInD3(); center.setValues(c, 3); center.setW(point.getPointSize()); // put point size in fourth unused // coord // warning: plotter will scale center coords setGeometryIndex(getView3D().getRenderer().getGeometryManager() .drawPoint(point.getPointSize(), center, getReusableGeometryIndex())); // bounds double radius = point.getPointSize() / getView3D().getScale() * DrawPoint3D.DRAW_POINT_FACTOR; boundsMin.setX(c.getX() - radius); boundsMin.setY(c.getY() - radius); boundsMin.setZ(c.getZ() - radius); boundsMax.setX(c.getX() + radius); boundsMax.setY(c.getY() + radius); boundsMax.setZ(c.getZ() + radius); return true; } @Override protected void doRemoveGeometryIndex(int index) { // for shaders: use Manager templates -- no remove for points if (!getView3D().getRenderer().useShaders()) { super.doRemoveGeometryIndex(index); } } @Override protected void updateForView() { if (getView3D().viewChangedByZoom()) { updateForItSelf(); } } @Override public int getPickOrder() { return DRAW_PICK_ORDER_POINT; } // ////////////////////////////// // Previewable interface /** * @param a_view3D */ public DrawPoint3D(EuclidianView3D a_view3D) { super(a_view3D); setGeoElement(a_view3D.getCursor3D()); } @Override public void disposePreview() { // TODO Auto-generated method stub } @Override public void updateMousePos(double xRW, double yRW) { // not needed in 3D } @Override public void updatePreview() { // not needed } @Override public void addToDrawable3DLists(Drawable3DLists lists) { addToDrawable3DLists(lists, DRAW_TYPE_POINTS); } @Override public void removeFromDrawable3DLists(Drawable3DLists lists) { removeFromDrawable3DLists(lists, DRAW_TYPE_POINTS); } // ///////////////////////////////// // FUNCTION2VAR INTERFACE // ///////////////////////////////// public void evaluatePoint(double u, double v, Coords point) { GeoPointND geoPoint = (GeoPointND) getGeoElement(); double r = geoPoint.getPointSize() / getView3D().getScale() * 1.5; point.set(Math.cos(u) * Math.cos(v) * r, Math.sin(u) * Math.cos(v) * r, Math.sin(v) * r, 1); point.setAdd3(point, geoPoint.getInhomCoordsInD3()); } @Override public Coords evaluateNormal(double u, double v) { return new Coords(new double[] { Math.cos(u) * Math.cos(v), Math.sin(u) * Math.cos(v), Math.sin(v) }); } @Override public double getMinParameter(int index) { switch (index) { case 0: // u default: return 0; case 1: // v return -Math.PI / 2; } } @Override public double getMaxParameter(int index) { switch (index) { case 0: // u default: return 2 * Math.PI; case 1: // v return Math.PI / 2; } } @Override protected float getLabelOffsetX() { // consistent with DrawPoint return super.getLabelOffsetX() + 4; } @Override protected float getLabelOffsetY() { // consistent with DrawPoint return super.getLabelOffsetY() - 2 * ((GeoPointND) getGeoElement()).getPointSize(); } @Override protected double getColorShift() { return COLOR_SHIFT_POINTS; } @Override public boolean hit(Hitting hitting) { GeoPointND point = (GeoPointND) getGeoElement(); Coords p = point.getInhomCoordsInD3(); return DrawPoint3D.hit(hitting, p, this, point.getPointSize(), project, parameters, false); } @Override public boolean hitForList(Hitting hitting) { if (hasGeoElementVisible() && getGeoElement().isPickable()) { GeoPointND point = (GeoPointND) getGeoElement(); Coords p = point.getInhomCoordsInD3(); return DrawPoint3D.hit(hitting, p, this, point.getPointSize(), project, parameters, true); } return false; } /** * * @param hitting * hitting * @param p * point coords * @param drawable * drawable calling * @param pointSize * point size * @param project * temp coords for projection * @param parameters * temp values for paramters * @param checkRealPointSize * true if we check point size (and not threshold) * @return true if the hitting hits the point */ static public boolean hit(Hitting hitting, Coords p, Drawable3D drawable, int pointSize, Coords project, double[] parameters, boolean checkRealPointSize) { if (hitting.isSphere()) { double d = drawable.getView3D().getScaledDistance(p, hitting.origin); if (d <= pointSize + hitting.getThreshold()) { // double z = -parameters[0]; // double dz = pointSize/scale; drawable.setZPick(-d, -d); return true; } } else { p.projectLine(hitting.origin, hitting.direction, project, parameters); if (!hitting.isInsideClipping(project)) { return false; } double d = drawable.getView3D().getScaledDistance(p, project); boolean hitted; if (checkRealPointSize) { hitted = d <= pointSize + 2; } else { hitted = d <= DrawPoint .getSelectionThreshold(hitting.getThreshold()); } if (hitted) { double z = -parameters[0]; double dz = pointSize / drawable.getView3D().getScale(); drawable.setZPick(z + dz, z - dz); return true; } } return false; } private Coords project = Coords.createInhomCoorsInD3(); private double[] parameters = new double[2]; @Override protected TraceIndex newTraceIndex() { return new TraceIndex(getGeometryIndex(), getSurfaceIndex(), center.copyVector()); } @Override protected void drawGeom(Renderer renderer, TraceIndex index) { renderer.getGeometryManager().draw(index.geom, index.center); } @Override public void enlargeBounds(Coords min, Coords max) { enlargeBounds(min, max, boundsMin, boundsMax); } @Override protected void drawTracesOutline(Renderer renderer, boolean hidden) { if (!hidden) { return; } if (trace == null) { return; } for (Entry<TraceSettings, ArrayList<TraceIndex>> settings : trace .entrySet()) { ArrayList<TraceIndex> indices = settings.getValue(); setDrawingColor(settings.getKey().getColor()); // Log.debug(indices.size()); for (TraceIndex index : indices) { drawGeom(renderer, index); } } } }