private void CreateLinks()
        {
            #region Build up input args

            List<NeuralUtility.ContainerInput> inputs = new List<NeuralUtility.ContainerInput>();
            if (_gravSensors != null)
            {
                foreach (GravSensorStuff sensor in _gravSensors)
                {
                    // The sensor is a source, so shouldn't have any links.  But it needs to be included in the args so that other
                    // neuron containers can hook to it
                    inputs.Add(new NeuralUtility.ContainerInput(sensor.Body.Token, sensor.Sensor, NeuronContainerType.Sensor, sensor.Sensor.Position, sensor.Sensor.Orientation, null, null, 0, null, null));
                }
            }

            if (_brains != null)
            {
                foreach (BrainStuff brain in _brains)
                {
                    inputs.Add(new NeuralUtility.ContainerInput(
                        brain.Body.Token,
                        brain.Brain, NeuronContainerType.Brain,
                        brain.Brain.Position, brain.Brain.Orientation,
                        _itemOptions.Brain_LinksPerNeuron_Internal,
                        new Tuple<NeuronContainerType, NeuralUtility.ExternalLinkRatioCalcType, double>[]
							{
								Tuple.Create(NeuronContainerType.Sensor, NeuralUtility.ExternalLinkRatioCalcType.Smallest, _itemOptions.Brain_LinksPerNeuron_External_FromSensor),
								Tuple.Create(NeuronContainerType.Brain, NeuralUtility.ExternalLinkRatioCalcType.Average, _itemOptions.Brain_LinksPerNeuron_External_FromBrain),
								Tuple.Create(NeuronContainerType.Manipulator, NeuralUtility.ExternalLinkRatioCalcType.Smallest, _itemOptions.Brain_LinksPerNeuron_External_FromManipulator)
							},
                        Convert.ToInt32(Math.Round(brain.Brain.BrainChemicalCount * 1.33d, 0)),		// increasing so that there is a higher chance of listeners
                        brain.DNAInternalLinks, brain.DNAExternalLinks));
                }
            }

            if (_thrusters != null)
            {
                foreach (var thrust in _thrusters)
                {
                    //TODO: Consider existing links
                    //NOTE: This won't be fed by other manipulators
                    inputs.Add(new NeuralUtility.ContainerInput(
                        thrust.Body.Token,
                        thrust.Thrust, NeuronContainerType.Manipulator,
                        thrust.Thrust.Position, thrust.Thrust.Orientation,
                        null,
                        new Tuple<NeuronContainerType, NeuralUtility.ExternalLinkRatioCalcType, double>[]
							{
								Tuple.Create(NeuronContainerType.Sensor, NeuralUtility.ExternalLinkRatioCalcType.Destination, _itemOptions.Thruster_LinksPerNeuron_Sensor),
								Tuple.Create(NeuronContainerType.Brain, NeuralUtility.ExternalLinkRatioCalcType.Destination, _itemOptions.Thruster_LinksPerNeuron_Brain),
							},
                        0,
                        null, thrust.DNAExternalLinks));
                }
            }

            #endregion

            // Create links
            NeuralUtility.ContainerOutput[] outputs = null;
            if (inputs.Count > 0)
            {
                outputs = NeuralUtility.LinkNeurons(inputs.ToArray(), _itemOptions.NeuralLink_MaxWeight);
            }

            #region Show new links

            if (outputs != null)
            {
                _links = new LinkStuff();
                _links.Outputs = outputs;
                _links.Visuals = new List<Visual3D>();

                Model3DGroup posLines = null, negLines = null;
                DiffuseMaterial posDiffuse = null, negDiffuse = null;

                Dictionary<INeuronContainer, Transform3D> containerTransforms = new Dictionary<INeuronContainer, Transform3D>();

                foreach (var output in outputs)
                {
                    Transform3D toTransform = GetContainerTransform(containerTransforms, output.Container);

                    foreach (var link in UtilityCore.Iterate(output.InternalLinks, output.ExternalLinks))
                    {
                        Transform3D fromTransform = GetContainerTransform(containerTransforms, link.FromContainer);

                        BuildLinkVisual(ref posLines, ref posDiffuse, ref negLines, ref negDiffuse, fromTransform.Transform(link.From.Position), toTransform.Transform(link.To.Position), link.Weight, link.BrainChemicalModifiers, _colors);
                    }
                }

                if (posLines != null)
                {
                    ModelVisual3D model = new ModelVisual3D();
                    model.Content = posLines;
                    _links.Visuals.Add(model);
                    _viewportNeural.Children.Add(model);
                }

                if (negLines != null)
                {
                    ModelVisual3D model = new ModelVisual3D();
                    model.Content = negLines;
                    _links.Visuals.Add(model);
                    _viewportNeural.Children.Add(model);
                }
            }

            #endregion

            UpdateCountReport();

            if (chkBrainRunning.IsChecked.Value)
            {
                StartBrainOperation();
            }
        }
        private void ClearLinks()
        {
            ClearDebugVisuals();
            CancelBrainOperation();

            if (_links != null)
            {
                foreach (Visual3D visual in _links.Visuals)
                {
                    _viewportNeural.Children.Remove(visual);
                }

                _links = null;
            }

            // Reset the neuron values (leave the sensors alone, because they aren't affected by links)
            foreach (var neuron in UtilityCore.Iterate(
                _brains == null ? null : _brains.SelectMany(o => o.Neurons),
                _thrusters == null ? null : _thrusters.SelectMany(o => o.Neurons)))
            {
                neuron.Item1.SetValue(0d);
            }
        }