public List <List <Point2d <T> > > Geometry <T>(
            uint?clipBuffer = null
            , float?scale   = null
            )
        {
            // parameters passed to this method override parameters passed to the constructor
            if (_clipBuffer.HasValue && !clipBuffer.HasValue)
            {
                clipBuffer = _clipBuffer;
            }
            if (_scale.HasValue && !scale.HasValue)
            {
                scale = _scale;
            }

            // TODO: how to cache 'finalGeom' without making whole class generic???
            // and without using an object (boxing) ???
            List <List <Point2d <T> > > finalGeom = _cachedGeometry as List <List <Point2d <T> > >;

            if (null != finalGeom && scale == _previousScale)
            {
                return(finalGeom);
            }

            //decode commands and coordinates
            List <List <Point2d <long> > > geom = DecodeGeometry.GetGeometry(
                _layer.Extent
                , GeometryType
                , GeometryCommands
                , scale.Value
                );

            if (clipBuffer.HasValue)
            {
                geom = UtilGeom.ClipGeometries(geom, GeometryType, (long)_layer.Extent, clipBuffer.Value, scale.Value);
            }

            //HACK: use 'Scale' to convert to <T> too
            finalGeom = DecodeGeometry.Scale <T>(geom, scale.Value);

            //set field needed for next iteration
            _previousScale  = scale;
            _cachedGeometry = finalGeom;

            return(finalGeom);
        }
Ejemplo n.º 2
0
        public List <List <Vector2 <T> > > Geometry <T>(
            uint?clipBuffer = null
            , float?scale   = null
            )
        {
            // parameters passed to this method override parameters passed to the constructor
            if (_clipBuffer.HasValue && !clipBuffer.HasValue)
            {
                clipBuffer = _clipBuffer;
            }

            if (_scale.HasValue && !scale.HasValue)
            {
                scale = _scale;
            }

            // TODO: how to cache 'finalGeom' without making whole class generic???
            // and without using an object (boxing) ???
            var finalGeom = _cachedGeometry as List <List <Vector2 <T> > >;

            if (null != finalGeom && scale == _previousScale)
            {
                return(finalGeom);
            }

            //decode commands and coordinates
            List <List <Vector2 <long> > > geom = DecodeGeometry.GetGeometry(
                Layer.Extent
                , GeometryType
                , GeometryCommands
                , scale.Value
                );

            if (clipBuffer.HasValue)
            {
                // HACK !!!
                // work around a 'feature' of clipper where the ring order gets mixed up
                // with multipolygons containing holes
                if (geom.Count < 2 || GeometryType != GeomType.POLYGON)
                {
                    // work on points, lines and single part polygons as before
                    geom = UtilGeom.ClipGeometries(geom, GeometryType, (long)Layer.Extent, clipBuffer.Value,
                                                   scale.Value);
                }
                else
                {
                    // process every ring of a polygon in a separate loop
                    var newGeom   = new List <List <Vector2 <long> > >();
                    int geomCount = geom.Count;
                    for (int i = 0; i < geomCount; i++)
                    {
                        List <Vector2 <long> > part = geom[i];
                        var tmp = new List <List <Vector2 <long> > >();
                        // flip order of inner rings to look like outer rings
                        bool isInner = signedPolygonArea(part) >= 0;
                        if (isInner)
                        {
                            part.Reverse();
                        }

                        tmp.Add(part);
                        tmp = UtilGeom.ClipGeometries(tmp, GeometryType, (long)Layer.Extent, clipBuffer.Value,
                                                      scale.Value);
                        // ring was completely outside of clip border
                        if (0 == tmp.Count)
                        {
                            continue;
                        }

                        // one part might result in several geoms after clipping, eg 'u'-shape where the
                        // lower part is completely beyond the actual tile border but still within the buffer
                        foreach (List <Vector2 <long> > item in tmp)
                        {
                            // flip winding order of inner rings back
                            if (isInner)
                            {
                                item.Reverse();
                            }

                            newGeom.Add(item);
                        }
                    }

                    geom = newGeom;
                }
            }

            //HACK: use 'Scale' to convert to <T> too
            finalGeom = DecodeGeometry.Scale <T>(geom, scale.Value);

            //set field needed for next iteration
            _previousScale  = scale;
            _cachedGeometry = finalGeom;

            return(finalGeom);
        }