public List <T> BoxCrossing <T>(int x1, int y1, int x2, int y2) { Dictionary <object, bool> r = new Dictionary <object, bool>(); List <T> result = new List <T>(); List <object> res = tx.Find(x1, x2, (o) => { IntLine l = o as IntLine; if (l.y1 < y1 && l.y2 < y1) { return(false); } if (l.y1 > y2 && l.y2 > y2) { return(false); } if (r.ContainsKey(l.obj)) { return(false); } if (!LineVisible(l.x1, l.y1, l.x2, l.y2, x1, y1, x2, y2)) { return(false); } r[l.obj] = true; if (l.obj is T) { result.Add((T)l.obj); } return(true); }); return(result); }
/// <summary> /// Returns parameter on l1 /// </summary> /// <param name="l1"></param> /// <param name="l2"></param> /// <returns></returns> double SegmentSegment(IntLine l1, IntLine l2) { double denom = l1.x1 * (l2.y2 - l2.y1) + l1.x2 * (l2.y1 - l2.y2) + l2.x2 * (l1.y2 - l1.y1) + l2.x1 * (l1.y1 - l1.y2); if (denom != 0.0) { return((l1.x1 * (l2.y2 - l2.y1) + l2.x1 * (l1.y1 - l2.y2) + l2.x2 * (l2.y1 - l1.y1)) / denom); } //handle parallel lines double dist1 = MathUtil.Hypot(l1.x1 - l2.x1, l1.y1 - l2.y1); double dist2 = MathUtil.Hypot(l1.x1 - l2.x2, l1.y1 - l2.y2); double l = MathUtil.Hypot(l1.x1 - l1.x2, l1.y1 - l1.y2); if (l < 1e-3) { return(0.0); } if (dist1 < dist2) { return(dist1 / l); } else { return(dist1 / l); } }
public List <T> BoxWindow <T>(int x1, int y1, int x2, int y2) { Dictionary <object, int> r = new Dictionary <object, int>(); List <T> result = new List <T>(); List <object> res = tx.Find(x1, x2, (o) => { IntLine l = o as IntLine; if (l.x1 < x1 || l.x1 > x2 || l.x2 < x1 || l.x2 > x2 || l.y1 < y1 || l.y1 > y2 || l.y2 < y1 || l.y2 > y2) { return(false); } if (!r.ContainsKey(l.obj)) { r[l.obj] = 0; } r[l.obj] += 1; if (r[l.obj] == objects[l.obj] && l.obj is T) { result.Add((T)l.obj); } return(true); }); return(result); }
public static IEnumerator LineSurface(Emplacement place, OptionEffect options) { Vector3i shape = options.OptionShape.shape; /// (avancée, hauteur, largeur) Vector3i above = Vectors.Up; Vector3i pos = place.ipos; Vector3i offsetSurface = new Vector3i(0, options.OptionShape.offsetSurface, 0); bool reverse = options.OptionShape.reverse != ""; float pace = options.OptionShape.pace; bool collapse_once = options.OptionShape.reverse == "once"; Block air = Block.GetBlockByName("air", false); Block blk = options.OptionBlock.block; BlockSetter setter = new BlockSetter(options.OptionBlock); /// IntLine traj = new IntLine(place.ipos, Vectors.Float.UnitX); IntLine traj = new IntLine(place.ipos, Emplacement.Truncate(place.direction, true, true)); for (int avance = 0; avance < shape.x; avance++) { Vector3i where = traj.Get(avance); Debug.Log("LineSurface " + avance.ToString()); IntLine orth = new IntLine(Vectors.ToFloat(where), Vectors.Float.UnitZ); foreach (int ligne in LR(shape.z)) { Vector3i at = orth.Get(ligne); //Debug.Log("Line Surface inner " + p.ToString()); at = Geo3D.Surface(at); // I don't need surface before orthogonal ... surface made after setter.Apply(at + above + offsetSurface); } setter.Push(); yield return(new WaitForEndOfFrame()); } }
bool Intersect(IntLine l, List <object> lines) { foreach (IntLine l2 in lines) { if (Intersect(l.x1, l.y1, l.x2, l.y2, l2.x1, l2.y1, l2.x2, l2.y2)) { return(true); } } return(false); }
public static IEnumerator TrapLine(Entity player, Emplacement place, OptionEffect options) { /// TODO: recoder ca avec rift Vector3i offsetSurface = new Vector3i(0, options.OptionShape.offsetSurface, 0); Vector3i pos = place.ipos; // size = E/W=largeur, hauteur, N/S profondeur (portee) Vector3i size = options.OptionShape.shape; Vector3 base_direction = Emplacement.Truncate(place.direction, true, true); float pace = 0.1f; // TODO pace in option Block air = Block.GetBlockByName("air", false); // The air instance could prolly be shared ... // Block blk = options.OptionBlock.block; int portee = 100; BlockSetter setter = new BlockSetter(options.OptionBlock); BlockSetter setterAir = new BlockSetter(options.OptionBlock.Copy()); setterAir.options.block = air; Vector3 posf = Vectors.ToFloat(pos + offsetSurface); // string[] random_blocks = new string[]{"trapSpikesWoodDmg0", "trapSpikesWoodDmg1", "trapSpikesWoodDmg2"}; // Block[] random_blocks = options.OptionBlock.blocks; Vector3i start = Geo3D.Surface(place.ipos); for (int k = 0; k < 10; k++) { Vector3 direction = base_direction + Vectors.Float.Randomize(GameManager.Instance.World.GetGameRandom(), 0.1f); direction.y = 0; direction = direction.normalized; // IntLine traj = new IntLine(start, direction); //east IEnumerable <Vector3i> segment = IntLine.Segment(Vectors.ToFloat(start), direction, 1, 10); // skip 0 intersecting with the previous foreach (Vector3i where in segment) { Vector3i Swhere = Geo3D.Surface(where); // randomisation : "trapSpikesWoodDmg0-2" // string rdm = random_blocks[(int) Math.Floor(GameManager.Instance.World.GetGameRandom().RandomFloat*3)]; // setter.options.block = Block.GetBlockByName(rdm, false); // Block rdm = setter.Apply(Swhere + Vectors.Up); setter.Push(); start = Swhere; yield return(new WaitForEndOfFrame()); } yield return(new WaitForSeconds(0.5f)); } }
/* * * Options: * - ground (water, traps) * - recursion * - size / depth (puis avant) * - other content : Z, animal, torch, lights ... * */ public static IEnumerator Rift(EntityPlayer player, Emplacement place, OptionEffect options) { /* * Laisse des blocks tomber au dessus ? just changed erase="yes" * (longueur 1, hauteur (profonfeur), replicats) */ EntityPlayerLocal epl = player as EntityPlayerLocal; epl.cameraTransform.SendMessage("ShakeBig"); yield return(new WaitForSeconds(1f)); BlockSetter setter = new BlockSetter(options.OptionBlock); Vector3 direction = Vectors.Copy(place.direction); direction.y = 0; direction = direction.normalized; Vector3i start = Geo3D.Surface(place.ipos); for (int k = 0; k < options.OptionShape.shape.z; k++) { Vector3 kdirection = direction + Vectors.Float.Randomize(GameManager.Instance.World.GetGameRandom(), 0.2f); // IntLine traj = new IntLine(start, direction); //east IEnumerable <Vector3i> segment = IntLine.Segment(Vectors.ToFloat(start), kdirection, 0, options.OptionShape.shape.x); Vector3i prev = new Vector3i(); bool hasprev = false; foreach (Vector3i where in segment) { Vector3i Swhere = Geo3D.Surface(where); setter.Apply(Swhere); if (hasprev) { for (int creuse = 1; creuse < options.OptionShape.shape.y; creuse++) { setter.Apply(prev + creuse * Vectors.Down); } } setter.Push(); start = Swhere; yield return(new WaitForEndOfFrame()); hasprev = true; prev = Swhere; } yield return(new WaitForSeconds(1f)); } }
bool Outside(IntLine l, int x1, int y1, int x2, int y2) { if (l.x1 < x1 && l.x2 < x1) { return(true); } if (l.y1 < y1 && l.y2 < y1) { return(true); } if (l.x1 > x2 && l.x2 > x2) { return(true); } if (l.y1 > y2 && l.y2 > y2) { return(true); } return(false); }
public static IEnumerator Rift(EntityPlayer player, Emplacement place, OptionEffect options) { /* * Laisse des blocks tomber au dessus ? just changed erase="yes" */ Vector3i offsetSurface = new Vector3i(0, options.OptionShape.offsetSurface, 0); EntityPlayerLocal epl = player as EntityPlayerLocal; epl.cameraTransform.SendMessage("ShakeBig"); yield return(new WaitForSeconds(1f)); // Vector3i shape = options.OptionShape.shape; /// (longueur, hauteur, largeur) BlockSetter setter = new BlockSetter(options.OptionBlock); Vector3i start = Geo3D.Surface(place.ipos); for (int k = 0; k < 3; k++) { // Vector3 direction = Vectors.Float.UnitX + Vectors.Float.Randomize(GameManager.Instance.World.GetGameRandom(), 0.1f); Vector3 direction = place.direction + Vectors.Float.Randomize(GameManager.Instance.World.GetGameRandom(), 0.1f); direction.y = 0; direction = direction.normalized; // IntLine traj = new IntLine(start, direction); //east IEnumerable <Vector3i> segment = IntLine.Segment(Vectors.ToFloat(start), direction, 1, 5); // skip 0 intersecting with the previous foreach (Vector3i where in segment) { Vector3i Swhere = Geo3D.Surface(where) + offsetSurface; setter.Apply(Swhere); setter.Apply(Swhere + Vectors.Up); setter.Apply(Swhere + 2 * Vectors.Up); setter.Push(); start = Swhere; yield return(new WaitForEndOfFrame()); } yield return(new WaitForSeconds(1f)); } }
public static IEnumerator Cave(EntityPlayer player, Emplacement place, OptionEffect options) { /// TODO: enumérer les colonnes et s'arreter à surface BlockSetter setter = new BlockSetter(options.OptionBlock); Vector3i shape = options.OptionShape.shape; Vector3i start = Geo3D.Surface(place.ipos); int depth = shape.y; Vector3 direction = Vectors.Float.UnitY; // cannot use negative, so positive and get(_k) ! IntLine colonne = new IntLine(Vectors.ToFloat(start), direction); // Debug.Log(String.Format("Cave: pos={0} start={1} dir={2} ground={3}", place.position, start, direction, ground)); for (int d = 0; d < depth; d++) { // Debug.Log(String.Format("cave {0} {1}", d, setter)); if (options.OptionShape.ground != "" && d == depth - 1) { setter.options.block = Block.GetBlockByName(options.OptionShape.ground, false); } Vector3i where = colonne.Get(-d); Vector3i dxy = new Vector3i(0, 0, 0); foreach (int p in SdtdUtils.EffectsGround.LR(shape.x)) { foreach (int q in SdtdUtils.EffectsGround.LR(shape.z)) { dxy.x = p; dxy.z = q; Printer.Log(20, "Cave Apply (d,p) =", d, p, "where, dxy=", where, dxy); setter.Apply(where + dxy); } } Printer.FLog(20, "cave Push {0} {1}", d, where); setter.Push(); } yield return(new WaitForEndOfFrame()); }
bool Intersect(IntLine l1, IntLine l2) { return(Intersect(l1.x1, l1.y1, l1.x2, l1.y2, l2.x1, l2.y1, l2.x2, l2.y2)); }
public List <T> Fence <T>(List <Point2i> pnts, Func <int, int, int, int, int, int> plot = null) { Dictionary <object, bool> r = new Dictionary <object, bool>(); List <T> result = new List <T>(); int cnt = pnts.Count; for (int i = 0; i < cnt - 1; i++) { IntLine seg = new IntLine(pnts[i].X, pnts[i].Y, pnts[(i + 1) % cnt].X, pnts[(i + 1) % cnt].Y, null); if (plot != null) { plot(seg.x1, seg.y1, seg.x2, seg.y2, 3); } int x1 = Math.Min(seg.x1, seg.x2); int y1 = Math.Min(seg.y1, seg.y2); int x2 = Math.Max(seg.x1, seg.x2); int y2 = Math.Max(seg.y1, seg.y2); List <object> res = tx.Find(seg.x1, seg.x2, (o) => { IntLine l = o as IntLine; if (Outside(l, x1, y1, x2, y2)) { return(false); } if (r.ContainsKey(l.obj)) { return(false); } if (Intersect(l, seg)) { r[l.obj] = true; return(true); } return(false); }); if (res.Count <= 0) { continue; } else if (res.Count == 1) { object o = ((IntLine)res[0]).obj; if (o is T) { result.Add((T)o); } } else { // Loop res and calc proper intersections and sort then add List <KeyValuePair <IntLine, double> > ints = new List <KeyValuePair <IntLine, double> >(); foreach (IntLine l in res) { double s = SegmentSegment(seg, l); ints.Add(new KeyValuePair <IntLine, double>(l, s)); } ints.Sort((a, b) => { return(a.Value.CompareTo(b.Value)); }); foreach (var l in ints) { if (l.Key.obj is T) { result.Add((T)(l.Key.obj)); } } } } if (plot != null) { foreach (IntLine l in tx) { plot(l.x1, l.y1, l.x2, l.y2, r.ContainsKey(l.obj)?5:1); } } return(result); }
public List <T> PolyWindow <T>(List <Point2i> pnts) { Dictionary <object, int> r = new Dictionary <object, int>(); List <T> result = new List <T>(); // Bounding box int x1 = int.MaxValue; int y1 = int.MaxValue; int x2 = int.MinValue; int y2 = int.MinValue; // First create an Y-interval tree for fast inside/intersection checking IntervalTreeInt ins = new IntervalTreeInt(); int cnt = pnts.Count; for (int i = 0; i < cnt; i++) { IntLine l = new IntLine(pnts[i].X, pnts[i].Y, pnts[(i + 1) % cnt].X, pnts[(i + 1) % cnt].Y, null); ins.Add(l, Math.Min(l.y1, l.y2), Math.Max(l.y1, l.y2)); // Calc bbox if (pnts[i].X < x1) { x1 = pnts[i].X; } if (pnts[i].X > x2) { x2 = pnts[i].X; } if (pnts[i].Y < y1) { y1 = pnts[i].Y; } if (pnts[i].Y > y2) { y2 = pnts[i].Y; } } List <object> res = tx.Find(x1, x2, (o) => { IntLine l = o as IntLine; if (l.y1 < y1 && l.y2 < y1) { return(false); } if (l.y1 > y2 && l.y2 > y2) { return(false); } // Collect all candidates from poly List <object> candidates = ins.Find(l.y1, l.y2, null); if (Inside(l.x1, l.y1, candidates) && Inside(l.x2, l.y2, candidates) && !Intersect(l, candidates)) { if (!r.ContainsKey(l.obj)) { r[l.obj] = 0; } r[l.obj] += 1; if (r[l.obj] == objects[l.obj] && l.obj is T) { result.Add((T)l.obj); } return(true); } return(false); }); return(result); }