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 Pyramid * */ public class AlgoPolyhedronPointsPyramid extends AlgoPolyhedronPoints { /** * creates a pyramid regarding vertices * * @param c * construction * @param labels * labels * @param points * vertices */ public AlgoPolyhedronPointsPyramid(Construction c, String[] labels, GeoPointND[] points) { super(c, labels, points); } /** * * @param c * construction * @param labels * labels * @param polygon * bottom face * @param point * top vertex */ public AlgoPolyhedronPointsPyramid(Construction c, String[] labels, GeoPolygon polygon, GeoPointND point) { super(c, labels, polygon, point); } /** * pyramid with top point over center of bottom face * * @param c * @param labels * @param polygon * @param height */ public AlgoPolyhedronPointsPyramid(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 // ///////// points = new GeoPointND[bottomPointsLength + 1]; for (int i = 0; i < bottomPointsLength; i++) { points[i] = bottomPoints[i]; } points[bottomPointsLength] = topPoint; // ///////// // faces // ///////// // bottom has already been set // sides of the pyramid for (int i = 0; i < bottomPointsLength; i++) { polyhedron.startNewFace(); polyhedron.addPointToCurrentFace(bottomPoints[i]); polyhedron.addPointToCurrentFace( bottomPoints[(i + 1) % (bottomPointsLength)]); polyhedron.addPointToCurrentFace(topPoint);// apex polyhedron.endCurrentFace(); } polyhedron.setType(GeoPolyhedron.TYPE_PYRAMID); } @Override protected void updateOutput(int newBottomPointsLength) { updateOutputPoints(); GeoPointND[] bottomPoints = getBottomPoints(); GeoSegmentND[] bottomSegments = getBottom().getSegments(); // current length int nOld = outputSegmentsSide.size(); /* * Log.debug("nOld:"+nOld +"\nbottomPointsLength:"+bottomPointsLength * +"\nnewBottomPointsLength:"+newBottomPointsLength * +"\noutputSegmentsSide:"+outputSegmentsSide.size()); */ if (newBottomPointsLength > nOld) { // update segments linked polyhedron.updateSegmentsLinked(); // create new sides for (int i = nOld; i < newBottomPointsLength; i++) { // Log.debug("bottomPoints["+i+"]="+bottomPoints[i]); // Log.debug("bottomPoints["+((i+1)%newBottomPointsLength)+"]="+bottomPoints[(i+1)%newBottomPointsLength]); polyhedron.startNewFace(); polyhedron.addPointToCurrentFace(bottomPoints[i]); polyhedron.addPointToCurrentFace( bottomPoints[(i + 1) % newBottomPointsLength]); polyhedron.addPointToCurrentFace(getTopPoint()); polyhedron.endCurrentFace(); GeoPolygon3D polygon = polyhedron.createPolygon(i); outputPolygonsSide.addOutput(polygon, false); outputSegmentsSide.addOutput( (GeoSegment3D) polygon.getSegments()[2], false); } if (getPolyhedron().allLabelsAreSet()) { outputSegmentsSide.setLabels(null); outputPolygonsSide.setLabels(null); } refreshOutput(); } else if (newBottomPointsLength < nOld) { // update last side GeoPolygon polygon = outputPolygonsSide .getElement(newBottomPointsLength - 1); GeoPointND[] p = new GeoPointND[3]; p[0] = bottomPoints[newBottomPointsLength - 1]; p[1] = bottomPoints[0]; p[2] = getTopPoint(); polygon.modifyInputPoints(p); GeoSegmentND[] s = new GeoSegmentND[3]; s[0] = getBottom().getSegments()[newBottomPointsLength - 1]; s[1] = outputSegmentsSide.getElement(newBottomPointsLength - 1); s[2] = outputSegmentsSide.getElement(0); polygon.setSegments(s); polygon.calcArea(); } /* * Application.debug("nOld:"+nOld * +"\nbottomPointsLength:"+bottomPointsLength * +"\nnewBottomPointsLength:"+newBottomPointsLength * +"\noutputSegmentsSide:"+outputSegmentsSide.size()); */ if (bottomPointsLength < newBottomPointsLength) { // update last sides for (int i = bottomPointsLength; i < newBottomPointsLength; i++) { updateSide(i, bottomPoints, bottomSegments); } } bottomPointsLength = newBottomPointsLength; } private void updateSide(int index, GeoPointND[] bottomPoints, GeoSegmentND[] bottomSegments) { GeoPolygon polygon = outputPolygonsSide.getElement(index - 1); GeoPointND[] p = new GeoPointND[3]; p[0] = bottomPoints[index - 1]; p[1] = bottomPoints[index]; p[2] = getTopPoint(); polygon.modifyInputPoints(p); GeoSegmentND[] s = new GeoSegmentND[3]; s[0] = bottomSegments[index - 1]; s[1] = outputSegmentsSide.getElement(index); s[2] = outputSegmentsSide.getElement(index - 1); polygon.setSegments(s); polygon.calcArea(); } // /////////////////////////////////////////// // END OF THE CONSTRUCTION // ////////////////////////////////////////// private Coords bottomCenter; @Override protected void initCoords() { bottomCenter = new Coords(4); } @Override protected void updateOutputPoints() { GeoPointND[] bottomPoints = getBottomPoints(); if (bottomPoints == null) { return; } Coords bottomCenter1 = new Coords(4); // interiorPoint.set(0); for (int i = 0; i < bottomPoints.length; i++) { bottomCenter1 = bottomCenter1 .add(bottomPoints[i].getInhomCoordsInD3()); } bottomCenter = bottomCenter1.mul((double) 1 / (bottomPoints.length)); if (height != null) { Coords v = bottom.getMainDirection().normalized() .mul(height.getDouble()); getTopPoint().setCoords(bottomCenter.add(v), true); } } @Override public void compute() { if (!preCompute()) { if (height != null) { ((GeoPoint3D) getTopPoint()).setUndefined(); } return; } } @Override public Commands getClassName() { return Commands.Pyramid; } @Override protected void updateOutput() { // Application.printStacktrace(""); Collection<GeoPolygon3D> faces = polyhedron.getFacesCollection(); // Application.debug(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++; } else {// sides outputPolygonsSide.addOutput((GeoPolygon3D) polygon, false); outputSegmentsSide.addOutput( (GeoSegment3D) polygon.getSegments()[2], false); step++; // Application.debug(outputSegmentsSide.size()); } } refreshOutput(); } @Override protected int getSideLengthFromLabelsLength(int length) { // Application.debug("bottomAsInput="+bottomAsInput+",shift="+getShift()); if (bottomAsInput) { return (length + getShift() - 2) / 2; } return (length + getShift() - 3) / 3; } @Override protected void updateVolume(double height) { super.updateVolume(height); getPolyhedron().setVolume(getBottom().getArea() * height / 3); } @Override protected void updateDependentGeos() { super.updateDependentGeos(); if (height != null) { getTopPoint().update(); } // force update of segments and polygons when e.g. in a list if (!getPolyhedron().allLabelsAreSet()) { outputSegmentsBottom.updateParentAlgorithm(); outputSegmentsSide.updateParentAlgorithm(); outputPolygonsBottom.updateParentAlgorithm(); outputPolygonsSide.updateParentAlgorithm(); } } @Override protected void updateOutputSegmentsAndPolygonsParentAlgorithms() { outputSegmentsBottom.updateParentAlgorithm(); outputSegmentsSide.updateParentAlgorithm(); outputPolygonsBottom.updateParentAlgorithm(); outputPolygonsSide.updateParentAlgorithm(); } }