package org.geogebra.common.geogebra3D.euclidian3D.printer3D;
import org.geogebra.common.geogebra3D.euclidian3D.EuclidianView3D;
import org.geogebra.common.geogebra3D.euclidian3D.draw.DrawPoint3D;
import org.geogebra.common.geogebra3D.euclidian3D.draw.Drawable3D;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.GLBuffer;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.GLBufferIndices;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.ManagerShaders.GeometriesSet;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.ManagerShaders.Geometry;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.ManagerShadersElementsGlobalBuffer;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.ManagerShadersElementsGlobalBuffer.GeometryElementsGlobalBuffer;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.PlotterBrush;
import org.geogebra.common.kernel.Matrix.Coords;
import org.geogebra.common.kernel.discrete.PolygonTriangulation.Convexity;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoPolygon;
public abstract class ExportToPrinter3D {
static public enum Type {
CURVE, CURVE_CLOSED, SURFACE_CLOSED, POINT
}
private Format format;
private ManagerShadersElementsGlobalBuffer manager;
private EuclidianView3D view;
private StringBuilder sb;
private Coords center = null;
private boolean reverse = false;
/**
* constructor
*/
public ExportToPrinter3D() {
format = new FormatJscad();
// format = new FormatScad();
sb = new StringBuilder();
}
/**
* set view and manager
*
* @param view
* 3D view
* @param manager
* geometries manager
*/
final protected void set(EuclidianView3D view,
ManagerShadersElementsGlobalBuffer manager) {
this.view = view;
this.manager = manager;
}
public void export(Drawable3D d, Type type) {
reverse = false;
GeometriesSet currentGeometriesSet = manager
.getGeometrySet(d.getGeometryIndex());
if (type == Type.POINT) {
center = ((DrawPoint3D) d).getCenter();
} else {
center = null;
}
if (currentGeometriesSet != null) {
sb.setLength(0);
for (Geometry g : currentGeometriesSet) {
GeometryElementsGlobalBuffer geometry = (GeometryElementsGlobalBuffer) g;
GeoElement geo = d.getGeoElement();
format.getObjectStart(sb, geo.getGeoClassType(),
geo.getLabelSimple());
// object is a polyhedron
format.getPolyhedronStart(sb);
// vertices
boolean notFirst = false;
format.getVerticesStart(sb);
GLBuffer fb = geometry.getVertices();
for (int i = 0; i < geometry.getLength(); i++) {
double x = fb.get();
double y = fb.get();
double z = fb.get();
getVertex(notFirst, x, y, z);
notFirst = true;
}
format.getVerticesEnd(sb);
fb.rewind();
// faces
GLBufferIndices bi = geometry.getCurrentBufferI();
format.getFacesStart(sb);
notFirst = false;
for (int i = 0; i < geometry.getIndicesLength() / 3; i++) {
int v1 = bi.get();
int v2 = bi.get();
int v3 = bi.get();
getFace(notFirst, v1, v2, v3);
notFirst = true;
}
bi.rewind();
if (type == Type.CURVE) {
// face for start
for (int i = 1; i < 7; i++) {
getFace(notFirst, 0, i, i + 1);
}
}
// update index
int l = geometry.getLength();
if (type == Type.CURVE) {
// face for end
for (int i = 2; i < 8; i++) {
getFace(notFirst, l - 1, l - i, l - i - 1);
}
}
format.getFacesEnd(sb); // end of faces
// end of polyhedron
format.getPolyhedronEnd(sb);
}
printToFile(sb.toString());
}
}
public void export(GeoPolygon polygon, Coords[] vertices) {
sb.setLength(0);
// check if the polygon is convex
Convexity convexity = polygon.getPolygonTriangulation().checkIsConvex();
if (convexity != Convexity.NOT) {
Coords n = polygon.getMainDirection();
double delta = 3 * PlotterBrush.LINE3D_THICKNESS / view.getScale();
double dx = n.getX() * delta;
double dy = n.getY() * delta;
double dz = n.getZ() * delta;
int length = polygon.getPointsLength();
reverse = polygon.getReverseNormalForDrawing()
^ (convexity == Convexity.CLOCKWISE);
format.getObjectStart(sb, polygon.getGeoClassType(),
polygon.getLabelSimple());
// object is a polyhedron
format.getPolyhedronStart(sb);
// vertices
boolean notFirst = false;
format.getVerticesStart(sb);
for (int i = 0; i < length; i++) {
Coords v = vertices[i];
getVertex(notFirst, v.getX() + dx, v.getY() + dy,
v.getZ() + dz);
notFirst = true;
getVertex(notFirst, v.getX() - dx, v.getY() - dy,
v.getZ() - dz);
}
format.getVerticesEnd(sb);
// faces
format.getFacesStart(sb);
notFirst = false;
for (int i = 1; i < length - 1; i++) {
getFace(notFirst, 0, 2 * i, 2 * (i + 1)); // bottom
notFirst = true;
getFace(notFirst, 1, 2 * (i + 1) + 1, 2 * i + 1); // bottom
}
for (int i = 0; i < length; i++) { // side
getFace(notFirst, 2 * i, 2 * i + 1, (2 * i + 3) % (2 * length));
getFace(notFirst, 2 * i, (2 * i + 3) % (2 * length),
(2 * i + 2) % (2 * length));
}
format.getFacesEnd(sb); // end of faces
// end of polyhedron
format.getPolyhedronEnd(sb);
printToFile(sb.toString());
} else {
// TODO implement non convex polygons
}
}
/**
*
* @return 3D printer format
*/
public Format getFormat() {
return format;
}
/**
* Print script to a file
*
* @param s
* exported script
*/
abstract protected void printToFile(String s);
private void getVertex(boolean notFirst, double x0, double y0, double z0) {
double x = x0;
double y = y0;
double z = z0;
if (center != null) {
double r = center.getW() * DrawPoint3D.DRAW_POINT_FACTOR
/ view.getScale();
x = center.getX() + x * r;
y = center.getY() + y * r;
z = center.getZ() + z * r;
}
if (notFirst) {
format.getVerticesSeparator(sb);
}
format.getVertices(sb, x, y, z);
}
private void getFace(boolean notFirst, int v1, int v2, int v3) {
if (notFirst) {
format.getFacesSeparator(sb);
}
if (reverse) {
format.getFaces(sb, v1, v3, v2);
} else {
format.getFaces(sb, v1, v2, v3);
}
}
}