/*  This file is part of the source code for 3D-XplorMath-J, Version 1.0 (January 2008).
 *  Copyright (c) 2008 The 3D-XplorMath Consortium (http://3d-xplormath.org).
 *  This source code is released under a BSD License, which allows redistribution   
 *  in source and binary form, with or without modification, provided copyright
 *  and license information are included, and with no warranty or guarantee of
 *  any kind.  For details, see http://3d-xplormath.org/j/source/BSDLicense.txt
 */
 
 package vmm3d.planecurve.parametric;

import java.awt.BasicStroke;
import java.awt.Color;

import org.freehep.graphics2d.VectorGraphics;

import java.awt.Stroke;
import java.awt.geom.Line2D;

import vmm3d.core.Decoration;
import vmm3d.core.Exhibit;
import vmm3d.core.Transform;
import vmm3d.core.VMMSave;
import vmm3d.core.View;

/**
 * A decoration that appears as a red tangent line and a blue normal line
 * on a parametric plane curve at a specified value of t.  The length of
 * the lines is 40 pixels.  If the functions that define the curve or
 * their derivatives are undefined at t, or if the length of the tangent
 * vector is zero, then nothing is drawn.
 */
public class TangentAndNormalDecoration extends Decoration {

	private PlaneCurveParametric curve; //private PlaneCurveParametricInterface curve;
	@VMMSave private double t = Double.NaN;
	
	/**
	 * Creates a TangentAndNormalDecoration with no associated curve.  A curve can be
	 * set later with {@link #setCurve(PlaneCurveParametric)}, or it will be set
	 * implicitly when the decoration is drawn. 
	 */
	public TangentAndNormalDecoration() {
	}
	
	
	/**
	 * Returns the curve to which this decoration applies.
	 */
	public PlaneCurveParametric getCurve() {
		return curve;
	}
	
	/**
	 * Sets the curve to which this decoration applies.
	 */
	public void setCurve(PlaneCurveParametric c) {
		curve = c;
	}

	/**
	 * Change the value of t where the decoration appears.  This should
	 * be withing the range of t-values shown on the curve, although
	 * this is not checked.
	 */
	public void setT(double t) {
		this.t = t;
		fireDecorationChangeEvent();
	}
	
	/**
	 * Returns the t-value of the point (x(t),y(t)) where the decoration
	 * is drawn on the curve.  A value of Double.NaN means that the
	 * decoration is not drawn; this is the value when the decoration is
	 * first constructed.
	 */
	public double getT() {
		return t;
	}
	
	/**
	 * Set the t-value to be at one of the points that are used for
	 * drawing the curve. If the curve is null when this is called, it
	 * has no effect.
	 * @param tIndex An index into the array of t-values that the curve
	 * uses to generate the curve.  The index should be in the legal
	 * range; if not, nothing is drawn.  The range is from 0 to
	 * getCurve().getPointCount().
	 */
	public void setIndex(int tIndex) {
		if (curve != null)
			setT(curve.getT(tIndex));
	}

	/**
	 * Draw the decoration.  If the curve is null when this is called, then
	 * curve will be set to the exhibit displayed in the View, which should
	 * be of type PlaneCurveParameteric, if this decoration is being used correctly.
	 */
	public void doDraw(org.freehep.graphics2d.VectorGraphics g, View view, Transform limits) {
		if (curve == null && view != null) {
			Exhibit c = view.getExhibit();
			if (c instanceof PlaneCurveParametric)  // It better be!
				curve = (PlaneCurveParametric)c;
			else
				return;
		}
		if (Double.isNaN(t))
			return;
		double x = curve.xValue(t);
		if (Double.isNaN(x) || Double.isInfinite(x))
			return;
		double y = curve.yValue(t);
		if (Double.isNaN(y) || Double.isInfinite(y))
			return;
		double dx = curve.xDerivativeValue(t);
		if (Double.isNaN(dx) || Double.isInfinite(dx))
			return;
		double dy = curve.yDerivativeValue(t);
		if (Double.isNaN(dy) || Double.isInfinite(dy))
			return;
		double length = Math.sqrt(dx*dx + dy*dy);
		if (length == 0)
			return;
		dx = dx/length * 40*limits.getPixelWidth();
		dy = dy/length * 40*limits.getPixelHeight();
		Color saveColor = g.getColor();
		Stroke saveStroke = g.getStroke();
		g.setStroke(new BasicStroke(2*limits.getDefaultStrokeSize()));
		g.setColor(Color.red);
		g.draw(new Line2D.Double(x,y,x+dx,y+dy));
		g.setColor(Color.blue);
		g.draw(new Line2D.Double(x,y,x-dy,y+dx));
		g.setColor(saveColor);
		g.setStroke(saveStroke);
	}
		
}

 

Ads help maintain this website.