/*============================================================================= * 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);