AlgoTangentCurve(Construction cons, String label, GeoPoint P, GeoCurveCartesian f) { super(cons); this.P = P; this.f = f; tangent = new GeoLine(cons); // check if P is defined as a point of the curve's graph pointOnCurve = false; if (P.getParentAlgorithm() instanceof AlgoPointOnPath) { AlgoPointOnPath algo = (AlgoPointOnPath) P.getParentAlgorithm(); pointOnCurve = algo.getPath() == f; } if (pointOnCurve) T = P; else T = new GeoPoint(cons); tangent.setStartPoint(T); // First derivative of curve f AlgoDerivative algo = new AlgoDerivative(cons, f); this.df = (GeoCurveCartesian) algo.getDerivative(); cons.removeFromConstructionList(algo); setInputOutput(); // for AlgoElement compute(); tangent.setLabel(label); }
// calc axes protected final void compute() { // only parabola has directrix if (c.type == GeoConic.CONIC_PARABOLA) { // directrix has direction of second eigenvector // through point (b - p/2* eigenvec1) directrix.x = -eigenvec[1].y; directrix.y = eigenvec[1].x; double px = b.x - c.p / 2.0 * eigenvec[0].x; double py = b.y - c.p / 2.0 * eigenvec[0].y; directrix.z = -(directrix.x * px + directrix.y * py); P.setCoords(px, py, 1.0); } else directrix.setUndefined(); }
AlgoDirectrix(Construction cons, String label, GeoConic c) { super(cons); this.c = c; eigenvec = c.eigenvec; b = c.b; directrix = new GeoLine(cons); P = new GeoPoint(cons); directrix.setStartPoint(P); setInputOutput(); // for AlgoElement compute(); directrix.setLabel(label); }
public void setVisualStyle(GeoElement geo) { super.setVisualStyle(geo); if (geo.isGeoRay()) { GeoRay ray = (GeoRay) geo; allowOutlyingIntersections = ray.allowOutlyingIntersections; } }
/** * Creates a new ray using a geometric transform. * * @param type of transform (Kernel constant) */ public GeoElement[] createTransformedObject( int type, String label, GeoPoint Q, GeoLine l, GeoVector vec, NumberValue n) { AlgoElement algoParent = keepTypeOnGeometricTransform ? getParentAlgorithm() : null; // CREATE RAY if (algoParent instanceof AlgoJoinPointsRay) { // transform points AlgoJoinPointsRay algo = (AlgoJoinPointsRay) algoParent; GeoPoint[] points = {algo.getP(), algo.getQ()}; points = kernel.transformPoints(type, points, Q, l, vec, n); GeoElement ray = kernel.Ray(label, points[0], points[1]); ray.setVisualStyleForTransformations(this); GeoElement[] geos = {ray, points[0], points[1]}; return geos; } else if (algoParent instanceof AlgoRayPointVector) { // transform startpoint GeoPoint[] points = {getStartPoint()}; points = kernel.transformPoints(type, points, Q, l, vec, n); // get transformed line from this ray GeoLine transformedLine = kernel.getTransformedLine(type, this, Q, l, vec, n); cons.removeFromConstructionList(transformedLine.getParentAlgorithm()); // get direction of transformed line boolean oldSuppressLabelCreation = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); AlgoDirection algoDir = new AlgoDirection(cons, transformedLine); cons.removeFromConstructionList(algoDir); GeoVector direction = algoDir.getVector(); cons.setSuppressLabelCreation(oldSuppressLabelCreation); // ray through transformed point with direction of transformed line GeoElement ray = kernel.Ray(label, points[0], direction); ray.setVisualStyleForTransformations(this); GeoElement[] geos = {ray, points[0], direction}; return geos; } else { // create LINE GeoLine transformedLine = kernel.getTransformedLine(type, this, Q, l, vec, n); transformedLine.setLabel(label); GeoElement[] ret = {transformedLine}; return ret; } }
public void set(GeoElement geo) { super.set(geo); if (!geo.isGeoRay()) return; GeoRay ray = (GeoRay) geo; keepTypeOnGeometricTransform = ray.keepTypeOnGeometricTransform; startPoint.set(ray.startPoint); }
/* * Path interface */ public void pointChanged(GeoPoint P) { super.pointChanged(P); // ensure that the point doesn't get outside the ray // i.e. ensure 0 <= t <= 1 PathParameter pp = P.getPathParameter(); if (pp.t < 0.0) { P.x = startPoint.x; P.y = startPoint.y; P.z = startPoint.z; pp.t = 0.0; } }
protected final void compute() { if (!(f.isDefined() && P.isDefined())) { tangent.setUndefined(); return; } // first derivative if (df == null || !df.isDefined()) { tangent.setUndefined(); return; } // calc the tangent; double feval[] = new double[2]; double dfeval[] = new double[2]; double tvalue = f.getClosestParameter(P, f.getMinParameter()); f.evaluateCurve(tvalue, feval); df.evaluateCurve(tvalue, dfeval); tangent.setCoords(-dfeval[1], dfeval[0], feval[0] * dfeval[1] - dfeval[0] * feval[1]); if (!pointOnCurve) T.setCoords(feval[0], feval[1], 1.0); }
// compute circle through A, B, C protected void compute() { // A, B or C undefined if (!getA().isFinite() || !getB().isFinite() || !getC().isFinite()) { circle.setUndefined(); return; } // get inhomogenous coords of points ax = ((GeoPoint) getA()).inhomX; ay = ((GeoPoint) getA()).inhomY; bx = ((GeoPoint) getB()).inhomX; by = ((GeoPoint) getB()).inhomY; cx = ((GeoPoint) getC()).inhomX; cy = ((GeoPoint) getC()).inhomY; // A = B = C if (kernel.isEqual(ax, bx) && kernel.isEqual(ax, cx) && kernel.isEqual(ay, by) && kernel.isEqual(ay, cy)) { circle.setCircle((GeoPoint) getA(), 0.0); // single point return; } // calc vectors AB, AC, BC ABx = bx - ax; ABy = by - ay; ACx = cx - ax; ACy = cy - ay; BCx = cx - bx; BCy = cy - by; double lengthAB = GeoVec2D.length(ABx, ABy); double lengthAC = GeoVec2D.length(ACx, ACy); double lengthBC = GeoVec2D.length(BCx, BCy); // find the two bisectors with max intersection angle // i.e. maximum abs of determinant of directions // max( abs(det(AB, AC)), abs(det(AC, BC)), abs(det(AB, BC)) ) det[0] = Math.abs(ABx * ACy - ABy * ACx) / (lengthAB * lengthAC); // AB, AC det[1] = Math.abs(ACx * BCy - ACy * BCx) / (lengthAC * lengthBC); // AC, BC det[2] = Math.abs(ABx * BCy - ABy * BCx) / (lengthAB * lengthBC); // AB, BC // take ip[0] as init minimum and find minimum case maxDet = det[0]; casenr = 0; if (det[1] > maxDet) { casenr = 1; maxDet = det[1]; } if (det[2] > maxDet) { casenr = 2; maxDet = det[2]; } // A, B, C are collinear: set M to infinite point // in perpendicular direction of AB if (kernel.isZero(maxDet)) { center.setCoords(-ABy, ABx, 0.0d); circle.setCircle(center, (GeoPoint) getA()); } // standard case else { // intersect two line bisectors according to casenr switch (casenr) { case 0: // bisectors of AB, AC s0.x = ABx; s0.y = ABy; s0.z = -((ax + bx) * s0.x + (ay + by) * s0.y) / 2.0; s1.x = ACx; s1.y = ACy; s1.z = -((ax + cx) * s1.x + (ay + cy) * s1.y) / 2.0; break; case 1: // bisectors of AC, BC s1.x = ACx; s1.y = ACy; s1.z = -((ax + cx) * s1.x + (ay + cy) * s1.y) / 2.0; s0.x = BCx; s0.y = BCy; s0.z = -((bx + cx) * s0.x + (by + cy) * s0.y) / 2.0; break; case 2: // bisectors of AB, BC s0.x = ABx; s0.y = ABy; s0.z = -((ax + bx) * s0.x + (ay + by) * s0.y) / 2.0; s1.x = BCx; s1.y = BCy; s1.z = -((bx + cx) * s1.x + (by + cy) * s1.y) / 2.0; break; } // intersect line bisectors to get midpoint GeoVec3D.cross(s0, s1, center); circle.setCircle(center, center.distance(getA())); } }
/** Fills the list of default geos */ protected void createDefaultGeoElements() { defaultGeoElements = new HashMap<Integer, GeoElement>(); // free point GeoPoint freePoint = new GeoPoint(cons); // freePoint.setLocalVariableLabel(app.getPlain("Point") + strFree); freePoint.setPointSize(EuclidianView.DEFAULT_POINT_SIZE); freePoint.setPointStyle(EuclidianView.POINT_STYLE_DOT); freePoint.setLocalVariableLabel("Point" + strFree); freePoint.setObjColor(colPoint); freePoint.setPointSize(pointSize); defaultGeoElements.put(DEFAULT_POINT_FREE, freePoint); // dependent point GeoPoint depPoint = new GeoPoint(cons); // depPoint.setLocalVariableLabel(app.getPlain("Point") + strDependent); depPoint.setPointSize(EuclidianView.DEFAULT_POINT_SIZE); depPoint.setPointStyle(EuclidianView.POINT_STYLE_DOT); depPoint.setLocalVariableLabel("Point" + strDependent); depPoint.setObjColor(colDepPoint); depPoint.setPointSize(pointSize); defaultGeoElements.put(DEFAULT_POINT_DEPENDENT, depPoint); // point on path GeoPoint pathPoint = new GeoPoint(cons); // pathPoint.setLocalVariableLabel(app.getPlain("PointOn")); pathPoint.setPointSize(EuclidianView.DEFAULT_POINT_SIZE); pathPoint.setPointStyle(EuclidianView.POINT_STYLE_DOT); pathPoint.setLocalVariableLabel("PointOn"); pathPoint.setObjColor(colPathPoint); pathPoint.setPointSize(pointSize); defaultGeoElements.put(DEFAULT_POINT_ON_PATH, pathPoint); // point in region GeoPoint regionPoint = new GeoPoint(cons); // regionPoint.setLocalVariableLabel(app.getPlain("PointOn")); regionPoint.setPointSize(EuclidianView.DEFAULT_POINT_SIZE); regionPoint.setPointStyle(EuclidianView.POINT_STYLE_DOT); regionPoint.setLocalVariableLabel("PointInRegion"); regionPoint.setObjColor(colRegionPoint); defaultGeoElements.put(DEFAULT_POINT_IN_REGION, regionPoint); // complex number (handled like a point) GeoPoint complexPoint = new GeoPoint(cons); complexPoint.setPointSize(EuclidianView.DEFAULT_POINT_SIZE); complexPoint.setPointStyle(EuclidianView.POINT_STYLE_DOT); complexPoint.setLocalVariableLabel("PointOn"); complexPoint.setObjColor(colComplexPoint); complexPoint.setPointSize(pointSize); defaultGeoElements.put(DEFAULT_POINT_COMPLEX, complexPoint); // line GeoLine line = new GeoLine(cons); // line.setLocalVariableLabel(app.getPlain("Line")); line.setLocalVariableLabel("Line"); line.setObjColor(colLine); defaultGeoElements.put(DEFAULT_LINE, line); GeoFunctionNVar inequality = new GeoFunctionNVar(cons, null); // inequality.setLocalVariableLabel("Inequality"); inequality.setObjColor(colInequality); inequality.setAlphaValue(DEFAULT_INEQUALITY_ALPHA); defaultGeoElements.put(DEFAULT_INEQUALITY, inequality); GeoFunction inequality1var = new GeoFunction(cons); // inequality.setLocalVariableLabel("Inequality"); inequality1var.setObjColor(colInequality); inequality1var.setAlphaValue(DEFAULT_INEQUALITY_ALPHA); defaultGeoElements.put(DEFAULT_INEQUALITY_1VAR, inequality1var); // vector GeoVector vector = new GeoVector(cons); vector.setLocalVariableLabel("Vector"); vector.setObjColor(colLine); defaultGeoElements.put(DEFAULT_VECTOR, vector); // polygon GeoPolygon polygon = new GeoPolygon(cons, null); // polygon.setLocalVariableLabel(app.getPlain("Polygon")); polygon.setLocalVariableLabel("Polygon"); polygon.setObjColor(colPolygon); polygon.setAlphaValue(DEFAULT_POLYGON_ALPHA); defaultGeoElements.put(DEFAULT_POLYGON, polygon); // conic GeoConic conic = new GeoConic(cons); // conic.setLocalVariableLabel(app.getPlain("Conic")); conic.setLocalVariableLabel("Conic"); conic.setObjColor(colConic); defaultGeoElements.put(DEFAULT_CONIC, conic); // conic sector GeoConicPart conicSector = new GeoConicPart(cons, GeoConicPart.CONIC_PART_SECTOR); // conicSector.setLocalVariableLabel(app.getPlain("Sector")); conicSector.setLocalVariableLabel("Sector"); conicSector.setObjColor(colPolygon); conicSector.setAlphaValue(DEFAULT_POLYGON_ALPHA); defaultGeoElements.put(DEFAULT_CONIC_SECTOR, conicSector); // number GeoNumeric number = new GeoNumeric(cons); // number.setLocalVariableLabel(app.getPlain("Numeric")); number.setLocalVariableLabel("Numeric"); number.setSliderFixed(true); number.setLabelMode(GeoElement.LABEL_NAME_VALUE); /*we have to set min/max/increment/speed here because SetEuclideanVisible takes these from default geo*/ number.setIntervalMax(GeoNumeric.DEFAULT_SLIDER_MAX); number.setIntervalMin(GeoNumeric.DEFAULT_SLIDER_MIN); number.setAnimationStep(GeoNumeric.DEFAULT_SLIDER_INCREMENT); number.setAnimationSpeed(GeoNumeric.DEFAULT_SLIDER_SPEED); defaultGeoElements.put(DEFAULT_NUMBER, number); // angle GeoAngle angle = new GeoAngle(cons); // angle.setLocalVariableLabel(app.getPlain("Angle")); angle.setLocalVariableLabel("Angle"); angle.setSliderFixed(true); angle.setObjColor(colAngle); angle.setAlphaValue(DEFAULT_ANGLE_ALPHA); angle.setArcSize(angleSize); /*we have to set min/max/increment/speed here because SetEuclideanVisible takes these from default geo*/ angle.setIntervalMax(GeoAngle.DEFAULT_SLIDER_MAX); angle.setIntervalMin(GeoAngle.DEFAULT_SLIDER_MIN); angle.setAnimationStep(GeoAngle.DEFAULT_SLIDER_INCREMENT); angle.setAnimationSpeed(GeoAngle.DEFAULT_SLIDER_SPEED); defaultGeoElements.put(DEFAULT_ANGLE, angle); // function GeoFunction function = new GeoFunction(cons); // function.setLocalVariableLabel(app.getPlain("Function")); function.setLocalVariableLabel("Function"); function.setObjColor(colFunction); defaultGeoElements.put(DEFAULT_FUNCTION, function); // locus GeoLocus locus = new GeoLocus(cons); // locus.setLocalVariableLabel(app.getPlain("Locus")); locus.setLocalVariableLabel("Locus"); locus.setObjColor(colLocus); locus.setLabelVisible(false); defaultGeoElements.put(DEFAULT_LOCUS, locus); // text GeoText text = new GeoText(cons); // text.setLocalVariableLabel(app.getPlain("Text")); text.setLocalVariableLabel("Text"); defaultGeoElements.put(DEFAULT_TEXT, text); // image GeoImage img = new GeoImage(cons); // img.setLocalVariableLabel(app.getPlain("Image")); img.setLocalVariableLabel("Image"); defaultGeoElements.put(DEFAULT_IMAGE, img); // boolean GeoBoolean bool = new GeoBoolean(cons); // bool.setLocalVariableLabel(app.getPlain("Boolean")); bool.setLocalVariableLabel("Boolean"); defaultGeoElements.put(DEFAULT_BOOLEAN, bool); // list GeoList list = new GeoList(cons); // list.setLocalVariableLabel(app.getPlain("List")); list.setShowAllProperties(true); // show all properties in the defaults dialog list.setLocalVariableLabel("List"); list.setObjColor(colList); list.setAlphaValue(-1); // wait until we have an element in the list // then we will use the alphaValue of the first element in the list // see GeoList.setAlphaValue() and getAlphaValue() defaultGeoElements.put(DEFAULT_LIST, list); }