package org.geogebra.common.geogebra3D.kernel3D.algos; import java.util.Collection; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPoint3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPolygon3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPolyhedron; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoSegment3D; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.arithmetic.NumberValue; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoPolygon; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.kernel.kernelND.GeoSegmentND; /** * @author ggb3D * * Creates a new Prism * */ public class AlgoPolyhedronPointsPrism extends AlgoPolyhedronPoints { /** * @param c * @param labels * @param polygon * @param point */ public AlgoPolyhedronPointsPrism(Construction c, String[] labels, GeoPolygon polygon, GeoPointND point) { super(c, labels, polygon, point); } /** * @param c * @param labels * @param points */ public AlgoPolyhedronPointsPrism(Construction c, String[] labels, GeoPointND[] points) { super(c, labels, points); } /** * @param c * @param labels * @param polygon * @param height */ public AlgoPolyhedronPointsPrism(Construction c, String[] labels, GeoPolygon polygon, NumberValue height) { super(c, labels, polygon, height); } @Override protected void createPolyhedron(GeoPointND[] bottomPoints) { setBottom(polyhedron); GeoPointND topPoint = getTopPoint(); bottomPointsLength = bottomPoints.length; // ///////// // vertices // ///////// outputPoints.augmentOutputSize(bottomPointsLength - 1); points = new GeoPointND[bottomPointsLength * 2]; for (int i = 0; i < bottomPointsLength; i++) { points[i] = bottomPoints[i]; } points[bottomPointsLength] = topPoint; for (int i = 0; i < bottomPointsLength - 1; i++) { GeoPoint3D point = outputPoints.getElement(i + 1 - getShift()); points[bottomPointsLength + 1 + i] = point; } // ///////// // faces // ///////// // bottom has already been set // sides of the prism for (int i = 0; i < bottomPointsLength; i++) { polyhedron.startNewFace(); polyhedron.addPointToCurrentFace(points[i]); polyhedron.addPointToCurrentFace( points[(i + 1) % (bottomPointsLength)]); polyhedron.addPointToCurrentFace(points[bottomPointsLength + ((i + 1) % (bottomPointsLength))]); polyhedron.addPointToCurrentFace(points[bottomPointsLength + i]); polyhedron.endCurrentFace(); } // top of the prism polyhedron.startNewFace(); for (int i = 0; i < bottomPointsLength; i++) { polyhedron.addPointToCurrentFace(points[bottomPointsLength + i]); } polyhedron.endCurrentFace(); polyhedron.setCurrentFaceIsTopFace(); // for (int i=0; i<faces.length; i++) Application.debug(faces[i]); polyhedron.setType(GeoPolyhedron.TYPE_PRISM); } /** * * @param index * index of the point * @return top point #index */ protected GeoPointND getTopPoint(int index) { if (index == 0) { return getTopPoint(); } return outputPoints.getElement(index - getShift()); } @Override protected void updateOutput(int newBottomPointsLength) { // current length of top points int nOld = outputPoints.size() + getShift(); GeoPointND[] bottomPoints = getBottomPoints(); GeoSegmentND[] bottomSegments = getBottom().getSegments(); if (newBottomPointsLength > nOld) { // update segments linked polyhedron.updateSegmentsLinked(); int length = newBottomPointsLength - nOld; outputPoints.augmentOutputSize(length, false); if (getPolyhedron().allLabelsAreSet()) { outputPoints.setLabels(null); } updateOutputPoints(); // new sides of the prism int l = nOld + length; for (int i = nOld; i < l; i++) { polyhedron.startNewFace(); polyhedron.addPointToCurrentFace(bottomPoints[i]); polyhedron.addPointToCurrentFace(bottomPoints[(i + 1) % l]); polyhedron.addPointToCurrentFace(getTopPoint((i + 1) % l)); polyhedron.addPointToCurrentFace(getTopPoint(i)); polyhedron.endCurrentFace(); GeoPolygon3D polygon = polyhedron.createPolygon(i + 1); // i+1 // due // to // top // face if (polyhedron.allLabelsAreSet()) { polygon.setLabel(null); } outputPolygonsSide.addOutput(polygon, false); outputSegmentsSide.addOutput( (GeoSegment3D) polygon.getSegments()[3], false); outputSegmentsTop.addOutput( (GeoSegment3D) polygon.getSegments()[2], false); } if (getPolyhedron().allLabelsAreSet()) { outputSegmentsSide.setLabels(null); outputSegmentsTop.setLabels(null); outputPolygonsSide.setLabels(null); } refreshOutput(); } else if (newBottomPointsLength < nOld) { for (int i = newBottomPointsLength; i < bottomPointsLength; i++) { outputPoints.getElement(i - getShift()).setUndefined(); } updateOutputPoints(); // update top side outputSegmentsTop.getElement(newBottomPointsLength - 1) .modifyInputPoints(getTopPoint(newBottomPointsLength - 1), getTopPoint()); GeoPolygon polygon = getTopFace(); GeoPointND[] p = new GeoPointND[newBottomPointsLength]; p[0] = getTopPoint(); for (int i = 0; i < newBottomPointsLength - 1; i++) { p[1 + i] = getTopPoint(i + 1); } polygon.modifyInputPoints(p); polygon.setSegments(outputSegmentsTop .getOutput(new GeoSegment3D[newBottomPointsLength])); polygon.calcArea(); // update last side polygon = outputPolygonsSide.getElement(newBottomPointsLength - 1); p = new GeoPointND[4]; p[0] = bottomPoints[newBottomPointsLength - 1]; p[1] = bottomPoints[0]; p[2] = getTopPoint(); p[3] = getTopPoint(newBottomPointsLength - 1); polygon.setPoints(p, null, false); // don't create segments GeoSegmentND[] s = new GeoSegmentND[4]; s[0] = getBottom().getSegments()[newBottomPointsLength - 1]; s[1] = outputSegmentsSide.getElement(0); s[2] = outputSegmentsTop.getElement(newBottomPointsLength - 1); s[3] = outputSegmentsSide.getElement(newBottomPointsLength - 1); polygon.setSegments(s); polygon.calcArea(); } else { updateOutputPoints(); } if (bottomPointsLength < newBottomPointsLength) { // update top side updateTop(newBottomPointsLength); // update last sides for (int i = bottomPointsLength; i < newBottomPointsLength; i++) { updateSide(i, bottomPoints, bottomSegments); } } bottomPointsLength = newBottomPointsLength; } private void updateTop(int n) { GeoPolygon polygon = getTopFace(); GeoPointND[] p = new GeoPointND[n]; p[0] = getTopPoint(); for (int i = 0; i < n - 1; i++) { p[1 + i] = getTopPoint(i + 1); } polygon.modifyInputPoints(p); polygon.setSegments(outputSegmentsTop.getOutput(new GeoSegment3D[n])); polygon.calcArea(); } private void updateSide(int index, GeoPointND[] bottomPoints, GeoSegmentND[] bottomSegments) { outputSegmentsTop.getElement(index - 1) .modifyInputPoints(getTopPoint(index - 1), getTopPoint(index)); GeoPolygon polygon = outputPolygonsSide.getElement(index - 1); GeoPointND[] p = new GeoPointND[4]; p[0] = bottomPoints[index - 1]; p[1] = bottomPoints[index]; p[2] = getTopPoint(index); p[3] = getTopPoint(index - 1); polygon.modifyInputPoints(p); // don't create segments GeoSegmentND[] s = new GeoSegmentND[4]; s[0] = bottomSegments[index - 1]; s[1] = outputSegmentsSide.getElement(index); s[2] = outputSegmentsTop.getElement(index - 1); s[3] = outputSegmentsSide.getElement(index - 1); polygon.setSegments(s); polygon.calcArea(); } protected void removeBottomPoints(int length) { for (int i = bottomPointsLength; i < bottomPointsLength + length; i++) { outputPoints.getElement(i - getShift()).setUndefined(); } } // /////////////////////////////////////////// // END OF THE CONSTRUCTION // ////////////////////////////////////////// private Coords uptranslation; @Override protected void updateOutputPoints() { // Application.printStacktrace(""); if (height == null) { uptranslation = getTopPoint().getInhomCoordsInD3() .sub(getBottomPoints()[0].getInhomCoordsInD3()); } else { uptranslation = bottom.getMainDirection().normalized() .mul(height.getDouble()); } GeoPointND[] bottomPoints = getBottomPoints(); // translation from bottom to top if (bottomPoints != null) { for (int i = 0; i < outputPoints.size() && i + getShift() < bottomPoints.length; i++) { outputPoints.getElement(i) .setCoords(bottomPoints[i + getShift()] .getInhomCoordsInD3().add(uptranslation), true); } } } @Override public void compute() { if (!preCompute()) { for (int i = 0; i < bottomPointsLength - getShift(); i++) { outputPoints.getElement(i).setUndefined(); } // bottomPointsLength=getBottom().getPointsLength(); return; } if (!bottomAsInput) { updateOutputPoints(); } } @Override public Commands getClassName() { return Commands.Prism; } @Override protected void updateOutput() { // Application.debug("ici"); Collection<GeoPolygon3D> faces = polyhedron.getFacesCollection(); int top = faces.size(); int step = 1; for (GeoPolygon polygon : faces) { GeoSegmentND[] segments = polygon.getSegments(); if (step == 1 && !bottomAsInput) {// bottom outputPolygonsBottom.addOutput((GeoPolygon3D) polygon, false); for (int i = 0; i < segments.length; i++) { outputSegmentsBottom.addOutput((GeoSegment3D) segments[i], false); } step++; continue; } else if (step == top) {// top outputPolygonsTop.addOutput((GeoPolygon3D) polygon, false); for (int i = 0; i < segments.length; i++) { outputSegmentsTop.addOutput((GeoSegment3D) segments[i], false); } step++; continue; } // sides outputPolygonsSide.addOutput((GeoPolygon3D) polygon, false); outputSegmentsSide .addOutput((GeoSegment3D) polygon.getSegments()[3], false); step++; } refreshOutput(); } @Override protected int getSideLengthFromLabelsLength(int length) { if (bottomAsInput) { return (length + getShift() - 2) / 4; } return (length + getShift() - 3) / 5; } @Override protected void updateVolume(double height) { super.updateVolume(height); getPolyhedron().setVolume(getBottom().getArea() * height); } @Override protected void updateDependentGeos() { super.updateDependentGeos(); outputPoints.update(); // force update of segments and polygons when e.g. in a list if (!getPolyhedron().allLabelsAreSet()) { outputSegmentsBottom.updateParentAlgorithm(); outputSegmentsSide.updateParentAlgorithm(); outputSegmentsTop.updateParentAlgorithm(); outputPolygonsBottom.updateParentAlgorithm(); outputPolygonsSide.updateParentAlgorithm(); outputPolygonsTop.updateParentAlgorithm(); } } @Override protected void updateOutputSegmentsAndPolygonsParentAlgorithms() { outputSegmentsBottom.updateParentAlgorithm(); outputSegmentsSide.updateParentAlgorithm(); outputSegmentsTop.updateParentAlgorithm(); outputPolygonsBottom.updateParentAlgorithm(); outputPolygonsSide.updateParentAlgorithm(); outputPolygonsTop.updateParentAlgorithm(); } }