public static Element drawCosine ( SVGPlot svgp , Projection2D proj , NumberVector mid , double angle ) { // Project origin double [ ] pointOfOrigin = proj . fastProjectDataToRenderSpace ( new double [ proj . getInputDimensionality ( ) ] ) ; // direction of the selected Point double [ ] selPoint = proj . fastProjectDataToRenderSpace ( mid ) ; double [ ] range1 , range2 ; { // Rotation plane: double [ ] pm = mid . toArray ( ) ; // Compute relative vectors double [ ] p1 = minusEquals ( proj . fastProjectRenderToDataSpace ( selPoint [ 0 ] + 10 , selPoint [ 1 ] ) , pm ) ; double [ ] p2 = minusEquals ( proj . fastProjectRenderToDataSpace ( selPoint [ 0 ] , selPoint [ 1 ] + 10 ) , pm ) ; // Scale p1 and p2 to unit length: timesEquals ( p1 , 1. / euclideanLength ( p1 ) ) ; timesEquals ( p2 , 1. / euclideanLength ( p2 ) ) ; if ( Math . abs ( scalarProduct ( p1 , p2 ) ) > 1E-10 ) { LoggingUtil . warning ( "Projection does not seem to be orthogonal?" ) ; } // Project onto p1, p2: double l1 = scalarProduct ( pm , p1 ) , l2 = scalarProduct ( pm , p2 ) ; // Rotate projection by + and - angle // Using sin(-x) = -sin(x) and cos(-x)=cos(x) final DoubleWrapper tmp = new DoubleWrapper ( ) ; // To return cosine final double sangle = FastMath . sinAndCos ( angle , tmp ) , cangle = tmp . value ; double r11 = + cangle * l1 - sangle * l2 , r12 = + sangle * l1 + cangle * l2 ; double r21 = + cangle * l1 + sangle * l2 , r22 = - sangle * l1 + cangle * l2 ; // Build rotated vectors - remove projected component, add rotated // component: double [ ] r1 = plusTimesEquals ( plusTimes ( pm , p1 , - l1 + r11 ) , p2 , - l2 + r12 ) ; double [ ] r2 = plusTimesEquals ( plusTimes ( pm , p1 , - l1 + r21 ) , p2 , - l2 + r22 ) ; // Project to render space: range1 = proj . fastProjectDataToRenderSpace ( r1 ) ; range2 = proj . fastProjectDataToRenderSpace ( r2 ) ; } // Continue lines to viewport. { CanvasSize viewport = proj . estimateViewport ( ) ; minusEquals ( range1 , pointOfOrigin ) ; plusEquals ( timesEquals ( range1 , viewport . continueToMargin ( pointOfOrigin , range1 ) ) , pointOfOrigin ) ; minusEquals ( range2 , pointOfOrigin ) ; plusEquals ( timesEquals ( range2 , viewport . continueToMargin ( pointOfOrigin , range2 ) ) , pointOfOrigin ) ; // Go backwards into the other direction - the origin might not be in the // viewport! double [ ] start1 = minus ( pointOfOrigin , range1 ) ; plusEquals ( timesEquals ( start1 , viewport . continueToMargin ( range1 , start1 ) ) , range1 ) ; double [ ] start2 = minus ( pointOfOrigin , range2 ) ; plusEquals ( timesEquals ( start2 , viewport . continueToMargin ( range2 , start2 ) ) , range2 ) ; // TODO: add filled variant? return new SVGPath ( ) . moveTo ( start1 ) . lineTo ( range1 ) . moveTo ( start2 ) . lineTo ( range2 ) . makeElement ( svgp ) ; } }
Visualizes Cosine and ArcCosine distance functions