/// <summary>
        /// Sorts index array (optionally single threaded)
        /// Both variants return a CountdownEvent. For
        /// sequential execution (parallel = false), the
        /// returned event initially is signalled.
        /// </summary>
        public CountdownEvent SortVertexIndexArray(
            Order order, V3d eye, int[] vertexIndexArray, bool parallel = true)
        {
            var target = new TargetArray()
            {
                Via      = vertexIndexArray,
                Finished = new CountdownEvent(1)
            };

            Action <Action> runParallel   = a => Task.Factory.StartNew(a);
            Action <Action> runSequential = a => a();
            Action <Action> runChild      = parallel ? runParallel : runSequential;


            if (order == Order.BackToFront)
            {
                runChild(() =>
                {
                    m_tree.SortBackToFront(this, target, 0, eye, true, runChild);
                    target.Finished.Signal();
                });
            }
            else
            {
                runChild(() =>
                {
                    m_tree.SortFrontToBack(this, target, 0, eye, true, runChild);
                    target.Finished.Signal();
                });
            }

            if (!parallel)
            {
                target.Finished.Wait();
            }

            return(target.Finished);
        }
        /// <summary>
        /// Note, that the parallel implementation of this method could be
        /// optimized, by providing separate node types for parallel and non
        /// parallel execution.
        /// </summary>
        internal void SortBackToFront(
            BspTree t, TargetArray via,
            int ti3, V3d eye, bool mainTask, Action <Action> runChild)
        {
            int    nti3   = ti3;
            double height = V3d.Dot(m_normal, eye - m_point);

            if (height >= 0.0)
            {
                ti3 += m_negativeCount;
                foreach (int tiMul3 in m_zeroList)
                {
                    t.GetTriangleVertexIndices(tiMul3,
                                               out via.Via[ti3],
                                               out via.Via[ti3 + 1],
                                               out via.Via[ti3 + 2]);
                    ti3 += 3;
                }
            }
            else
            {
                nti3 += m_positiveCount;
                foreach (int tiMul3 in m_zeroList)
                {
                    t.GetTriangleVertexIndices(tiMul3,
                                               out via.Via[nti3],
                                               out via.Via[nti3 + 1],
                                               out via.Via[nti3 + 2]);
                    nti3 += 3;
                }
            }
            if (m_negativeTree != null)
            {
                if (mainTask && m_negativeCount < c_taskChunkSize)
                {
                    // via.Count += 1;
                    via.Finished.AddCount(1);
                    runChild(() =>
                    {
                        m_negativeTree.SortBackToFront(
                            t, via, nti3, eye, false, runChild);
                        via.Finished.Signal();
                    });
                }
                else
                {
                    m_negativeTree.SortBackToFront(
                        t, via, nti3, eye, mainTask, runChild);
                }
            }
            if (m_positiveTree != null)
            {
                if (mainTask && m_positiveCount < c_taskChunkSize)
                {
                    // via.Count += 1;
                    via.Finished.AddCount(1);
                    runChild(() =>
                    {
                        m_positiveTree.SortBackToFront(
                            t, via, ti3, eye, false, runChild);
                        via.Finished.Signal();
                    });
                }
                else
                {
                    m_positiveTree.SortBackToFront(
                        t, via, ti3, eye, mainTask, runChild);
                }
            }
        }