// replace every x in tree by (x - vx) // i.e. replace fVar with (fvar - vx) private void translateX(ExpressionNode en, double vx, int varNo) { ExpressionValue left = en.getLeft(); ExpressionValue right = en.getRight(); // left tree if (left == fVars[varNo]) { try { // is there a constant number to the right? MyDouble num = (MyDouble) right; double temp; switch (en.getOperation()) { case ExpressionNode.PLUS: temp = num.getDouble() - vx; if (Kernel.isZero(temp)) { expression = expression.replaceAndWrap(en, fVars[varNo]); } else if (temp < 0) { en.setOperation(ExpressionNode.MINUS); num.set(-temp); } else { num.set(temp); } return; case ExpressionNode.MINUS: temp = num.getDouble() + vx; if (Kernel.isZero(temp)) { expression = expression.replaceAndWrap(en, fVars[varNo]); } else if (temp < 0) { en.setOperation(ExpressionNode.PLUS); num.set(-temp); } else { num.set(temp); } return; default: en.setLeft(shiftXnode(vx, varNo)); } } catch (Exception e) { en.setLeft(shiftXnode(vx, varNo)); } } else if (left instanceof ExpressionNode) { translateX((ExpressionNode) left, vx, varNo); } // right tree if (right == fVars[varNo]) { en.setRight(shiftXnode(vx, varNo)); } else if (right instanceof ExpressionNode) { translateX((ExpressionNode) right, vx, varNo); } }
public GgbVector getCartesianEquationVector(GgbMatrix m) { GgbVector origin = getCoordSys().getOrigin(); GgbVector direction = getCoordSys().getVx(); // TODO generalize it to other planes than xOy // if lines is not in the plane, return null if (!Kernel.isZero(origin.getZ()) || !Kernel.isZero(direction.getZ())) return null; double x = -direction.getY(); double y = direction.getX(); double z = -x * origin.getX() - y * origin.getY(); return new GgbVector(x, y, z); }
public void translate(double vx, double vy) { // translate x if (!Kernel.isZero(vx)) { translateX(expression, vx, 0); } if (!Kernel.isZero(vy)) { translateX(expression, vy, 1); } // make sure that expression object is changed! // this is needed to know that the expression has changed if (expression.isLeaf() && expression.getLeft().isExpressionNode()) { expression = new ExpressionNode((ExpressionNode) expression.getLeft()); } else { expression = new ExpressionNode(expression); } }
public final void update() { isVisible = geo.isEuclidianVisible(); if (!isVisible) return; labelVisible = geo.isLabelVisible(); updateStrokes(geo); Coords A = view.getCoordsForView(s.getStartInhomCoords()); Coords B = view.getCoordsForView(s.getEndInhomCoords()); // check if in view if (!Kernel.isZero(A.getZ()) || !Kernel.isZero(B.getZ())) { isVisible = false; return; } /* if (s.getEndPoint().getLabel().equals("S3'")) Application.debug("start=\n"+s.getStartInhomCoords()+"\nA=\n"+A); */ coordsA[0] = A.getX(); coordsA[1] = A.getY(); coordsB[0] = B.getX(); coordsB[1] = B.getY(); boolean onscreenA = view.toScreenCoords(coordsA); boolean onscreenB = view.toScreenCoords(coordsB); if (line == null) line = new Line2D.Double(); if (onscreenA && onscreenB) { // A and B on screen line.setLine(coordsA[0], coordsA[1], coordsB[0], coordsB[1]); } else { // A or B off screen // clip at screen, that's important for huge coordinates Point2D.Double[] clippedPoints = ClipLine.getClipped( coordsA[0], coordsA[1], coordsB[0], coordsB[1], -EuclidianView.CLIP_DISTANCE, view.width + EuclidianView.CLIP_DISTANCE, -EuclidianView.CLIP_DISTANCE, view.height + EuclidianView.CLIP_DISTANCE); if (clippedPoints == null) { isVisible = false; } else { line.setLine( clippedPoints[0].x, clippedPoints[0].y, clippedPoints[1].x, clippedPoints[1].y); } } // draw trace if (s.getTrace()) { isTracing = true; Graphics2D g2 = view.getBackgroundGraphics(); if (g2 != null) drawTrace(g2); } else { if (isTracing) { isTracing = false; view.updateBackground(); } } // if no label and no decoration then we're done if (!labelVisible && geo.decorationType == GeoElement.DECORATION_NONE) return; // calc midpoint (midX, midY) and perpendicular vector (nx, ny) double midX = (coordsA[0] + coordsB[0]) / 2.0; double midY = (coordsA[1] + coordsB[1]) / 2.0; double nx = coordsA[1] - coordsB[1]; double ny = coordsB[0] - coordsA[0]; double nLength = GeoVec2D.length(nx, ny); // label position // use unit perpendicular vector to move away from line if (labelVisible) { labelDesc = geo.getLabelDescription(); if (nLength > 0.0) { xLabel = (int) (midX + nx * 16 / nLength); yLabel = (int) (midY + ny * 16 / nLength); } else { xLabel = (int) midX; yLabel = (int) (midY + 16); } addLabelOffset(); } // update decoration // added by Lo�c and Markus BEGIN, if (geo.decorationType != GeoElement.DECORATION_NONE && nLength > 0) { if (decoTicks == null) { // only create these object when they are really needed decoTicks = new Line2D.Double[6]; // Michael Borcherds 20071006 changed from 3 to 6 for (int i = 0; i < decoTicks.length; i++) decoTicks[i] = new Line2D.Double(); } // tick spacing and length. double tickSpacing = 2.5 + geo.lineThickness / 2d; double tickLength = tickSpacing + 1; // Michael Borcherds 20071006 start double arrowlength = 1.5; // Michael Borcherds 20071006 end double vx, vy, factor; switch (geo.decorationType) { case GeoElement.DECORATION_SEGMENT_ONE_TICK: // use perpendicular vector to set tick factor = tickLength / nLength; nx *= factor; ny *= factor; decoTicks[0].setLine(midX - nx, midY - ny, midX + nx, midY + ny); break; case GeoElement.DECORATION_SEGMENT_TWO_TICKS: // vector (vx, vy) to get 2 points around midpoint factor = tickSpacing / (2 * nLength); vx = -ny * factor; vy = nx * factor; // use perpendicular vector to set ticks factor = tickLength / nLength; nx *= factor; ny *= factor; decoTicks[0].setLine(midX + vx - nx, midY + vy - ny, midX + vx + nx, midY + vy + ny); decoTicks[1].setLine(midX - vx - nx, midY - vy - ny, midX - vx + nx, midY - vy + ny); break; case GeoElement.DECORATION_SEGMENT_THREE_TICKS: // vector (vx, vy) to get 2 points around midpoint factor = tickSpacing / nLength; vx = -ny * factor; vy = nx * factor; // use perpendicular vector to set ticks factor = tickLength / nLength; nx *= factor; ny *= factor; decoTicks[0].setLine(midX + vx - nx, midY + vy - ny, midX + vx + nx, midY + vy + ny); decoTicks[1].setLine(midX - nx, midY - ny, midX + nx, midY + ny); decoTicks[2].setLine(midX - vx - nx, midY - vy - ny, midX - vx + nx, midY - vy + ny); break; // Michael Borcherds 20071006 start case GeoElement.DECORATION_SEGMENT_ONE_ARROW: // vector (vx, vy) to get 2 points around midpoint factor = tickSpacing / (1.5 * nLength); vx = -ny * factor; vy = nx * factor; // use perpendicular vector to set tick factor = tickLength / (1.5 * nLength); nx *= factor; ny *= factor; decoTicks[0].setLine( midX - arrowlength * vx, midY - arrowlength * vy, midX - arrowlength * vx + arrowlength * (nx + vx), midY - arrowlength * vy + arrowlength * (ny + vy)); decoTicks[1].setLine( midX - arrowlength * vx, midY - arrowlength * vy, midX - arrowlength * vx + arrowlength * (-nx + vx), midY - arrowlength * vy + arrowlength * (-ny + vy)); break; case GeoElement.DECORATION_SEGMENT_TWO_ARROWS: // vector (vx, vy) to get 2 points around midpoint factor = tickSpacing / (1.5 * nLength); vx = -ny * factor; vy = nx * factor; // use perpendicular vector to set ticks factor = tickLength / (1.5 * nLength); nx *= factor; ny *= factor; decoTicks[0].setLine( midX - 2 * arrowlength * vx, midY - 2 * arrowlength * vy, midX - 2 * arrowlength * vx + arrowlength * (nx + vx), midY - 2 * arrowlength * vy + arrowlength * (ny + vy)); decoTicks[1].setLine( midX - 2 * arrowlength * vx, midY - 2 * arrowlength * vy, midX - 2 * arrowlength * vx + arrowlength * (-nx + vx), midY - 2 * arrowlength * vy + arrowlength * (-ny + vy)); decoTicks[2].setLine( midX, midY, midX + arrowlength * (nx + vx), midY + arrowlength * (ny + vy)); decoTicks[3].setLine( midX, midY, midX + arrowlength * (-nx + vx), midY + arrowlength * (-ny + vy)); break; case GeoElement.DECORATION_SEGMENT_THREE_ARROWS: // vector (vx, vy) to get 2 points around midpoint factor = tickSpacing / (1.5 * nLength); vx = -ny * factor; vy = nx * factor; // use perpendicular vector to set ticks factor = tickLength / (1.5 * nLength); nx *= factor; ny *= factor; decoTicks[0].setLine( midX - arrowlength * vx, midY - arrowlength * vy, midX - arrowlength * vx + arrowlength * (nx + vx), midY - arrowlength * vy + arrowlength * (ny + vy)); decoTicks[1].setLine( midX - arrowlength * vx, midY - arrowlength * vy, midX - arrowlength * vx + arrowlength * (-nx + vx), midY - arrowlength * vy + arrowlength * (-ny + vy)); decoTicks[2].setLine( midX + arrowlength * vx, midY + arrowlength * vy, midX + arrowlength * vx + arrowlength * (nx + vx), midY + arrowlength * vy + arrowlength * (ny + vy)); decoTicks[3].setLine( midX + arrowlength * vx, midY + arrowlength * vy, midX + arrowlength * vx + arrowlength * (-nx + vx), midY + arrowlength * vy + arrowlength * (-ny + vy)); decoTicks[4].setLine( midX - 3 * arrowlength * vx, midY - 3 * arrowlength * vy, midX - 3 * arrowlength * vx + arrowlength * (nx + vx), midY - 3 * arrowlength * vy + arrowlength * (ny + vy)); decoTicks[5].setLine( midX - 3 * arrowlength * vx, midY - 3 * arrowlength * vy, midX - 3 * arrowlength * vx + arrowlength * (-nx + vx), midY - 3 * arrowlength * vy + arrowlength * (-ny + vy)); break; // Michael Borcherds 20071006 end } } }