package org.geogebra.common.geogebra3D.util; import java.util.ArrayList; import java.util.Iterator; import java.util.TreeSet; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoCircle3DThreePoints; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoConicFivePoints3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoEllipseHyperbolaFociPoint3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoJoinPoints3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoPolyLine3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoPolygon3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoPolygonRegular3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoQuadricLimitedConicHeightCone; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoQuadricLimitedConicHeightCylinder; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoQuadricLimitedPointPointRadiusCone; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoQuadricLimitedPointPointRadiusCylinder; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoVector3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPolyLine3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPolygon3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPolyhedron; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPolyhedronNet; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoQuadric3DLimited; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoSegment3D; import org.geogebra.common.kernel.algos.ConstructionElement; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoPolygon; import org.geogebra.common.kernel.kernelND.GeoElementND; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.util.CopyPaste; /** * 3D extension of copy paste utility */ public class CopyPaste3D extends CopyPaste { @Override protected void addSubGeos(ArrayList<ConstructionElement> geos) { // even in 3D, there may be a lot of 2D objects super.addSubGeos(geos); GeoElement geo; for (int i = geos.size() - 1; i >= 0; i--) { geo = (GeoElement) geos.get(i); if (geo.getParentAlgorithm() == null) { continue; } if (geo.isGeoElement3D()) { // TODO: implementation! if (geo.isGeoPolyhedron()) { TreeSet<GeoElement> ancestors = getAllIndependentPredecessors( geo); // there are many kinds of algorithm to create a // GeoPolyhedron, // but the essence is that its faces, edges and points // should // be shown in any case when they have common parent algo // inputs Iterator<GeoPolygon3D> polysit = ((GeoPolyhedron) geo) .getPolygons().iterator(); GeoPolygon3D psnext; while (polysit.hasNext()) { psnext = polysit.next(); if (!geos.contains(psnext) && predecessorsCovered(psnext, ancestors)) { geos.add(psnext); } } Iterator<GeoPolygon> ps2 = ((GeoPolyhedron) geo) .getPolygonsLinked().iterator(); GeoPolygon ps2n; while (ps2.hasNext()) { ps2n = ps2.next(); if (!geos.contains(ps2n) && predecessorsCovered(ps2n, ancestors)) { geos.add(ps2n); } } GeoSegment3D[] segm = ((GeoPolyhedron) geo).getSegments3D(); for (int j = 0; j < segm.length; j++) { if (!geos.contains(segm[j]) && predecessorsCovered(segm[j], ancestors)) { geos.add(segm[j]); GeoPointND[] pspoints2 = { segm[j].getStartPoint(), segm[j].getEndPoint() }; for (int k = 0; k < pspoints2.length; k++) { if (!geos.contains(pspoints2[k]) && predecessorsCovered(pspoints2[k], ancestors)) { geos.add((GeoElement) (pspoints2[k])); } } } } } else if (geo instanceof GeoPolyhedronNet) { TreeSet<GeoElement> ancestors = getAllIndependentPredecessors( geo); Iterator<GeoPolygon3D> polysit = ((GeoPolyhedronNet) geo) .getPolygons().iterator(); GeoPolygon3D psnext; while (polysit.hasNext()) { psnext = polysit.next(); if (!geos.contains(psnext) && predecessorsCovered(psnext, ancestors)) { geos.add(psnext); } } Iterator<GeoPolygon> ps2 = ((GeoPolyhedronNet) geo) .getPolygonsLinked().iterator(); GeoPolygon ps2n; while (ps2.hasNext()) { ps2n = ps2.next(); if (!geos.contains(ps2n) && predecessorsCovered(ps2n, ancestors)) { geos.add(ps2n); } } GeoSegment3D[] segm = ((GeoPolyhedronNet) geo) .getSegments3D(); for (int j = 0; j < segm.length; j++) { if (!geos.contains(segm[j]) && predecessorsCovered(segm[j], ancestors)) { geos.add(segm[j]); GeoPointND[] pspoints2 = { segm[j].getStartPoint(), segm[j].getEndPoint() }; for (int k = 0; k < pspoints2.length; k++) { if (!geos.contains(pspoints2[k]) && predecessorsCovered(pspoints2[k], ancestors)) { geos.add((GeoElement) (pspoints2[k])); } } } } } else if (geo instanceof GeoQuadric3DLimited) { if (geo.getParentAlgorithm() instanceof AlgoQuadricLimitedPointPointRadiusCone || geo.getParentAlgorithm() instanceof AlgoQuadricLimitedPointPointRadiusCylinder || geo.getParentAlgorithm() instanceof AlgoQuadricLimitedConicHeightCone || geo.getParentAlgorithm() instanceof AlgoQuadricLimitedConicHeightCylinder) { TreeSet<GeoElement> ancestors = getAllIndependentPredecessors( geo); GeoElement[] pgeos = geo.getParentAlgorithm() .getInput(); for (int j = 0; j < pgeos.length; j++) { if (!geos.contains(pgeos[j]) && predecessorsCovered( pgeos[j], ancestors)) { geos.add(pgeos[j]); } } pgeos = geo.getParentAlgorithm().getOutput(); for (int j = 0; j < pgeos.length; j++) { if (!geos.contains(pgeos[j]) && predecessorsCovered( pgeos[j], ancestors)) { geos.add(pgeos[j]); } } } } else if ((geo.isGeoLine() && geo.getParentAlgorithm() instanceof AlgoJoinPoints3D) || (geo.isGeoVector() && geo .getParentAlgorithm() instanceof AlgoVector3D)) { if (!geos .contains(geo.getParentAlgorithm().getInput()[0])) { geos.add(geo.getParentAlgorithm().getInput()[0]); } if (!geos .contains(geo.getParentAlgorithm().getInput()[1])) { geos.add(geo.getParentAlgorithm().getInput()[1]); } } else if (geo instanceof GeoPolygon3D) { if (geo.getParentAlgorithm() instanceof AlgoPolygon3D) { GeoPointND[] points = ((AlgoPolygon3D) (geo .getParentAlgorithm())).getPoints(); for (int j = 0; j < points.length; j++) { if (!geos.contains(points[j])) { geos.add((GeoElement) points[j]); } } GeoElement[] ogeos = ((AlgoPolygon3D) (geo .getParentAlgorithm())).getOutput(); for (int j = 0; j < ogeos.length; j++) { if (!geos.contains(ogeos[j]) && ogeos[j].isGeoSegment()) { geos.add(ogeos[j]); } } } else if (geo .getParentAlgorithm() instanceof AlgoPolygonRegular3D) { GeoElement[] pgeos = ((geo.getParentAlgorithm())) .getInput(); for (int j = 0; j < pgeos.length; j++) { if (!geos.contains(pgeos[j]) && pgeos[j].isGeoPoint() && j < 3) { geos.add(pgeos[j]); } } GeoElement[] ogeos = ((geo.getParentAlgorithm())) .getOutput(); for (int j = 0; j < ogeos.length; j++) { if (!geos.contains(ogeos[j]) && (ogeos[j].isGeoSegment() || ogeos[j].isGeoPoint())) { geos.add(ogeos[j]); } } } } else if (geo instanceof GeoPolyLine3D) { if (geo.getParentAlgorithm() instanceof AlgoPolyLine3D) { GeoPointND[] pgeos = ((AlgoPolyLine3D) (geo .getParentAlgorithm())).getPointsND(); for (int j = 0; j < pgeos.length; j++) { if (!geos.contains(pgeos[j])) { geos.add((GeoElement) pgeos[j]); } } } } else if (geo.isGeoConic()) { // different, harder! /* * if (geo.getParentAlgorithm() instanceof * AlgoCircleTwoPoints) { GeoElement[] pgeos = * geo.getParentAlgorithm().getInput(); if * (!geos.contains(pgeos[0])) geos.add(pgeos[0]); if * (!geos.contains(pgeos[1])) geos.add(pgeos[1]); } else */if (geo .getParentAlgorithm() instanceof AlgoCircle3DThreePoints || geo.getParentAlgorithm() instanceof AlgoEllipseHyperbolaFociPoint3D) { GeoElement[] pgeos = geo.getParentAlgorithm() .getInput(); if (!geos.contains(pgeos[0])) { geos.add(pgeos[0]); } if (!geos.contains(pgeos[1])) { geos.add(pgeos[1]); } if (!geos.contains(pgeos[2])) { geos.add(pgeos[2]); } } else if (geo .getParentAlgorithm() instanceof AlgoConicFivePoints3D) { GeoElement[] pgeos = geo.getParentAlgorithm() .getInput(); for (int j = 0; j < pgeos.length; j++) { if (!geos.contains(pgeos[j])) { geos.add(pgeos[j]); } } } /* * else if (geo.getParentAlgorithm() instanceof * AlgoCirclePointRadius) { GeoElement[] pgeos = * geo.getParentAlgorithm().getInput(); if * (!geos.contains(pgeos[0])) geos.add(pgeos[0]); } */ } } } } private static TreeSet<GeoElement> getAllIndependentPredecessors( GeoElement geo) { TreeSet<GeoElement> ancestors = new TreeSet<GeoElement>(); geo.addPredecessorsToSet(ancestors, true); return ancestors; } private static boolean predecessorsCovered(GeoElementND ps2n, TreeSet<GeoElement> ancestors) { return ancestors.containsAll( getAllIndependentPredecessors(ps2n.toGeoElement())); } }