/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.kernel.algos; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoConicPart; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.kernel.kernelND.GeoConicND; import org.geogebra.common.kernel.kernelND.GeoConicNDConstants; /** * Algorithm to compute the circumference of a * {@link org.geogebra.common.kernel.geos.GeoConic GeoConic}. * * @author Philipp Weissenbacher (materthron@users.sourceforge.net) * @author Markus Hohenwarter */ public class AlgoCircumferenceConic extends AlgoElement { // Take a conic as input private GeoConicND conic; // Output is a GeoNumeric (= a number) private GeoNumeric circum; // Helper to calculate circumference for ellipse public AlgoCircumferenceConic(Construction cons, String label, GeoConicND conic) { this(cons, conic); circum.setLabel(label); } AlgoCircumferenceConic(Construction cons, GeoConicND conic) { super(cons); this.conic = conic; circum = new GeoNumeric(cons); setInputOutput(); compute(); } @Override public Commands getClassName() { return Commands.Circumference; } @Override protected void setInputOutput() { input = new GeoElement[1]; input[0] = conic; super.setOutputLength(1); super.setOutput(0, circum); setDependencies(); } /** * Compute circumference. In order to do so we have to distinguishe between * the following cases: * * <pre> * a) conic is a circle * b) conic is an ellipse * </pre> * * For all other cases circumference is undefined. */ @Override public final void compute() { if (!conic.isDefined()) { circum.setUndefined(); } // conic type int type = conic.getType(); // circumference of sector if (conic.isGeoConicPart()) { GeoConicPart conicPart = (GeoConicPart) conic; int partType = conicPart.getConicPartType(); if (type == GeoConicNDConstants.CONIC_CIRCLE && partType == GeoConicNDConstants.CONIC_PART_SECTOR) { /* * value of sector is area: area = r*r * paramExtent / 2; * arclength = r * paramExtent; arclength = area * 2/r; */ double area = conicPart.getValue(); double r = conic.getHalfAxis(0); double arclength = area * 2.0 / r; // circumference of sector circum.setValue(arclength + 2 * r); } else if (type == GeoConicNDConstants.CONIC_CIRCLE && partType == GeoConicNDConstants.CONIC_PART_ARC) { // value of arc is curved length double arclength = conicPart.getValue(); double r = conic.getHalfAxis(0); double angle = conicPart.getParameterExtent(); // return circumference of **segment** // ie curved + straight circum.setValue(arclength + 2.0 * r * Math.sin(angle / 2)); } else { // circumference of ellipse sector is undefined // note: circumference of ellipse sector is simply not // implemented yet circum.setUndefined(); } return; } // standard case: conic switch (type) { case GeoConicNDConstants.CONIC_CIRCLE: // r is length of one of the half axes double r = conic.getHalfAxis(0); circum.setValue(2 * r * Math.PI); break; case GeoConicNDConstants.CONIC_ELLIPSE: // new, more accurate method // https://jira.geogebra.org/browse/GGB-692 circum.setValue(conic.getEllipseCircumference()); break; default: circum.setUndefined(); } } /** * Get the GeoConics's circumference. * * @return circumference */ public GeoNumeric getCircumference() { return circum; } }