//public void Dispose()
 //{
 //}
 public MouseController(PointingDeviceCollection pd, Dock d, ScrollBar sB, SystemState st, PhotoDisplay photoDisplay, StrokeBoxCollection s, KeyboardDevice key)
 {
     dock = d;
     sBar = sB;
     //pdCollection = pdc;
     strokeGroup = s;
     systemState = st;
     photoDisplayManager = photoDisplay;
     //rawInputForm_ = new RawInputForm();
     pdCollection = pd;
     keyboard = key;
 }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            float MinPhotoSize = SystemParameter.MinPhotoScale(SystemParameter.ClientWidth, SystemParameter.ClientHeight, ResourceManager.MAXX, ResourceManager.MAXY, photos.Count);
            //MinPhotoSize = 0f;// ムービー用
            float MaxPhotoSize = SystemParameter.MaxPhotoScale(SystemParameter.ClientWidth, SystemParameter.ClientHeight, ResourceManager.MAXX, ResourceManager.MAXY, photos.Count);

            weight_ = weight.ScaleWeight;

            // アトラクター選択
            foreach (Photo a in photos)
            {
                // スケール速度
                float ds = 0;

                // added by Gengdai
                realMinScale = a.GetTexture().Width > a.GetTexture().Height ? MinPhotoSize * ResourceManager.MAXX / a.GetTexture().Width : MinPhotoSize * ResourceManager.MAXY / a.GetTexture().Height;
                realMaxScale = a.GetTexture().Width > a.GetTexture().Height ? MaxPhotoSize * ResourceManager.MAXX / a.GetTexture().Width : MaxPhotoSize * ResourceManager.MAXY / a.GetTexture().Height;
                followMinScale = realMinScale * 5f;
                if (followMinScale > realMaxScale)
                    followMinScale = realMaxScale;
                // 重ならないように制約
                if (a.Adjacency.Count == 0)
                {
                    // 周りに画像がなければMaxPhotoSizeまで拡大させる
                    ds += (realMaxScale - a.Scale) * 0.01f * weight_;
                }

                // サイズがMinPhotoSize以下もしくはMaxPhotoSize以上になるのを防ぐ制約
                if (a.IsFollowing && a.Scale < followMinScale)
                {
                    ds += (followMinScale - a.Scale) * 0.02f * weight_;
                }
                else if (!a.IsFollowing && a.Scale < realMinScale)
                {
                    ds += (realMinScale - a.Scale) * 0.02f * weight_;
                }
                else if (a.Scale > realMaxScale)
                {
                    ds -= (a.Scale - realMaxScale) * 0.02f * weight_;
                }

                //ノイズを付加する
                if (false)
                {
                    float variance = weight.NoiseWeight * 0.2f;
                    float noise = (float)randbm.NextDouble(variance);
                    ds += noise;
                }

                a.AddScale(ds);
            }
        }
 public PhotoDisplay(SystemState st, Dock d, ScrollBar s, StrokeBoxCollection str)
 {
     systemState = st;
     dock = d;
     sBar = s;
     strokes = str;
     //photos = p;
     weight = new AttractorWeight(
         NonOverlapWeight,
         ScaleWeight,
         AttractToMouseWeight,
         ScaleUpMouseWeight,
         TagWeight,
         NoiseWeight);
 }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            float MinPhotoSize = SystemParameter.MinPhotoScale(SystemParameter.ClientWidth, SystemParameter.ClientHeight, ResourceManager.MAXX, ResourceManager.MAXY, photos.Count) * 5;
            float MaxPhotoSize = SystemParameter.MaxPhotoScale(SystemParameter.ClientWidth, SystemParameter.ClientHeight, ResourceManager.MAXX, ResourceManager.MAXY, photos.Count) * 2;

            weight_ = weight.ScaleUpMouseWeight;
            // アトラクター選択
            foreach (Photo a in activePhotos)
            {
                float ds = 0; // スケール

                // added by Gengdai
                realMinScale = a.GetTexture().Width > a.GetTexture().Height ? MinPhotoSize * ResourceManager.MAXX / a.GetTexture().Width : MinPhotoSize * ResourceManager.MAXY / a.GetTexture().Height;
                realMaxScale = a.GetTexture().Width > a.GetTexture().Height ? MaxPhotoSize * ResourceManager.MAXX / a.GetTexture().Width : MaxPhotoSize * ResourceManager.MAXY / a.GetTexture().Height;

                // マウスに重なっているほど大きくしたい
                //if (a.IsGazeds)
                {
                    ds += (realMaxScale - a.Scale) * weight_ * 0.05f;
                    // サイズが最小値以下もしくは最大値以上になるのを防ぐ制約
                    if (a.Scale < realMinScale)
                    {
                        ds += (realMinScale - a.Scale) * weight_ * 0.01f;
                    }
                    else if (a.Scale > realMaxScale)
                    {
                        ds -= (a.Scale - realMaxScale) * weight_ * 0.01f;
                    }
                    // ノイズを付加する
                    if (false)
                    {
                        float variance = weight.NoiseWeight * 0.2f;
                        float noise = (float)randbm.NextDouble(variance);
                        ds += noise;
                    }
                }

                a.AddScale(ds);
            }
        }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            float MinPhotoSize = SystemParameter.MinPhotoScale(SystemParameter.ClientWidth, SystemParameter.ClientHeight, ResourceManager.MAXX, ResourceManager.MAXY, photos.Count);
            //MinPhotoSize = 0f;// for movie
            float MaxPhotoSize = SystemParameter.MaxPhotoScale(SystemParameter.ClientWidth, SystemParameter.ClientHeight, ResourceManager.MAXX, ResourceManager.MAXY, photos.Count);

            weight_ = weight.ScaleWeight;

            foreach (Photo a in photos)
            {
                // big scale velocity
                float ds = 0;

                // added by Gengdai
                realMinScale = a.GetTexture().Width > a.GetTexture().Height ? MinPhotoSize * ResourceManager.MAXX / a.GetTexture().Width : MinPhotoSize * ResourceManager.MAXY / a.GetTexture().Height;
                realMaxScale = a.GetTexture().Width > a.GetTexture().Height ? MaxPhotoSize * ResourceManager.MAXX / a.GetTexture().Width : MaxPhotoSize * ResourceManager.MAXY / a.GetTexture().Height;
                aPhotoArea = a.Scale * a.GetTexture().Width * a.Scale * a.GetTexture().Height;

                // restraint to avoid overlapping
                if (a.Adjacency.Count > 0)
                {
                    foreach (AdjacentPhoto b in a)
                    {
                        bPhotoArea = b.Photo.Scale * b.Photo.GetTexture().Width * b.Photo.Scale * b.Photo.GetTexture().Height;

                        // avoid overlapping, decrease MinPhotoSize
                        if (bPhotoArea < aPhotoArea)
                        {
                            if (a.IsGazeds && b.Photo.IsGazeds)
                            {
                                ds -= (a.Scale - realMinScale) * 0.1f * weight_;
                            }
                            else
                            {
                                ds -= (a.Scale - realMinScale) * 0.01f * weight_;
                            }
                        }
                    }
                }

                // avoid MinPhotoSize getting bigger than MaxPhotoSize
                if (a.Scale < realMinScale)
                {
                    ds += (realMinScale - a.Scale) * 0.02f * weight_;
                }
                else if (a.Scale > realMaxScale)
                {
                    ds -= (a.Scale - realMaxScale) * 0.02f * weight_;
                }

                // add noise
                if (false)
                {
                    float variance = weight.NoiseWeight * 0.2f;
                    float noise = (float)randbm.NextDouble(variance);
                    ds += noise;
                }

                a.AddScale(ds);
            }
        }
