using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace VisiMath.Geometry
{
    /// <summary>
    /// Geometry object using list of vertices and several sets of indices to specify primitive.
    /// EVERY operation is working only on the current selected subset!
    /// </summary>
    public abstract class IndexedGeo : Geometry    
    {
        /// <summary>
        /// All indices of the geometry
        /// </summary>
        public int[][] Indices;
        /// <summary>
        /// Currently selected subset
        /// </summary>
        protected int _currentSubset;

        /// <summary>
        /// Type of the mesh
        /// </summary>
        public abstract PrimitiveTypes MeshType {get;}

        /// <summary>
        /// Number of indices per one element
        /// </summary>
        public abstract int IndicesPerElement { get; }

        /// <summary>
        /// Gets or sets current subset in case there are more
        /// </summary>
        public int CurrentSubset 
        {
            get { return _currentSubset;}
            set 
            { 
                if (value > Indices.Length)
                    throw new ArgumentException("Indexed Geo doesn't contain so many subsets!");
                _currentSubset = value;
            }
        }

        /// <summary>
        /// Returns number of subsets in indexed geo
        /// </summary>
        public int SubsetCount
        {
            get{ return Indices.Length;}
        }

        /// <summary>
        /// Returns current indices
        /// </summary>
        public int[] CurrentIndices
        {
            get 
            {
                return Indices[_currentSubset];
            }
        }

        /// <summary>
        /// Returns vertex pointed to by index in current indices
        /// </summary>
        /// <param name="index">Index of indice</param>
        /// <returns>Vertex</returns>
        public override IVertex GetVertex(int index)
        {
            return Vertices[CurrentIndices[index]];
        }

        public void SetVertex(int index, IVertex ver)
        {
            Vertices[CurrentIndices[index]] = ver;
        }

        /// <summary>
        /// Returns positional vector pointed to by index in current indices
        /// </summary>
        /// <param name="index">Index of indice</param>
        /// <param name="vec">Vector to save position</param>
        public override void GetPosition(int index, out Vector3 vec)
        {
            vec = Vertices[CurrentIndices[index]].Position;
        }

        /// <summary>
        /// XML reader constructor
        /// </summary>
        /// <param name="reader">XML reader</param>
        public IndexedGeo(System.Xml.XmlReader reader)
            : base(reader)
        {
        }

        /// <summary>
        /// Copy constructor
        /// </summary>
        /// <param name="source">Source geometry</param>
        public IndexedGeo(IndexedGeo source)
        {
            Indices = new int[source.Indices.Length][];
            for (int i = 0; i < Indices.Length; i++)
            {
                Indices[i] = new int[source.Indices[i].Length];
                source.Indices[i].CopyTo(Indices[i], 0);
            }
            Vertices = source.Vertices.GetCopy();
        }

        /// <summary>
        /// Creates indexed geo with default vertex format, with specified number of vertices, one subset with selected number of indices
        /// </summary>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexcount">Number of indices</param>
        public IndexedGeo(int vertexcount, int indexcount) : base(vertexcount)
        {
            ConstructIndices(indexcount);
        }

        /// <summary>
        /// Creates indexed geo with default vertex format, with specified number of vertices, specified number of subset with selected number of indices
        /// </summary>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexsets">Number of subsets</param>
        /// <param name="indexcounts">Array with length of all subsets</param>
        public IndexedGeo(int vertexcount, int indexsets, int[] indexcounts) : base(vertexcount)
        {
            ConstructIndices(indexsets, indexcounts);
        }

        /// <summary>
        /// Creates indexed geo of specified format, with specified number of vertices, one subset and specified number of indices
        /// </summary>
        /// <param name="vertextype">Type of vertex (must be IVertex)</param>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexcount">Number of indices</param>
        public IndexedGeo(Type vertextype, int vertexcount, int indexcount) :base(vertextype, vertexcount)
        {
            ConstructIndices(indexcount);
        }

        /// <summary>
        /// Creates indexed geo of specified format, with specified number of vertices, specified number of subsets and specified number of indices
        /// </summary>
        /// <param name="vertextype">Type of vertex (must be IVertex)</param>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexsets">Number of subsets</param>
        /// <param name="indexcounts">Array with length of all subsets</param>
        public IndexedGeo(Type vertextype, int vertexcount, int indexsets, int[] indexcounts) : base(vertextype, vertexcount)
        {
            ConstructIndices(indexsets, indexcounts);
        }

        /// <summary>
        /// Creates indexed geo from array of vertices one subset and specified number of indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indexcount">number of vertices</param>
        public IndexedGeo(IVertexArray source, int indexcount) : base(source)
        {
            ConstructIndices(indexcount);
        }

        /// <summary>
        /// Creates indexed geo from array of vertices specified number of subsets and specified number of indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indexsets">Number of subsets</param>
        /// <param name="indexcounts">Array with length of all subsets</param>
        public IndexedGeo(IVertexArray source, int indexsets, int[] indexcounts) : base(source)
        {
            ConstructIndices(indexsets, indexcounts);
        }

        /// <summary>
        /// Creates indexed geo from array of vertices specified with one subset of specified indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indices">Array with indices</param>
        public IndexedGeo(IVertexArray source, int[] indices) : base(source)
        {
            Indices = new int[1][];
            Indices[0] = indices;
            _currentSubset = 0;
        }

        /// <summary>
        /// Creates indexed geo from array of vertices and from indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indices">Array with indices</param>
        public IndexedGeo(IVertexArray source, int[][] indices) : base(source)
        {
            Indices = indices;
            _currentSubset = 0;
        }


        /// <summary>
        /// Constructs indices
        /// </summary>
        /// <param name="indexcount">Number of indices</param>
        protected void ConstructIndices(int indexcount)
        {
            Indices = new int[1][];
            Indices[0] = new int[indexcount];
            _currentSubset = 0;
        }

        /// <summary>
        /// Constructs indices
        /// </summary>
        ///<param name="indexsets">Number of index sets</param>
        /// <param name="indexcounts">Number of indices for all sets</param>
        protected void ConstructIndices(int indexsets, int[] indexcounts)
        {
            Indices = new int[indexsets][];
            _currentSubset = 0;
            for (int i = 0; i < indexsets; i++)
            {
                Indices[i] = new int[indexcounts[i]];
            }
        }

        /*
        /// <summary>
        /// Convert object to list of points
        /// </summary>
        /// <returns>New geometry object containing point based definition of the object</returns>
        /// <param name="quality">
        /// Quality for parametric objects (0-1). Zero is simples possible, 1 maximal for the current dimension of the object. 
        /// If vertexlimit parameter is used, quality will be reduced to fullfill maximal vertex budget
        /// </param>
        /// <param name="vertexlimit">Maximal number of allowed vertices. If set to zero, there's no limit. 
        /// Used for fully parametric objects or to reduce number of the vertices in complicated objects.</param>
        public abstract Point3DList ToPoints(float quality = 0, int vertexlimit = 0);

        /// <summary>
        /// Convert object to list of lines
        /// </summary>
        /// <returns>New geometry object containing edges of the object</returns>
        /// <param name="quality">
        /// Quality for parametric objects (0-1). Zero is simples possible, 1 maximal for the current dimension of the object. 
        /// If vertexlimit parameter is used, quality will be reduced to fullfill maximal vertex budget
        /// </param>
        /// <param name="vertexlimit">Maximal number of allowed vertices. If set to zero, there's no limit. 
        /// Used for fully parametric objects or to reduce number of the vertices in complicated objects.</param>
        public abstract LineList ToLines(float quality = 0, int vertexlimit = 0);
        /// <summary>
        /// Convert object to list of triangles. Valid only for surface based objects, otherwise returns null.
        /// </summary>
        /// <returns>New geometry object containing triangle faces of the object surface.</returns>
        /// <param name="quality">
        /// Quality for parametric objects (0-1). Zero is simples possible, 1 maximal for the current dimension of the object. 
        /// If vertexlimit parameter is used, quality will be reduced to fullfill maximal vertex budget
        /// </param>
        /// <param name="vertexlimit">Maximal number of allowed vertices. If set to zero, there's no limit. 
        /// Used for fully parametric objects or to reduce number of the vertices in complicated objects.</param>
        public abstract TriangleList ToTriangles(float quality = 0, int vertexlimit = 0);
        /// <summary>
        /// Convert object to indexed triangle mesh. Valid only for surface based objects, otherwise returns null.
        /// </summary>
        /// <returns>New geometry object containing triangle faces of the object surface</returns>
        /// <param name="quality">
        /// Quality for parametric objects (0-1). Zero is simples possible, 1 maximal for the current dimension of the object. 
        /// If vertexlimit parameter is used, quality will be reduced to fullfill maximal vertex budget
        /// </param>
        /// <param name="vertexlimit">Maximal number of allowed vertices. If set to zero, there's no limit. 
        /// Used for fully parametric objects or to reduce number of the vertices in complicated objects.</param>
        public abstract IndexedMesh ToIndexedMesh(float quality = 0, int vertexlimit = 0);
*/

        /// <summary>
        /// Reads one subset of the mesh from the XML
        /// </summary>
        /// <param name="reader">XML reader</param>
        /// <returns>Indices</returns>
        protected int[] ReadSubset(System.Xml.XmlReader reader)
        {
            List<int> rval = new List<int>();

            while (reader.Read())
            {
                if (reader.IsStartElement("Element"))
                {
                    for (int k = 0; k < IndicesPerElement; k++)
                    {
                        string attr = "i" + k.ToString();
                        string idx = reader[attr];

                        int id;
                        int.TryParse(idx, out id);
                        rval.Add(id);
                    }
                }
                else break;
            }

            return rval.ToArray();
        }

        /// <summary>
        /// Deserializes object from XML
        /// </summary>
        /// <param name="reader">XML reader</param>
        public override void ReadXml(System.Xml.XmlReader reader)
        {
            base.ReadXml(reader);
            //reader.Read();
            if (!reader.IsStartElement("Indices"))
            {
                return;
            }

            List<int[]> newind = new List<int[]>();

            while (reader.Read())
            {
                if (reader.IsStartElement("IndiceSubset"))
                {
                    int[] newsubs = ReadSubset(reader);
                    if (newsubs != null)
                        newind.Add(newsubs);
                }
                else break;
            }

            Indices = newind.ToArray();
            reader.ReadEndElement(); // indices
            reader.ReadEndElement();
        }

        /// <summary>
        /// Serializes object to XML
        /// </summary>
        /// <param name="writer">XML writer to save values</param>
        public override void WriteXml(System.Xml.XmlWriter writer)
        {
            base.WriteXml(writer);

            writer.WriteStartElement("Indices");

            //XmlSerializer intser = new XmlSerializer(

            for (int i = 0; i < Indices.Length; i++)
            {
                writer.WriteStartElement("IndiceSubset");

                int idx = 0;

                for (int j = 0; j < Indices[i].Length/IndicesPerElement; j++)
                {
                    writer.WriteStartElement("Element");

                    for (int k = 0; k < IndicesPerElement; k++)
                    {
                        writer.WriteAttributeString("i" + k.ToString(), Indices[i][idx].ToString());
                        idx++;
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }

            writer.WriteEndElement();
        }
    }

    public class IndexedLines : IndexedGeo, IGeoContainer<LineSegment3D>
    {

        /// <summary>
        /// Returns copy of the geometric data
        /// </summary>
        /// <returns>Full copy of the geometry</returns>
        public override IGeometry GetCopy()
        {
            return new IndexedLines(this);
        }


        /// <summary>
        /// XML reader constructor
        /// </summary>
        /// <param name="reader">XML reader</param>
        public IndexedLines(System.Xml.XmlReader reader)
            : base(reader)
        {
        }

        /// <summary>
        /// Copy constructor
        /// </summary>
        /// <param name="copy">Lines to copy</param>
        public IndexedLines(IndexedLines copy)
            : base(copy)
        {
        }
            


        public override PrimitiveTypes MeshType
        {
            get { return PrimitiveTypes.IndexedLines; }
        }

        public override int IndicesPerElement { get { return 2; } }

        #region constructors
        /// <summary>
        /// Creates indexed geo with default vertex format, with specified number of vertices, one subset with selected number of indices
        /// </summary>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexcount">Number of indices</param>
        public IndexedLines(int vertexcount, int indexcount) : base(vertexcount, indexcount) {}

        /// <summary>
        /// Creates indexed geo with default vertex format, with specified number of vertices, specified number of subset with selected number of indices
        /// </summary>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexsets">Number of subsets</param>
        /// <param name="indexcounts">Array with length of all subsets</param>
        public IndexedLines(int vertexcount, int indexsets, int[] indexcounts) : base(vertexcount, indexsets, indexcounts){}

        /// <summary>
        /// Creates indexed geo of specified format, with specified number of vertices, one subset and specified number of indices
        /// </summary>
        /// <param name="vertextype">Type of vertex (must be IVertex)</param>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexcount">Number of indices</param>
        public IndexedLines(Type vertextype, int vertexcount, int indexcount) :base(vertextype, vertexcount, indexcount){}

        /// <summary>
        /// Creates indexed geo of specified format, with specified number of vertices, specified number of subsets and specified number of indices
        /// </summary>
        /// <param name="vertextype">Type of vertex (must be IVertex)</param>
        /// <param name="vertexcount">Number of vertices</param>
        /// <param name="indexsets">Number of subsets</param>
        /// <param name="indexcounts">Array with length of all subsets</param>
        public IndexedLines(Type vertextype, int vertexcount, int indexsets, int[] indexcounts) : base(vertextype, vertexcount, indexsets, indexcounts){}

        /// <summary>
        /// Creates indexed geo from array of vertices one subset and specified number of indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indexcount">number of vertices</param>
        public IndexedLines(IVertexArray source, int indexcount) : base(source, indexcount) {}

        /// <summary>
        /// Creates indexed geo from array of vertices specified number of subsets and specified number of indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indexsets">Number of subsets</param>
        /// <param name="indexcounts">Array with length of all subsets</param>
        public IndexedLines(IVertexArray source, int indexsets, int[] indexcounts) : base(source, indexsets, indexcounts){}

        /// <summary>
        /// Creates indexed geo from array of vertices specified with one subset of specified indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indices">Array with indices</param>
        public IndexedLines(IVertexArray source, int[] indices) : base(source, indices){}

        /// <summary>
        /// Creates indexed geo from array of vertices and from indices
        /// </summary>
        /// <param name="source">Source vertex array</param>
        /// <param name="indices">Array with indices</param>
        public IndexedLines(IVertexArray source, int[][] indices) : base(source, indices) { }

        #endregion

        /// <summary>
        /// IndexedLineList is  primitive
        /// </summary>
        public override bool IsPrimitive
        {
            get { return true; }
        }

        /// <summary>
        /// IndexedLineList can work as a list of LineSegments
        /// </summary>
        public override bool IsContainer
        {
            get { return true; }
        }


        /// <summary>
        /// Returns closest distance from pos to one of the segments
        /// </summary>
        /// <param name="pos">position vector</param>
        /// <returns>closest distance</returns>
        public override float Distance(ref Vector3 pos)
        {
            float dst = float.MaxValue;
            for (int i = 0; i < Count; i++)
            {
                Vector3 line1 = GetPosition(i*2);
                Vector3 line2 = GetPosition(i * 2 + 1);
                float newdst = MathTools.DistanceVectorLineSegment(ref line1, ref line2, ref pos);
                if (newdst < dst)
                    dst = newdst;
            }
            return dst;
        }

        /// <summary>
        /// Returns closest distance to the ray
        /// </summary>
        /// <param name="ray">Ray to check distance to</param>
        /// <param name="frontOnly">Check only objects in front of the origin</param>
        /// <returns>Closest distance to the ray, if frontOnly and object is behind the ray, returns NaN</returns>
        public override float Distance(Ray ray, bool frontOnly = false)
        {
            float dst = float.MaxValue;
            for (int i = 0; i < Count; i++)
            {
                Vector3 line1 = GetPosition(i * 2);
                Vector3 line2 = GetPosition(i * 2 + 1);
                float newdst = ray.DistanceToLineSegment(ref line1, ref line2, frontOnly);
                if (newdst != float.NaN)
                {
                    if (newdst < dst)
                        dst = newdst;
                }
            }
            return dst;
        }

        /// <summary>
        /// Returns closest distance to the line segment. Generic, from center, OVERRIDE!
        /// </summary>
        ///<param name="pos1">Start of the line</param>
        ///<param name="pos2">end of the line</param>
        /// <returns>Closest distance</returns>
        public override float DistanceLineSegment(ref Vector3 pos1, ref Vector3 pos2)
        {
            float dst = float.MaxValue;
            for (int i = 0; i < Vertices.Count -1; i++)
            {
                Vector3 line1 = Vertices[i].Position;
                Vector3 line2 = Vertices[i + 1].Position;
                float newdst = MathTools.DistanceTwoLineSegments(ref line1, ref line2, ref pos1, ref pos2);
                if (newdst < dst)
                    dst = newdst;
            }
            return dst;
        }

        /// <summary>
        /// Returns closest distance to the triangle.
        /// </summary>
        /// <param name="pos1">First corner</param>
        /// <param name="pos2">Second corner</param>
        /// <param name="pos3">Third corner</param>
        /// <returns>Distance</returns>
        public override float DistanceTriangle(ref Vector3 pos1, ref Vector3 pos2, ref Vector3 pos3)
        {
            float dst = float.MaxValue;
            for (int i = 0; i < Vertices.Count - 1; i++)
            {
                Vector3 line1 = Vertices[i].Position;
                Vector3 line2 = Vertices[i + 1].Position;
                float newdst = MathTools.DistanceLineSegmentTriangle(ref line1, ref line2, ref pos1, ref pos2, ref pos3);
                if (newdst < dst)
                    dst = newdst;
            }
            return dst;
        }

        /// <summary>
        /// Returns closest distance to the sphere
        /// </summary>
        /// <param name="center">center of the sphere</param>
        /// <param name="radius">radius of the sphere</param>
        /// <returns>Closest distance</returns>
        public override float DistanceSphere(ref Vector3 center, float radius)
        {
            float dst = float.MaxValue;
            for (int i = 0; i < Vertices.Count - 1; i++)
            {
                Vector3 line1 = Vertices[i].Position;
                Vector3 line2 = Vertices[i + 1].Position;
                float newdst = MathTools.DistanceLineSegmentSphere(ref line1, ref line2, ref center, radius);
                if (newdst < dst)
                    dst = newdst;
            }
            return dst;
        }

        /// <summary>
        /// Returns closest distance from the generic geometric object
        /// </summary>
        /// <param name="obj">Object to check distance with</param>
        /// <returns>Closest distance to the object</returns>
        public override float Distance(IGeometry obj)
        {
            return obj.DistanceLines(this);
        }

        /// <summary>
        /// Checks if specified position is inside the object
        /// </summary>
        /// <param name="pos">Position to check</param>
        /// <returns>True if vector is inside the object</returns>
        public override bool ContainsPosition(Vector3 pos)
        {

            for (int i = 0; i < Count; i++)
            {
                if (MathTools.PointOnLineSegment(GetPosition(i*2), GetPosition(i*2+1), pos))
                    return true;
            }
            return false;
        }


        /// <summary>
        /// Check for intersection and fills intersection info if intersection is closer to the origin of the ray then value before
        /// </summary>
        /// <param name="inters">Data structure with intersection info</param>
        /// <param name="obj">Ray object</param>
        /// <returns>True if there was an intersection and it was closer then previous stored</returns>
        public override bool GetIntersectionInfo(Ray obj, ref IIntersectionInfo inters)
        {
            float dist;
            Vector3 point;
            bool rval = false;

            for (int i = 0; i < Count; i++)
            {
                if (MathTools.IntersectionRayLineSegment(obj.Origin, obj.Direction, GetPosition(i * 2), GetPosition(i * 2 + 1), out dist, out point))
                {
                    if (dist < inters.Distance)
                    {
                        inters.Distance = dist;
                        inters.IntersectionPoint = point;
                        inters.GeoObject = this;
                        rval = true;
                    }
                }
            }
            return rval;
        }

        /// <summary>
        /// Checks for intersection between object and moving sphere
        /// </summary>
        ///<param name="radius">Radius of the sphere</param>
        /// <param name="maxdistance">Maximal distance to travel</param>
        /// <param name="ray">Ray describing movement of the sphere</param>
        /// <returns>Distance to the intersection or -1 if no intersection exists</returns>
        public override float IntersectsMoving(float radius, Ray ray, float maxdistance)
        {
            Vector3 targ = Vector3.MoveInDirection(ref ray.Origin, ref ray.Direction, maxdistance);
            float t;

            float mindist = float.MaxValue;

            for (int i = 0; i < Count; i++)
            {
                Vector3 me0 = GetPosition(i * 2);
                Vector3 me1 = GetPosition(i * 2 + 1);

                if (MathTools.IntersectionSegmentCapsule(ref me0, ref me1, ref ray.Origin, ref targ, radius, out t))
                {
                    float newdst = t * maxdistance;
                    mindist = MathTools.Min(mindist, newdst);
                }
            }
            if (mindist == float.MaxValue)
                return -1;
            return mindist;
        }

        #region Conversions

        /// <summary>
        /// IndexedLineList prefers linelist
        /// </summary>
        public override PrimitiveTypes PreferredPrimitive
        {
            get { return PrimitiveTypes.LineList; }
        }

        /// <summary>
        /// Convert object to list of points
        /// </summary>
        /// <returns>New geometry object containing point based definition of the object</returns>
        /// <param name="quality">
        /// Quality for parametric objects (0-1). Zero is simples possible, 1 maximal for the current dimension of the object. 
        /// If vertexlimit parameter is used, quality will be reduced to fullfill maximal vertex budget
        /// </param>
        /// <param name="VertexType">Required vertex type</param>
        /// <param name="vertexlimit">Maximal number of allowed vertices. If set to zero, there's no limit. 
        /// Used for fully parametric objects or to reduce number of the vertices in complicated objects.</param>
        public override Point3DList ToPoints(Type VertexType, float quality = 0, int vertexlimit = 0)
        {
            return new Point3DList(VertexType, Vertices);
        }

        /// <summary>
        /// Convert object to list of lines - returns self
        /// </summary>
        /// <returns>New geometry object containing edges of the object</returns>
        /// <param name="quality">
        /// Quality for parametric objects (0-1). Zero is simples possible, 1 maximal for the current dimension of the object. 
        /// If vertexlimit parameter is used, quality will be reduced to fullfill maximal vertex budget
        /// </param>
        /// <param name="VertexType">Required vertex type</param>
        /// <param name="vertexlimit">Maximal number of allowed vertices. If set to zero, there's no limit. 
        /// Used for fully parametric objects or to reduce number of the vertices in complicated objects.</param>
        public override LineList ToLines(Type VertexType, float quality = 0, int vertexlimit = 0)
        {
            IVertexArray varray = VertexFactory.CreateArray(VertexType, Count * 2);

            int idx = 0;
            for (int i = 0; i < Count; i++)
            {
                varray[idx] = GetVertex(i * 2);
                varray[idx+1] = GetVertex(i*2+1);
                idx += 2;
            }

            return new LineList(varray);
        }

        /// <summary>
        /// Linelist can't be converted to triangles, returns null
        /// </summary>
        /// <param name="VertexType">unused</param>
        /// <param name="quality">unused</param>
        /// <param name="vertexlimit">unused</param>
        public override TriangleList ToTriangles(Type VertexType, float quality = 0, int vertexlimit = 0)
        {
            return null;
        }

        /// <summary>
        /// Linelist can't be converted to triangles, returns null
        /// </summary>
        /// <param name="VertexType">unused</param>
        /// <param name="quality">unused</param>
        /// <param name="vertexlimit">unused</param>
        public override IndexedMesh ToIndexedMesh(Type VertexType, float quality = 0, int vertexlimit = 0)
        {
            return null;
        }

        #endregion

        #region IGeoContainer<LineSegment3D> Members

        public LineSegment3D this[int index]
        {
            get
            {
                return new LineSegment3D(GetVertex(index*2), GetVertex(index*2+1));
            }
            set
            {
                this.Vertices[index * 2] = value.Vertices[0];
                this.Vertices[index * 2 + 1] = value.Vertices[1];
            }
        }

        public int Count
        {
            get { return CurrentIndices.Length/2; }
        }

        /// <summary>
        /// LineList is fixed array, can't add, doesn't do anything
        /// </summary>
        /// <param name="geoobject"></param>
        public void Add(LineSegment3D geoobject)
        {            
        }

        #endregion

        #region IEnumerable<IGeometry> Members

        public IEnumerator<IGeometry> GetEnumerator()
        {
            return new GeoEnumerator<LineSegment3D>(this);
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Vertices.GetEnumerator(); //???
        }

        #endregion

    }



}
