# IKRootsHelper

class in `closed-chain-ik/three`, extends `Group`

```js
import { IKRootsHelper } from 'closed-chain-ik/three';
```

Renders the frames of an IK system in a three.js scene. Frame relationships are drawn as
lines and joints are drawn with indicators for their degrees of freedom.

Example: Drawing a robot's IK links and joints as it moves

```js
import { HemisphereLight, MathUtils } from 'three';
import URDFLoader from 'urdf-loader';
import { Solver, Goal, IKRootsHelper, URDFUtils, IKUtils } from 'closed-chain-ik';

// scene, camera and renderer are initialized here

const URL = 'https://raw.githubusercontent.com/gkjohnson/urdf-loaders/master/urdf/T12/urdf/T12_flipped.URDF';

scene.add( new HemisphereLight( 0xffffff, 0x444444, 3 ) );
camera.position.set( 6, 5, 8 );

const robot = await new URDFLoader().loadAsync( URL );
robot.rotation.x = Math.PI / 2;
robot.position.y = 1.25;
for ( let i = 1; i <= 6; i ++ ) {

	robot.setJointValue( `HP${ i }`, MathUtils.degToRad( 30 ) );
	robot.setJointValue( `KP${ i }`, MathUtils.degToRad( 90 ) );
	robot.setJointValue( `AP${ i }`, MathUtils.degToRad( - 30 ) );

}

robot.updateMatrixWorld( true );
scene.add( robot );

const ik = URDFUtils.urdfRobotToIKRoot( robot );
URDFUtils.setIKFromUrdf( ik, robot );
IKUtils.saveRestPose( ik );

ik.traverse( frame => {

	if ( ! /^Foot/.test( frame.name ) ) return;

	const goal = new Goal();
	goal.makeClosure( frame );
	frame.getWorldPosition( goal.position );
	frame.getWorldQuaternion( goal.quaternion );
	goal.setMatrixNeedsUpdate();

} );

const body = ik.find( frame => frame.name === 'Body' );
const bodyGoal = new Goal();
bodyGoal.makeClosure( body );
body.getWorldQuaternion( bodyGoal.quaternion );

const start = [ 0, 0, 0 ];
body.getWorldPosition( start );

const helper = new IKRootsHelper( ik );
helper.setColor( 0xe91e63 );

const drawThroughHelper = new IKRootsHelper( ik );
drawThroughHelper.setColor( 0xe91e63 );
drawThroughHelper.setDrawThrough( true );
scene.add( helper, drawThroughHelper );

const solver = new Solver( ik );
renderer.setAnimationLoop( time => {

	const angle = time / 800;
	bodyGoal.setPosition( start[ 0 ] + 0.4 * Math.cos( angle ), start[ 1 ] + 0.35 * Math.sin( 2 * angle ), start[ 2 ] + 0.4 * Math.sin( angle ) );
	solver.solve();
	URDFUtils.setUrdfFromIK( robot, ik );
	renderer.render( scene, camera );

} );
```

## Constructor

```js
new IKRootsHelper( roots: Frame | Array<Frame> )
```

- `roots`, `Frame | Array<Frame>`: The roots of the trees to render.

## Properties

### .roots: Array<Frame>

The roots to render. If modified `updateStructure` must be called.

## Methods

### .setColor

```js
.setColor( color: Color | string | number ): IKRootsHelper
```

Sets the color of the helper.

- `color`, `Color | string | number`

### .setJointScale

```js
.setJointScale( scale: number ): IKRootsHelper
```

Sets the scale of the joint indicators.

- `scale`, `number`

### .setDrawThrough

```js
.setDrawThrough( drawThrough: boolean ): IKRootsHelper
```

Sets whether the helper is drawn on top of everything else in the scene.

- `drawThrough`, `boolean`

### .updateStructure

```js
.updateStructure(  )
```

Rebuilds the helpers for the frames in the roots. Must be called whenever the structure of
the rendered trees or `roots` change.

### .dispose

```js
.dispose(  )
```

Disposes of every material and geometry created by the helper.