Exemple #6
0
 public void invokeAttractorSelection(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
 {
     for (int i = 0, size = Attractors.Length; i < size; ++i)
     {
         if ((attractor_ & (1 << i)) != 0)
         {
             Attractors[i].select(dock, sBar, weight, photos, activePhotos, strokes, systemState);
         }
     }
 }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            weight_ = weight.NonOverlapWeight;

            foreach (Photo a in photos)
            {
                //velocity
                Vector2 v = Vector2.Zero;

                //avoid photo going out of the window(strong constraint)
            #if NO_ROTATION
                if (systemState.curState != SystemState.ATTRACTOR_TIME)
                {
                    if (a.BoundingBox.Min.X < dock.DockBoundX)
                    {
                        v.X -= (a.BoundingBox.Min.X - dock.DockBoundX);
                    }
                    if (a.BoundingBox.Max.X > SystemParameter.ClientWidth)
                    {
                        v.X -= (a.BoundingBox.Max.X - SystemParameter.ClientWidth);
                    }
                }
                if (a.BoundingBox.Min.Y < 0)
                {
                    v.Y -= (a.BoundingBox.Min.Y);
                }
                if (a.BoundingBox.Max.Y > SystemParameter.ClientHeight)
                {
                    v.Y -= (a.BoundingBox.Max.Y - SystemParameter.ClientHeight);
                }
                v *= 0.02f * INTO_DISPLAY * weight_;
            #else
                float va = 0f;
                for (int i = 0; i < 4; ++i)
                {
                    Vector2 v1 = a.Position - a.BoudingBox.Vertex[i];
                    v1.Normalize();
                    Vector2 v2 = Vector2.Zero;
                    float dist = 0f;
                    if (a.BoudingBox.Vertex[i].X < input.DockBound)
                    {
                        v2 = Vector2.UnitX;
                        dist = input.DockBound - a.BoudingBox.Vertex[i].X ;
                    }
                    if (a.BoudingBox.Vertex[i].X > input.WindowWidth)
                    {
                        v2 = -Vector2.UnitX;
                        dist = a.BoudingBox.Vertex[i].X - input.WindowWidth;
                    }
                    if (a.BoudingBox.Vertex[i].Y < 0)
                    {
                        v2 = Vector2.UnitY;
                        dist = -a.BoudingBox.Vertex[i].Y;
                    }
                    if (a.BoudingBox.Vertex[i].Y > input.WindowHeight)
                    {
                        v2 = -Vector2.UnitY;
                        dist = a.BoudingBox.Vertex[i].Y - input.WindowHeight;
                    }
                    //v += v1 * (float)(dist * Math.Abs(v1.X * v2.X + v1.Y * v2.Y));
                    v += dist * v2;
                    va += -(v1.X * v2.Y - v1.Y * v2.X) * INTO_DISPLAY;
                }
                v *= 0.02f * INTO_DISPLAY * weight_;
            #endif

                // add noise
                if (true)
                {
                    float variance = weight.NoiseWeight * 0.5f;
                    Vector2 noise = new Vector2((float)randbm.NextDouble(variance), (float)randbm.NextDouble(variance));
                    v += noise;
                }
                a.AddPosition(v);
            #if NO_ROTATION
            #else
                if (input.EnabledNoise)
                {
                    float variance = weight.NoiseWeight * 0.1f;
                    float noise = (float)randbm.NextDouble(variance);
                    va += noise;
                }
                a.AddAngle(va);
            #endif
            }
        }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            weight_ = weight.NonOverlapWeight;
            // 最も古い写真と新しい写真の撮影日時を取得
            DateTime mindt = DateTime.MaxValue;
            DateTime maxdt = DateTime.MinValue;
            foreach (Photo a in photos)
            {
                if (mindt > a.ptag.CapturedDate)
                {
                    mindt = a.ptag.CapturedDate;
                }
                if (maxdt < a.ptag.CapturedDate)
                {
                    maxdt = a.ptag.CapturedDate;
                }
            }
            sBar.Oldest = mindt;
            sBar.Newest = maxdt;
            // ウインドウ表示範囲内で最も古い写真と新しい写真の撮影日時を指定
            double max = maxdt.Subtract(mindt).TotalSeconds;
            double minw = max * (double)sBar.Min / (double)sBar.Width;
            double maxw = max * (double)sBar.Max / (double)sBar.Width;
            foreach (Photo a in photos)
            {
                bool flag = false;
                foreach (Stroke s in strokes)
                {
                    if (s.relatedPhotos.Contains(a))
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag)
                    continue;
                Vector2 v = Vector2.Zero;
                DateTime date = a.ptag.CapturedDate;
                //DateTime end = new DateTime(a.ptag.endDate, 12, 31);

                double x = date.Subtract(mindt).TotalSeconds;
                x -= minw;

                x *= (double)sBar.Width / Math.Max((maxw - minw), 1d);
                /*if (a.Position.X + a.Width / 2 > sBar.Width)
                    v = Vector2.UnitX * (float)(x - a.Position.X - a.Width / 2) * 0.02f * weight_;
                else if (a.Position.X - a.Width / 2 < 0)
                    v = Vector2.UnitX * (float)(x - a.Position.X + a.Width / 2) * 0.02f * weight_;
                else*/
                    v = Vector2.UnitX * (float)(x - (a.Position.X - a.Width/2 * a.Scale + a.Width * a.Scale * x/SystemParameter.ClientWidth)) * 0.1f * weight_;

                //// ノイズで方向を変化させる
                //if (v != Vector2.Zero && false)
                //{
                //    float noise = (float)((1 - Math.Exp(-rand.NextDouble())) * Math.PI);
                //    noise *= (float)Math.Log(a.Adjacency.Count + 1);
                //    if (rand.NextDouble() < 0.5)
                //    {
                //        noise *= -1;
                //    }
                //    float cnoise = (float)Math.Cos(noise);
                //    float snoise = (float)Math.Sin(noise);
                //    Vector2 noisyv = new Vector2(v.X * cnoise - v.Y * snoise, v.X * snoise + v.Y * cnoise);
                //    v = noisyv;
                //}
                a.AddPosition(v);
            }
        }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            weight_ = weight.NonOverlapWeight * (ResourceManager.MAXX + ResourceManager.MAXY);

            foreach (Photo a in photos)
            {
                // velocity
                Vector2 v = Vector2.Zero;

                //move direction to avoid adjacent photoes overlapping
                foreach (AdjacentPhoto b in a)
                {
                    if (a.IsGazeds && b.Photo.IsGazeds)
                    {
                        v += b.Direction * 0.2f * weight_ / 150f;
                        if (a.touchCount != 0 && b.Photo.touchCount != 0)
                        {
                            if (a.touchCount <= b.Photo.touchCount && a.LayerDepth >= b.Photo.LayerDepth)
                            {
                                b.Photo.LayerDepth = a.LayerDepth + 0.001f;
                                if (b.Photo.LayerDepth > 1f)
                                    b.Photo.LayerDepth = 1f;
                            }
                            else if (b.Photo.touchCount < a.touchCount && b.Photo.LayerDepth >= a.LayerDepth)
                            {
                                a.LayerDepth = b.Photo.LayerDepth + 0.001f;
                                if (a.LayerDepth > 1f)
                                    a.LayerDepth = 1f;
                            }
                        }
                    }
                    else
                    {
                        v += b.Direction * 0.02f * weight_/ 150f;
                    }
                }

                // add noise
                if (false)
                {
                    float variance = weight.NoiseWeight * 0.5f;
                    Vector2 noise = new Vector2((float)randbm.NextDouble(variance), (float)randbm.NextDouble(variance));
                    v += noise;
                }

                a.AddPosition(v);

            #if NO_ROTATION
            #else
                // 回転角
                float va = 0f;
                foreach (AdjacentPhoto b in a)
                {
                    va += b.AngleDirection;
                }

                //
                //

                float at = 0f;
                //// 1点を中心に回転させる
                //Vector2 spinCenter = new Vector2(input.WindowWidth / 2f, input.WindowHeight / 2f);
                ////spinCenter.Y = input.WindowHeight;
                //at = (float)(-Math.Atan2((double)(a.Position.X - (double)spinCenter.X), (double)(a.Position.Y - (double)spinCenter.Y)));
                //if (at > 0)
                //{
                //    at -= (float)Math.PI;
                //}
                //else
                //{
                //    at += (float)Math.PI;
                //}
                // できるだけ下を向かせる
                at = 0f;

                va += (at - a.Angle);

                //
                //

                // ノイズを付加する
                if (false)
                {
                    float variance = weight.NoiseWeight * 0.1f;
                    float noise = (float)randbm.NextDouble(variance);
                    va += noise;
                }
                a.AddAngle(va);
            #endif
            }
        }
