/// <summary>
        /// 打开一张扫描切片
        /// </summary>
        /// <param name="path"></param>
        /// <param name="info">输出. 封装了切片信息</param>
        /// <returns>切片的宽高 (slideW, slideH) </returns>
        public void Open(string path, object info)
        {
            if (!(info is SceneGeometry))
            {
                throw new InvalidOperationException("Info is not MapGeometry type.");
            }
            if (OpenSlideImage.DetectFormat(path) == null)
            {
                throw new InvalidOperationException($"<<{path}>> is NOT a digital slide!");
            }
            slide = OpenSlideImage.Open(path);
            SceneGeometry sg = info as SceneGeometry;

            sg.Init();
            sg.SlideW = (int)slide.Width;
            sg.SlideH = (int)slide.Height;
            sg.L      = 0;
            sg.X      = sg.SlideW / 2;
            sg.Y      = sg.SlideH / 2;
            sg.NumL   = slide.LevelCount;
            for (int i = 0; i < sg.NumL; ++i)
            {
                sg.SetDensityAtLevel(i, slide.GetLevelDownsample(i));
            }
            thumbJpgBuf = slide.GetThumbnailAsJpeg(1024, 90);
        }
        public List <Drawable> LoadRegionShapes(SceneGeometry sg)
        {
            double left, top, right, bottom;

            (left, top, right, bottom) = (sg.X, sg.Y, sg.X + sg.ToActualPixel(sg.OutW), sg.Y + sg.ToActualPixel(sg.OutH));
            //Console.WriteLine($"Loading w={right - left}(from {left} to {right}), h={bottom - top}(from {top} to {bottom})");
            var toShow = new List <Drawable>();

            foreach (var _ in polylines)
            {
                var id = _.Key;
                var pl = _.Value;

                if (pl.NumPoints == 1)
                {
                    double x, y;
                    (x, y) = (pl.Points[0].Item1, pl.Points[0].Item2);

                    if (Graphics.EncodePoint(left, top, right, bottom, x, y) == 0)
                    {
                        toShow.Add(new Point(x - left, y - top, id));
                    }
                }
                else if (pl.NumPoints > 1)
                {
                    for (int i = 0; i < pl.NumPoints - 1; i = i + 1)
                    {
                        double xa, ya, xb, yb;
                        (xa, ya, xb, yb) = (pl.Points[i].Item1, pl.Points[i].Item2, pl.Points[i + 1].Item1, pl.Points[i + 1].Item2);

                        Graphics.ClipByWindow(
                            left, top, right, bottom,
                            xa, ya, xb, yb,
                            out double x1, out double y1, out double x2, out double y2
                            );
                        //Console.WriteLine($"Rectangle({left - left:0.0}, {top - top:0.0}, {right - left:0.0}, {bottom - top:0.0}) " +
                        //    $"Cut({xa - left:0.0}, {ya - top:0.0} -> {xb - left:0.0}, {yb - top:0.0}), " +
                        //    $"Yield({x1 - left:0.0}, {y1 - top:0.0} -> {x2 - left:0.0}, {y2 - top:0.0})");

                        if (!double.IsNaN(x1))
                        {
                            if (x1 == y1 && x2 == y2)
                            {
                                toShow.Add(new Point(x1 - left, y1 - top, id));
                            }
                            else
                            {
                                toShow.Add(new LineSegment(x1 - left, y1 - top, x2 - left, y2 - top, id));
                            }
                        }
                    }
                }
            }

            return(toShow);
        }
 public void CopyFrom(SceneGeometry sg)
 {
     (X, Y, L, NumL, OutW, OutH, SlideW, SlideH) =
         (sg.X, sg.Y, sg.L, sg.NumL,
          sg.OutW, sg.OutH, sg.SlideW, sg.SlideH);
     if (pixelDensity == null)
     {
         pixelDensity = new double[BUFLEN];
     }
     Array.Copy(sg.pixelDensity, pixelDensity, BUFLEN);
 }
 /// <summary>
 /// 根据sg所描述的位置、大小和倍率, 读取一个区域
 /// </summary>
 /// <param name="sg"></param>
 /// <returns></returns>
 public byte[] LoadRegionBMP(SceneGeometry sg)
 {
     Helper.InitBgraHeader(imgBmpBuf, (int)sg.OutW, (int)sg.OutH);
     slide.DangerousReadRegion(sg.L, (int)sg.X, (int)sg.Y, (int)sg.OutW, (int)sg.OutH, ref imgBmpBuf[Helper.BMP_BGRA_DATA_OFFSET]);
     return(imgBmpBuf);
 }
 public void Update(SceneGeometry sg)
 {
     X = sg.X; Y = sg.Y;
     L = sg.L; OutW = sg.L; OutH = sg.OutH;
 }
 public SceneGeometry(SceneGeometry sg)
 {
     CopyFrom(sg);
 }