public static ProjectBoreholeResult ProjectBoreholes(List<Tuple<Borehole, IMapPoint>> input,
            IPolyline projLine, GeoProjSettings geoProjSettings)
        {
            if (input == null || projLine == null)
                return null;

            // remove the boreholes that do not have geology infos,
            // so called 'empty' boreholes
            //
            input.RemoveAll(x =>
                x.Item1.Geologies == null || x.Item1.Geologies.Count == 0
                || x.Item1.Top == x.Item1.Base);

            // sort the boreholes according to their projected position on the projection line
            //
            List<ProjectedBorehole> sortedList = new List<ProjectedBorehole>();
            foreach (var tuple in input)
            {
                Borehole bh = tuple.Item1;
                IMapPoint p = tuple.Item2;

                double distance = 0;
                IMapPoint prjPnt = null;
                bool canProject = GeomUtil.ProjectPointToPolyline(p,
                    projLine.GetPoints(), ref distance, ref prjPnt);
                if (geoProjSettings.clipInProjectionLine == true && canProject == false)
                    continue;

                distance /= geoProjSettings.scale;
                distance += geoProjSettings.xOffset;
                ProjectedBorehole prjBorehole = new ProjectedBorehole();
                prjBorehole.Borehole = bh;
                prjBorehole.Distance = distance;
                prjBorehole.Pos = p;
                sortedList.Add(prjBorehole);
            }
            if (sortedList.Count == 0)
                return null;

            sortedList.Sort((x, y) => x.Distance.CompareTo(y.Distance));

            // extend borholes to same depth
            //
            if (geoProjSettings.extendBorehole)
            {
                ExtendBoreholes(input);
            }

            // perform the projection
            //
            ProjectBoreholeResult result = new ProjectBoreholeResult();

            List<STGraphic> stResults = new List<STGraphic>();
            ProjectedBorehole previousBh = null;
            foreach (ProjectedBorehole projectedBorehole in sortedList)
            {
                Borehole bh = projectedBorehole.Borehole;

                // draw strata
                if (geoProjSettings.drawStratum)
                {
                    if (previousBh == null)
                    {
                        previousBh = projectedBorehole;
                    }
                    else
                    {
                        List<STGraphic> stGraphics = LinkBorehole(
                            previousBh.Borehole, projectedBorehole.Borehole,
                            previousBh.Distance, projectedBorehole.Distance,
                            geoProjSettings.zScale);
                        previousBh = projectedBorehole;
                        stResults.AddRange(stGraphics);
                    }
                }

                // draw borehole
                if (geoProjSettings.drawBorehole)
                {
                    IGraphicCollection gc = ProjectBorehole(bh,
                        projectedBorehole.Distance, geoProjSettings.zScale);
                    result.bhGraphics[bh.id] = gc;
                }
            }

            // transfrom strata results
            foreach (STGraphic stGraphic in stResults)
            {
                int id = stGraphic.StratumID;
                if (result.stGraphics.ContainsKey(id))
                {
                    IGraphicCollection gc = result.stGraphics[id];
                    gc.Add(stGraphic.Graphic);
                }
                else
                {
                    IGraphicCollection gc = NewGraphicCollection();
                    gc.Add(stGraphic.Graphic);
                    result.stGraphics[id] = gc;
                }
            }

            // calculate extent
            IEnvelope ext = null;
            foreach (IGraphicCollection gc in result.bhGraphics.Values)
            {
                IEnvelope itemExt = GraphicsUtil.GetGraphicsEnvelope(gc);
                if (ext == null)
                    ext = itemExt;
                else
                    ext = ext.Union(itemExt);
            }
            result.Extent = ext;

            return result;
        }
 static int CompareProjectedBorehole(ProjectedBorehole projectedBh1,
     ProjectedBorehole projectedBh2)
 {
     return projectedBh1.Distance.CompareTo(projectedBh2.Distance);
 }