Skip to content
Snippets Groups Projects
AnglePainter.java 9.22 KiB
package plugins.fab.anglehelper;

import icy.canvas.IcyCanvas;
import icy.canvas.IcyCanvas2D;
import icy.gui.util.GuiUtil;
import icy.main.Icy;
import icy.math.Scaler;
import icy.painter.Anchor2D;
import icy.painter.Anchor2D.Anchor2DListener;
import icy.painter.Painter;
import icy.painter.PainterEvent;
import icy.roi.ROI2D;
import icy.sequence.Sequence;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import plugins.fab.Ruler.Anchor2DTarget;
import plugins.fab.Ruler.ShapeDefinition;

/**
 * @author Fabrice de Chaumont
 */
public class AnglePainter implements Painter, Anchor2DListener {

	Anchor2DTarget a1 = new Anchor2DTarget( 0 , 0 );
	Anchor2DTarget a2 = new Anchor2DTarget( 0 , 0 );
	Anchor2DTarget a3 = new Anchor2DTarget( 0 , 0 );
	
	ArrayList<ShapeDefinition> shapeDefinitionList = new ArrayList<ShapeDefinition>();
	ArrayList<AffineTransform> affineTransformList = new ArrayList<AffineTransform>();
	
	public AnglePainter(Sequence sequence) {
	
		if ( sequence == null ) return;
		
		a1.setPosition( sequence.getWidth() / 2 , sequence.getHeight() / 2 );
		a2.setPosition( 3 * sequence.getWidth() / 4 , sequence.getHeight() / 2 );
		a3.setPosition( 3 * sequence.getWidth() / 4 , sequence.getHeight() / 3 );

		sequence.addPainter( this );
		a1.addListener( this );
		a2.addListener( this );
		a3.addListener( this );
		
	}
	
	// Listener of Anchor
	
	@Override
	public void painterChanged(PainterEvent event) {
		
		for ( Sequence sequence : Icy.getMainInterface().getSequencesContaining( this ) )
		{
			sequence.painterChanged( this );
		}
		
	}
	@Override
	public void positionChanged(Anchor2D source) {
		
		
	}
	
	void pushTransform( Graphics2D g )
	{
		affineTransformList.add( g.getTransform() );
	}

	void popTransform( Graphics2D g )
	{
		g.setTransform( affineTransformList.get( affineTransformList.size() -1 ) );
		affineTransformList.remove( affineTransformList.size() -1 );
	}
	
	public double CleanAngle( double angle )
	{
		double a = Math.abs( angle );
		a = Math.round(a*10)/10.;
		return a;
	}
	
	// Painter Section:

