/*=============================================================================
* Copyright Rob Clark 2000. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $
*/
pkg.system.declareJavaPackage("java.awt");
var swing = new JavaPackage("javax.swing");
var Math = java.lang.Math;
var Point = java.awt.Point;
var Dimension = java.awt.Dimension;
var BasicStroke = java.awt.BasicStroke;
function sin(d)
{
return Math.sin( Math.PI * d / 180.0 );
}
function cos(d)
{
return Math.cos( Math.PI * d / 180.0 );
}
var min = java.lang.Math.min;
var max = java.lang.Math.max;
/**
* A widget that given an inner radius, outer radius, and theta, will calulate
* and display the widest arc through the specified curve.
*
* @param ri inner radius (Ri)
* @param ro outer radius (Ro)
* @param theta angle turn sweeps through
*/
public function CurveDisplay( ri, ro, theta )
extends swing.JComponent()
{
/**
* ri -> Ri (inner radius)
* ro -> Ro (outer radius)
* rw -> Rw (widest arc radius)
*
* if center of Ci (arc describing inner edge of curve) and Co (arc describing
* outer edge of curve) are (0,0), then center of Cw (arc describign widest
* line) is (-x,-y)
*
*
* ro - ri cos(theta/2)
* rw = ----------------------
* 1 - cos(theta/2)
*
* x = rw - ro
* z = rw - ri
* y = z sin(theta/2)
*/
var rw;
var x;
var y;
var z;
/**
* When any of ri, ro, or theta change, this shoudl be called to recalculate
* widest arc through curve.
*/
function recalculate()
{
rw = (ro - (ri * cos(theta/2.0))) / (1.0 - cos(theta/2.0));
x = rw - ro;
z = rw - ri;
y = z * sin(theta/2.0);
repaint();
}
/**
* Set the Ri and Ro parameters. Must be less than outer radius.
*/
public function setRadius( _ri, _ro )
{
ri = _ri;
ro = _ro;
recalculate();
}
/**
* Set the angle the curve sweeps through. This parameter is in degrees and
* should be between 0 and 180.
*/
public function setTheta( _theta )
{
theta = _theta;
recalculate();
}
/**
*/
public function getWidestArcRadius()
{
return rw;
}
/**
*/
public function paint( g )
{
writeln("ro="+ro+",ri="+ri+",rw="+rw);
/**
* @param o origin
* @param r radius
* @param sa start-angle
* @param aa sweep-angle
*/
function drawArc( o, r, sa, aa )
{
g.drawArc( o.x - r, o.y - r,
r * 2.0, r * 2.0,
sa, aa );
}
/**
*/
function drawLine( x, y, dx, dy )
{
g.drawLine( x, y, x + dx, y + dy );
}
/* the swing coord system has (0,0) as the upper left corner, so everything
* needs to be translated relative to that...
*/
var w = getWidth();
var h = getHeight();
var o = new Point( w/2, h/2 ); // the origin, center of curve
//g.drawLine( o.x, o.y, o.x + ro, o.y );
g.setStroke( new BasicStroke(2) );
// draw inner-curve:
drawArc( o, ri, 0, theta );
// draw outer-curve:
drawArc( o, ro, 0, theta );
// draw straight leading into turn:
drawLine( o.x + ri * cos(theta), o.y - ri * sin(theta),
-y * cos(90.0-theta), -y * sin(90.0-theta) );
drawLine( o.x + ro * cos(theta), o.y - ro * sin(theta),
-y * cos(90.0-theta), -y * sin(90.0-theta) );
// draw straight coming out of turn:
drawLine( o.x + ri, o.y, 0, y );
drawLine( o.x + ro, o.y, 0, y );
// draw the widest-curve:
g.setStroke( new BasicStroke( 2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10, [2,5], 0 ) );
drawArc( new Point( o.x - x, o.y + y ), rw, 0, theta );
}
recalculate();
}
/**
* This is the window that has the curve display calc plus sliders and stuff...
*/
function CurveCalc()
extends swing.JFrame()
{
var innerRadius = 80.0;
var trackWidth = 40.0;
var angle = 140.0;
var box = new swing.Box( swing.BoxLayout.Y_AXIS );
// the curve-calculator:
var curveDisp = new CurveDisplay( innerRadius, innerRadius + trackWidth, angle );
curveDisp.setPreferredSize( new Dimension( 400, 400 ) );
box.add(curveDisp);
// the angle slider:
box.add( new swing.JLabel("Angle:") );
var angleSlider = new swing.JSlider( 15, 165, angle );
angleSlider.addChangeListener( new (function() extends swing.event.ChangeListener() {
public function stateChanged( evt )
{
angle = angleSlider.getValue();
updateAll();
}
})() );
box.add(angleSlider);
// the radius slider:
box.add( new swing.JLabel("Radius:") );
var radiusSlider = new swing.JSlider( 10, 90, innerRadius );
radiusSlider.addChangeListener( new (function() extends swing.event.ChangeListener() {
public function stateChanged( evt )
{
innerRadius = 0.0 + radiusSlider.getValue();
updateAll();
}
})() );
box.add(radiusSlider);
// the width slider:
box.add( new swing.JLabel("Width:") );
var widthSlider = new swing.JSlider( 10, 70, trackWidth );
widthSlider.addChangeListener( new (function() extends swing.event.ChangeListener() {
public function stateChanged( evt )
{
trackWidth = widthSlider.getValue();
updateAll();
}
})() );
box.add(widthSlider);
var statusLabel = new swing.JLabel();
box.add(statusLabel);
getContentPane().add(box);
function updateAll()
{
var rw = curveDisp.getWidestArcRadius();
var r = ((2 * innerRadius) + trackWidth) / 2;
curveDisp.setTheta(angle);
curveDisp.setRadius( innerRadius, innerRadius + trackWidth );
statusLabel.setText("<html>R<sub>i</sub> = " + innerRadius +
"<br>R<sub>o</sub> = " + (innerRadius + trackWidth) +
"<br>R<sub>w</sub> = " + rw +
"<br>widest arc is " + (((rw-r)/r)*100.0) + "% larger" +
"</html>" );
}
updateAll();
pack();
}
var window = new CurveCalc();
window.setVisible(true);