Exemple #10
0
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            weight_ = weight.TagWeight;

            // ���ڂ���Ă���摜��temActivePhoto�Ƃ���
            foreach (Photo a in activePhotos)
            {
                if (a.activeTag.Count == 0 || (a.activeTag.Count == 1 && a.activeTag.Contains("Color")))
                    continue;
                                        // �e�摜�̈ړ�
                foreach (Photo photo in photos)
                {
                    if (photo.ID == a.ID)
                        continue;
                    bool matched = false;
                    foreach (String tag in a.activeTag)
                    {
                        if (tag.Equals("Color"))
                            continue;
                        if (photo.containTag(tag))
                        {
                            matched = true;
                            break;
                        }
                    }
                    Vector2 v = a.Position - photo.Position;
                    if (matched)
                    {
                        photo.IsFollowing = true;
                        Vector2 tempdir = Vector2.Zero;
                        float tempdira = 0f;
                        if (a.boundingBox_.Overrap(photo.boundingBox_, ref tempdir, ref tempdira))
                        {
                            v *= -1f;
                        }
                        v *= (float)3f;
                    }
                    else
                    {
                        v *= -1f;
                    }
                    v *= weight_ / 128f;

                    // noise
                    if (v != Vector2.Zero && false) // noise enabled
                    {
                        float noise = (float)((1 - Math.Exp(-rand.NextDouble())) * Math.PI);
                        noise *= (float)Math.Log(photo.Adjacency.Count + 1);
                        if (rand.NextDouble() < 0.5)
                        {
                            noise *= -1;
                        }
                        float cnoise = (float)Math.Cos(noise);
                        float snoise = (float)Math.Sin(noise);
                        Vector2 noisyv = new Vector2(v.X * cnoise - v.Y * snoise, v.X * snoise + v.Y * cnoise);
                        v = noisyv;
                    }

                    photo.AddPosition(v);
                }
            }
        }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            //weight_ = weight.NonOverlapWeight;
            baseX = SystemParameter.ClientWidth;
            baseY = SystemParameter.ClientHeight;
            // get geotag info from ini file
            if (geotagList_.Count < 1)
            {
                string iniName;
                if (ResourceManager.homeDirectory_ == null)
                    iniName = "geotagList.ini";
                else iniName = ResourceManager.homeDirectory_ + "\\" + "geotagList.ini";
                if (File.Exists(iniName))
                {
                    string gtl = File.ReadAllText(iniName);
                    string[] sep = new string[1];
                    sep[0] = "\r\n";
                    string[] gts = gtl.Split(sep, StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0, ilen = gts.Length; i < ilen; ++i)
                    {
                        sep[0] = ":";
                        string[] gt = gts[i].Split(sep, StringSplitOptions.RemoveEmptyEntries);
                        sep[0] = ",";
                        string[] xy = gt[1].Split(sep, StringSplitOptions.RemoveEmptyEntries);
            #if JAPANESE_MAP
                        int x = int.Parse(xy[0]);
            #else
                        int x = ((int)(float.Parse(xy[0]) + mapDef * bx / mapX)) % ((int)bx);
                        //int x = int.Parse(xy[0]);
            #endif
                        int y = int.Parse(xy[1]);
                        geotagList_.Add(new SStringIntInt(gt[0], x, y)); //place,coordinate xy
                    }
                }
            }

            if (ResourceManager.IfTohoku)
            {
                bx = 1750f;
                by = 1196f;

                //read tohoku geotag list
                if (geotagList_tohoku.Count < 1)
                {
                    string iniName;
                    if (ResourceManager.homeDirectory_ == null)
                        iniName = "geotagList_tohoku.ini";
                    else iniName = ResourceManager.homeDirectory_ + "\\" + "geotagList_tohoku.ini";
                    if (File.Exists(iniName))
                    {
                        string gtl = File.ReadAllText(iniName);
                        string[] sep = new string[1];
                        sep[0] = "\r\n";
                        string[] gts = gtl.Split(sep, StringSplitOptions.RemoveEmptyEntries);
                        for (int i = 0, ilen = gts.Length; i < ilen; ++i)
                        {
                            sep[0] = ":";
                            string[] gt = gts[i].Split(sep, StringSplitOptions.RemoveEmptyEntries);
                            sep[0] = ",";
                            string[] xy = gt[1].Split(sep, StringSplitOptions.RemoveEmptyEntries);
                            int x = int.Parse(xy[0]);
                            int y = int.Parse(xy[1]);
                            geotagList_tohoku.Add(new SStringIntInt(gt[0], x, y)); // 地名,xy坐标
                        }
                    }
                }
            }

            else
            {
                bx = 1022f;
                by = 748f;
            }

            foreach (Photo a in photos)
            {
                bool flag = false;
                foreach (Stroke s in strokes)
                {
                    if (s.relatedPhotos.Contains(a))
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag)
                    continue;
                Vector2 v = Vector2.Zero;
                if (ResourceManager.IfTohoku)
                {
                    foreach (SStringIntInt gt in geotagList_tohoku)
                    {
                        if (a.containTag(gt.Name))
                        {
                            Vector2 target = new Vector2((float)gt.X * baseX / bx, (float)gt.Y * baseY / by);
                            v += target - a.Position;
                            break;
                        }
                    }
                }
                else
                {
                    foreach (SStringIntInt gt in geotagList_)
                    {
                        if (a.containTag(gt.Name))
                        {
                            Vector2 target = new Vector2((float)gt.X * baseX / bx, (float)gt.Y * baseY / by);
                            v += target - a.Position;
                            break;
                        }
                    }
                }
                // noise
                if (v != Vector2.Zero && false)
                {
                    float noise = (float)((1 - Math.Exp(-rand.NextDouble())) * Math.PI);
                    noise *= (float)Math.Log(a.Adjacency.Count + 1);
                    if (rand.NextDouble() < 0.5)
                    {
                        noise *= -1;
                    }
                    float cnoise = (float)Math.Cos(noise);
                    float snoise = (float)Math.Sin(noise);
                    Vector2 noisyv = new Vector2(v.X * cnoise - v.Y * snoise, v.X * snoise + v.Y * cnoise);
                    v = noisyv;
                }
                a.AddPosition(v);
            }
        }
 public TimeSliderManager()
 {
     sBar = new ScrollBar(1022);
     timeSign.Add(new Tip(sBar.MinDT, new Vector2(sBar.Min, (float)ScrollBar.Height * 1.45f)));
     timeSign.Add(new Tip(sBar.MaxDT, new Vector2(sBar.Max, (float)ScrollBar.Height * 1.45f)));
 }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            weight_ = weight.NonOverlapWeight;
            //List<Stroke> strokes = strokeCol.strokeList;
            foreach (var stroke in strokes)
            {
                if (!stroke.IsClosed)
                    continue;

                //foreach (Photo a in photos)
                //{
                    foreach (Photo a in photos)
                    {
                        //Console.WriteLine(a.Position);
                        Vector2 v = Vector2.Zero;
                        // 到最近锚点的矢量
                        Vector2 v2n = Vector2.One * float.MaxValue;
                        foreach (Vector2 s in stroke.Strokes)
                        {
                            Vector2 dist = s - a.Position;
                            if (dist.LengthSquared() < v2n.LengthSquared())
                            {
                                v2n = dist;
                            }
                        }
                        //if(v2n.X == 1f/0)
                            //Console.WriteLine(v2n);
                        int matchedTagCount = 0;
                        foreach (string t in stroke.Tags)
                        {
                            if (a.containTag(t))
                            {
                                ++matchedTagCount;
                                break;
                            }
                        }
                        if (matchedTagCount == 0)
                        {
                            if (stroke.IsInternal(a.Position, stroke.outsideStrokes_))
                            {
                                v += (a.Position - stroke.Center);
                                v *= 0.002f * INTO_DISPLAY * weight_;
                            }
                        }
                        else
                        {
                            if (!stroke.IsInternal(a.Position, stroke.insideStrokes_))
                            {
                                v += (stroke.Center - a.Position);
                                v *= 0.002f * INTO_DISPLAY * weight_;
                            }
                        }
                        /*
                        bool inner = stroke.IsInternal(a.Position);
                        //test four points of each image
            #if STRICT
                            bool inner1 = stroke.IsInternal(a.boundingBox_.Min);
                            bool inner2 = stroke.IsInternal(new Vector2(a.boundingBox_.Min.X, a.boundingBox_.Max.Y));
                            bool inner3 = stroke.IsInternal(a.boundingBox_.Max);
                            bool inner4 = stroke.IsInternal(new Vector2(a.boundingBox_.Max.X, a.boundingBox_.Min.Y));
                            if(inner1 || inner2 || inner3 || inner4)
                            {
            #else
                        if (inner)
                        {
            #endif
                            int matchedTagCount = 0;
                            foreach (string t in stroke.Tags)
                            {
                                if (a.containTag(t))
                                {
                                    ++matchedTagCount;
                                    break;
                                }
                            }
                            if (matchedTagCount == 0)
                            {
                               // v += v2n;
                                v += (a.Position - stroke.Center);
                                v *= 0.002f * INTO_DISPLAY * weight_;
                            }
            #if STRICT
                            }
                            if (!inner1 || !inner2 || !inner3 || !inner4)
                            {
            #else
                        }
                        else
                        {
            #endif
                            int matchedTagCount = 0;
                            foreach (string t in stroke.Tags)
                            {
                                if (a.containTag(t))
                                {
                                    ++matchedTagCount;
                                    break;
                                }
                            }
                            if (matchedTagCount > 0)
                            {
                                //v += v2n;
                                v += (stroke.Center - a.Position);
                                v *= 0.002f * INTO_DISPLAY * weight_;
                                //Console.WriteLine(v);
                            }
                        }
                         * */
                    //bool inner = stroke.IsInternal(a.Position);
                    //Vector2 v = Vector2.Zero;
                    //// vector to the nearest point
                    //Vector2 v2n = Vector2.One * float.MaxValue;

                    ////if (stroke.relatedPhotos.Contains(a))
                    //    //a.IsFollowing = true;
                    //if (stroke.relatedPhotos.Contains(a) && !inner)
                    //{
                    //    foreach (Vector2 s in stroke.Strokes)
                    //    {
                    //        Vector2 dist = s - a.Position;
                    //        if (dist.LengthSquared() < v2n.LengthSquared())
                    //        {
                    //            v2n = dist;
                    //        }
                    //    }
                    //    //v += v2n;
                    //    v += (stroke.Center - a.Position);
                    //    v *= 0.02f * INTO_DISPLAY * weight_;
                    //}
                    //else if (!stroke.relatedPhotos.Contains(a) && inner)
                    //{
                    //    foreach (Vector2 s in stroke.Strokes)
                    //    {
                    //        Vector2 dist = s - a.Position;
                    //        if (dist.LengthSquared() < v2n.LengthSquared())
                    //        {
                    //            v2n = dist;
                    //        }
                    //    }
                    //    //v += v2n;
                    //    v += (a.Position - stroke.Center);
                    //    v *= 0.02f * INTO_DISPLAY * weight_;
                    //}
                    // noise
                    if (false)
                    {
                        if (v != Vector2.Zero)
                        {
                            float variance = weight.NoiseWeight * 0.5f;
                            Vector2 noise = new Vector2((float)randbm.NextDouble(variance), (float)randbm.NextDouble(variance));
                            v += noise;
                        }
                    }
                    a.AddPosition(v);
                }

            }
        }
        public void select(Dock dock, ScrollBar sBar, AttractorWeight weight, List<Photo> photos, List<Photo> activePhotos, List<Stroke> strokes, SystemState systemState)
        {
            //Photo clickedPhoto = null;

            // 找到被点击的图片
            foreach (Photo a in activePhotos)
            {
                if (a.IsClicked == false)
                {
                    continue;
                }
                //if one picture is clickes
                List<PeopleTag> currentTagList = a.PTags.pTags;
                string selectedPeopleName = null;
                // 如果被选中的图片没有人物标签则返回,不予处理
                if (currentTagList == null)
                    continue;
                foreach (PeopleTag p in currentTagList)
                {
                    Rectangle box = p.Box;
                    Rectangle newbox = new Rectangle((int)((float)box.X * a.ScaleDisplay), (int)((float)box.Y * a.ScaleDisplay)
                        , (int)((float)box.Width * a.ScaleDisplay), (int)((float)box.Height * a.ScaleDisplay));

                    if (newbox.Contains((int)a.ClickedPoint.X, (int)a.ClickedPoint.Y))
                    {
                        selectedPeopleName = p.People;
                        break;
                    }
                }

                // 如果选中了某人
                if (selectedPeopleName != null)
                {
                    foreach (Photo p in photos)
                    {
                        Vector2 v = Vector2.Zero;
                        if (p.ptag.allTags.Contains(selectedPeopleName)) // 对于那些被吸引的图像
                        {
                            v = a.Position - p.Position; // 吸引
                            v *= weight_1 / 2f;// 10f;
                        }
                        else // 为被吸引的图像
                        {
                            v = p.Position - a.Position; // 排斥
                            v *= weight_2 / 3.0f;// 10f;
                        }

                        // 改变噪声方向
                        if (v != Vector2.Zero && false)
                        {
                            float noise = (float)((1 - Math.Exp(-rand.NextDouble())) * Math.PI);
                            noise *= (float)Math.Log(p.Adjacency.Count + 1);
                            if (rand.NextDouble() < 0.5)
                            {
                                noise *= -1;
                            }
                            float cnoise = (float)Math.Cos(noise) / 3f;
                            float snoise = (float)Math.Sin(noise) / 3f;
                            Vector2 noisyv = new Vector2(v.X * cnoise - v.Y * snoise, v.X * snoise + v.Y * cnoise);
                            v = noisyv;
                        }

                        // 将改变的向量v作用于图像
                        p.AddPosition(v);
                    }
                }
            }
        }