//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); } }
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 } }
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); } } } }