	@Override
	public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas) {
		
		if ( ! ( canvas instanceof IcyCanvas2D ) ) return;
		
		g= (Graphics2D) g.create();
		
		BasicStroke[] stroke = new BasicStroke[4];
		
		stroke[0] = new BasicStroke((float) ROI2D.canvasToImageLogDeltaX(canvas, 2 ) ); 
		stroke[1] = new BasicStroke((float) ROI2D.canvasToImageLogDeltaX(canvas, 3 ) ); 
		stroke[2] = new BasicStroke((float) ROI2D.canvasToImageLogDeltaX(canvas, 4 ) ); 
		stroke[3] = new BasicStroke((float) ROI2D.canvasToImageLogDeltaX(canvas, 5 ) ); 
				
		// transform and display ticks

		shapeDefinitionList.clear();
	
		pushTransform( g );
		
		double vx12 = ( a2.getX() - a1.getX() ) ;
		double vy12 = ( a2.getY() - a1.getY() ) ;
		double angle12 = Math.atan2( vy12 , vx12 ) * ( 180d / Math.PI ) ;

		double vx13 = ( a3.getX() - a1.getX() ) ;
		double vy13 = ( a3.getY() - a1.getY() ) ;
		double angle13 = Math.atan2( vy13 , vx13 ) * ( 180d / Math.PI );

		double angle1 = angle12-angle13;

		if ( angle1 < 0 ) angle1+=360;
		
		double angle2 = 360-angle1;
		
		double dis1 = a1.getPosition().distance( a2.getPosition() );
		double dis2 = a1.getPosition().distance( a3.getPosition() );
		
		double minDistance = Math.min( dis1 , dis2 );		

		double distanceAngle1 = minDistance ;
		double distanceAngle2 = minDistance / 2;

		double distanceTextAngle1 = minDistance;
		double distanceTextAngle2 = minDistance/2;
		
		// Lines
		
		shapeDefinitionList.add( new ShapeDefinition( 2 , new Line2D.Double( a1.getPosition() , a2.getPosition() ) ) );
		shapeDefinitionList.add( new ShapeDefinition( 2 , new Line2D.Double( a1.getPosition() , a3.getPosition() ) ) );

		// angle 1
		{
			double arcSize = distanceAngle1;
			Arc2D arc = new Arc2D.Double( 
					a1.getX() - arcSize/2d,
					a1.getY() - arcSize/2d,
					arcSize,
					arcSize,
					-angle12 ,
					angle1,//angle13,
					Arc2D.OPEN
					);

			shapeDefinitionList.add( new ShapeDefinition( 2 , arc ) );
		}
		
		// angle 2
		{
			double arcSize = distanceAngle2;
			Arc2D arc = new Arc2D.Double( 
					a1.getX() - arcSize/2d,
					a1.getY() - arcSize/2d,
					arcSize,
					arcSize,
					-angle13 ,
					angle2,//angle13,
					Arc2D.OPEN
					);

			shapeDefinitionList.add( new ShapeDefinition( 2 , arc ) );
		}

		// draw lines ( black background, then white )
		
		float oldAlpha= -1;
		g.setColor( Color.black );
		for ( ShapeDefinition ld : shapeDefinitionList )
		{
			if (oldAlpha!=ld.alpha)
			{
				g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, ld.alpha ) );
				oldAlpha = ld.alpha;
			}
			g.setStroke( stroke[ld.stroke] );
			g.draw( ld.shape );
		}

		g.setColor( Color.white );
		for ( ShapeDefinition ld : shapeDefinitionList )
		{
			if (oldAlpha!=ld.alpha)
			{
				g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, ld.alpha ) );
				oldAlpha = ld.alpha;
			}
			g.setStroke( stroke[ld.stroke-1] );
			g.draw( ld.shape );
		}
		
		// Display angle text
		
		{
			int fontSize =  (int)convertScale(canvas, 15 );
			Font font =  new Font( "Arial" , Font.PLAIN , fontSize ); 

			pushTransform( g );
			String pixelString = " "+ (int)( Math.round( angle1 ) ) + "° ";
			Rectangle2D pixelBounds = GuiUtil.getStringBounds( g , font, pixelString );
			g.translate( a1.getX() , a1.getY() );
			
			double angleText = Math.toRadians( angle12 - angle1 / 2d );			
			g.translate( Math.cos( angleText  ) * distanceTextAngle1 /2 , Math.sin( angleText ) * distanceTextAngle1 /2 );
			g.translate( -pixelBounds.getWidth() / 2 , 0 );
			
			g.setFont( font );
			g.setColor( Color.white );
			g.fill( pixelBounds );
			g.setColor( Color.black );
			g.drawString( pixelString , 0, 0 );
			popTransform( g );
		}

		{
			int fontSize =  (int)convertScale(canvas, 15 );
			Font font =  new Font( "Arial" , Font.PLAIN , fontSize ); 

			pushTransform( g );
			String pixelString = " "+ (int)(Math.round( angle2 ) ) + "� ";
			Rectangle2D pixelBounds = GuiUtil.getStringBounds( g , font, pixelString );
			g.translate( a1.getX() , a1.getY() );
			
			double angleText = Math.toRadians( 180 + angle12 - angle1 / 2d );			
			g.translate( Math.cos( angleText  ) * distanceTextAngle2 / 2d , Math.sin( angleText ) * distanceTextAngle2 / 2d );
			g.translate( -pixelBounds.getWidth() / 2 , 0 );

			float alpha = 1 ;
			double distance = canvas.getScaleX() * distanceTextAngle2 / 2d ;
			
			Scaler scaler = new Scaler( 0 , 10 , 0, 1 , false );
			alpha = (float)scaler.scale( distance - pixelBounds.getWidth() / 10d );
					
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha ) );

			g.setFont( font );
			g.setColor( Color.white );
			g.fill( pixelBounds );
			g.setColor( Color.black );
			g.drawString( pixelString , 0, 0 );
			
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1 ) );
			popTransform( g );
		}
		
		// get back to original transform
				
		popTransform( g );

		// display anchors
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1 ) );
		a1.paint( g, sequence, canvas);
		a2.paint( g, sequence, canvas);
		a3.paint( g, sequence, canvas);
	}
		
	double convertScale( IcyCanvas canvas , double value )
	{
		return ROI2D.canvasToImageLogDeltaX(canvas, value ); 
	}

	@Override
	public void mousePressed(MouseEvent e, Point2D imagePoint, IcyCanvas canvas) {
		a1.mousePressed(e, imagePoint, canvas);		
		a2.mousePressed(e, imagePoint, canvas);
		a3.mousePressed(e, imagePoint, canvas);
	}

	@Override
	public void mouseReleased(MouseEvent e, Point2D imagePoint, IcyCanvas canvas) {
		a1.mouseReleased(e, imagePoint, canvas);
		a2.mouseReleased(e, imagePoint, canvas);
		a3.mouseReleased(e, imagePoint, canvas);
	}

	@Override
	public void mouseClick(MouseEvent e, Point2D imagePoint, IcyCanvas canvas) {
		a1.mouseClick(e, imagePoint, canvas);
		a2.mouseClick(e, imagePoint, canvas);
		a3.mouseClick(e, imagePoint, canvas);
		
	}

	@Override
	public void mouseMove(MouseEvent e, Point2D imagePoint, IcyCanvas canvas) {
		a1.mouseMove(e, imagePoint, canvas);
		a2.mouseMove(e, imagePoint, canvas);
		a3.mouseMove(e, imagePoint, canvas);
	}

	@Override
	public void mouseDrag(MouseEvent e, Point2D imagePoint, IcyCanvas canvas) {
		a1.mouseDrag(e, imagePoint, canvas);
		a2.mouseDrag(e, imagePoint, canvas);
		a3.mouseDrag(e, imagePoint, canvas);
	}

	@Override
	public void keyPressed(KeyEvent e, Point2D imagePoint, IcyCanvas canvas) {
				
		if ( ( e.getKeyCode() == KeyEvent.VK_DELETE && a1.isSelected() ) || ( e.getKeyCode() == KeyEvent.VK_DELETE && a2.isSelected() ) )
		{			
			for ( Sequence sequence : Icy.getMainInterface().getSequencesContaining( this ) )
			{
				sequence.removePainter( this );
			}
			
		}
			
		a1.keyPressed(e, imagePoint, canvas);
		a2.keyPressed(e, imagePoint, canvas);
		a3.keyPressed(e, imagePoint, canvas);
	}

	@Override
	public void keyReleased(KeyEvent e, Point2D imagePoint, IcyCanvas canvas) {
		a1.keyReleased(e, imagePoint, canvas);
		a2.keyReleased(e, imagePoint, canvas);
		a3.keyReleased(e, imagePoint, canvas);
	}	
	
}