private static IGeometry BuildGeometry(string s, ISpatialReference spatialReference)
        {
            var wkt = new WktText(s);

            switch (wkt.Type)
            {
                case WktType.None:
                    return null;
                case WktType.Point:
                    return BuildPoint(wkt, spatialReference);
                case WktType.LineString:
                    return BuildPolyline(wkt, spatialReference);
                case WktType.Polygon:
                    return BuildPolygon(wkt, spatialReference);
                case WktType.Triangle:
                    return BuildPolygon(wkt, spatialReference);
                case WktType.PolyhedralSurface:
                    return BuildMultiPatch(wkt, spatialReference);
                case WktType.Tin:
                    return BuildMultiPolygon(wkt, spatialReference);
                case WktType.MultiPoint:
                    return BuildMultiPoint(wkt, spatialReference);
                case WktType.MultiLineString:
                    return BuildMultiPolyline(wkt, spatialReference);
                case WktType.MultiPolygon:
                    return BuildMultiPolygon(wkt, spatialReference);
                case WktType.GeometryCollection:
                    return BuildGeometryCollection(wkt, spatialReference);
                default:
                    throw new ArgumentOutOfRangeException("s", "Unsupported geometry type: " + wkt.Type);
            }
        }
        private static IGeometry BuildGeometryCollection(WktText wkt, ISpatialReference spatialReference)
        {
            var geometryBag = (IGeometryCollection)new GeometryBagClass();
            if (spatialReference != null)
                ((IGeometryBag)geometryBag).SpatialReference = spatialReference;

            foreach (var geomToken in wkt.Token.Tokens)
            {
                var geom = BuildGeometry(geomToken.ToString(), spatialReference);
                geometryBag.AddGeometry(geom);
            }
            var geometry = geometryBag as IGeometry;
            MakeZmAware(geometry, wkt.HasZ, wkt.HasM);
            return geometry;
        }
        private static IGeometry BuildMultiPatch(WktText wkt, ISpatialReference spatialReference)
        {
            var multiPatch = (IGeometryCollection)new MultiPatchClass();
            if (spatialReference != null)
                ((IGeometry)multiPatch).SpatialReference = spatialReference;

            foreach (var polygonString in wkt.Token.Tokens)
            {
                bool isOuter = true;
                foreach (var ringString in polygonString.Tokens)
                {
                    var ring = BuildRing(ringString, wkt, spatialReference);
                    multiPatch.AddGeometry(ring);
                    ((IMultiPatch)multiPatch).PutRingType(ring, isOuter
                                                                  ? esriMultiPatchRingType.esriMultiPatchOuterRing
                                                                  : esriMultiPatchRingType.esriMultiPatchInnerRing);
                    isOuter = false;
                }
            }
            ((ITopologicalOperator)multiPatch).Simplify();
            var geometry = multiPatch as IGeometry;
            MakeZmAware(geometry, wkt.HasZ, wkt.HasM);
            return geometry;
        }
        private static IGeometry BuildPolyline(WktText wkt, ISpatialReference spatialReference)
        {
            var multiPath = (IGeometryCollection)new PolylineClass();
            if (spatialReference != null)
                ((IGeometry)multiPath).SpatialReference = spatialReference;

            var path = BuildPath(wkt.Token, wkt, spatialReference);
            ((ITopologicalOperator)multiPath).Simplify();
            multiPath.AddGeometry(path);
            var geometry = multiPath as IGeometry;
            MakeZmAware(geometry, wkt.HasZ, wkt.HasM);
            return geometry;
        }
        private static IRing BuildRing(WktToken token, WktText wkt, ISpatialReference spatialReference)
        {
            var ring = (IPointCollection)new RingClass();
            if (spatialReference != null)
                ((IGeometry)ring).SpatialReference = spatialReference;

            foreach (var point in token.Tokens)
            {
                ring.AddPoint(BuildPoint(point, wkt, spatialReference));
            }
            MakeZmAware((IGeometry)ring, wkt.HasZ, wkt.HasM);
            return (IRing)ring;
        }
        private static IGeometry BuildPolygon(WktText wkt, ISpatialReference spatialReference)
        {
            var multiRing = (IGeometryCollection)new PolygonClass();
            if (spatialReference != null)
                ((IGeometry)multiRing).SpatialReference = spatialReference;

            foreach (var ringString in wkt.Token.Tokens)
            {
                var ring = BuildRing(ringString, wkt, spatialReference);
                multiRing.AddGeometry(ring);
            }
            ((ITopologicalOperator)multiRing).Simplify();
            var geometry = multiRing as IGeometry;
            MakeZmAware(geometry, wkt.HasZ, wkt.HasM);
            return geometry;
        }
        private static IPoint BuildPoint(WktToken token, WktText wkt, ISpatialReference spatialReference)
        {
            var coordinates = token.Coords.ToArray();

            int partCount = coordinates.Length;
            if (!wkt.HasZ && !wkt.HasM && partCount != 2)
                throw new ArgumentException("Mal-formed WKT, wrong number of elements, expecting x and y");
            if (wkt.HasZ && !wkt.HasM && partCount != 3)
                throw new ArgumentException("Mal-formed WKT, wrong number of elements, expecting x y z");
            if (!wkt.HasZ && wkt.HasM && partCount != 3)
                throw new ArgumentException("Mal-formed WKT, wrong number of elements, expecting x y m");
            if (wkt.HasZ && wkt.HasM && partCount != 4)
                throw new ArgumentException("Mal-formed WKT, wrong number of elements, expecting x y z m");

            var point = (IPoint)new PointClass();
            if (spatialReference != null)
                point.SpatialReference = spatialReference;

            point.PutCoords(coordinates[0], coordinates[1]);

            if (wkt.HasZ)
                point.Z = coordinates[2];
            if (wkt.HasM && !wkt.HasZ)
                point.M = coordinates[2];
            if (wkt.HasZ && wkt.HasM)
                point.M = coordinates[3];

            MakeZmAware(point, wkt.HasZ, wkt.HasM);
            return point;
        }
 private static IGeometry BuildPoint(WktText wkt, ISpatialReference spatialReference)
 {
     return BuildPoint(wkt.Token, wkt, spatialReference);
 }
        private static IPath BuildPath(WktToken token, WktText wkt, ISpatialReference spatialReference)
        {
            var path = (IPointCollection)new PathClass();
            if (spatialReference != null)
                ((IGeometry)path).SpatialReference = spatialReference;

            foreach (var point in token.Tokens)
            {
                path.AddPoint(BuildPoint(point, wkt, spatialReference));
            }
            var geometry = path as IGeometry;
            MakeZmAware(geometry, wkt.HasZ, wkt.HasM);
            return (IPath)path;
        }
        private static IGeometry BuildMultiPoint(WktText wkt, ISpatialReference spatialReference)
        {
            var multiPoint = (IPointCollection)new MultipointClass();
            if (spatialReference != null)
                ((IGeometry)multiPoint).SpatialReference = spatialReference;

            foreach (var point in wkt.Token.Tokens)
            {
                multiPoint.AddPoint(BuildPoint(point, wkt, spatialReference));
            }
            ((ITopologicalOperator)multiPoint).Simplify();
            var geometry = multiPoint as IGeometry;
            MakeZmAware(geometry, wkt.HasZ, wkt.HasM);
            return geometry;
        }