/// <summary> /// 凸多角形の再分割処理 /// </summary> public static ConvexPolygon Execute(ConvexPolygon polygon, float angleThreshold, float t = 0.5f) { //入力がnullならnullを返す if (polygon == null) { return(null); } //諸々のデータ構造 List <Vector2> results = new List <Vector2>(); //計算結果 List <Vector2> temp = new List <Vector2>(); //一時データ List <Vector2> vertices = polygon.GetVerticesCopy(); //はじめに2点追加 temp.Add(vertices[0]); temp.Add(vertices[1]); //巡回 int size = vertices.Count; for (int i = 2; i <= size; ++i) { //順次処理 temp.Add(vertices[i % size]); Process(temp, results, angleThreshold, t); //処理 } //0番目の処理 temp.Add(results[0]); Process(temp, results, angleThreshold, t); //処理 return(new ConvexPolygon(results)); }
private static LineSegment2D?ClosestTo(Point pt, ConvexPolygon poly) { FixedPoint? closest = null; LineSegment2D edge = default; for (var i = 0; i < poly.NumLineSegments; i++) { var seg = poly.GetLineSegment(i); var dist = CollisionDetector.DetermineClosestPoint(seg, pt); if (dist == null) { continue; } if (closest == null || dist.Value.Distance < closest) { closest = dist.Value.Distance; edge = seg; } } if (closest == null) { return(null); } return(edge); }
/// <summary> /// 重み付きボロノイ図の生成 /// </summary> public List <ConvexPolygon> Execute(ConvexPolygon area, List <WaitedVoronoiSite> sites) { List <ConvexPolygon> result = new List <ConvexPolygon>(); foreach (var s1 in sites) { ConvexPolygon region = null; //途中計算結果格納用の領域 foreach (var s2 in sites) { if (s1 == s2) { continue; } //s1とs2の垂直線を重み付きで求める Line line = Line.PerpendicularWaitLine(s1.Point, s1.Wait, s2.Point, s2.Wait); //垂直二等分線による半平面のうち,s1を含む方を求める ConvexPolygon halfPlane = halfPlaneGenerator.Execute(line, s1.Point); if (region == null) { //初回計算時 region = IntersectionOperation.Execute(area, halfPlane); } else { //二回目以降 region = IntersectionOperation.Execute(region, halfPlane); } } //最終的な計算結果をボロノイ領域とする result.Add(region); } return(result); }
public void Update(double elapsedTime) { _selectedPolygon = _navMesh.FindNearestPolygon(_input.Mouse.Position); _selectedVertexIndex = FindSelectedVertex(_input.Mouse.Position, _selectedPolygon, VertexEditRadius); if (_draggingVertex) { if (_input.Mouse.LeftHeld && _selectedVertexIndex != -1) { _selectedPolygon.TryToUpdateVertPosition(_selectedVertexIndex, _input.Mouse.Position); return; } else { _draggingVertex = false; } } if (_input.Keyboard.IsKeyPressed(System.Windows.Forms.Keys.A)) { _navMesh.AddPolygon(new ConvexPolygon(_input.Mouse.Position)); } if (_input.Mouse.LeftHeld && _selectedVertexIndex != -1) { _draggingVertex = true; } }
IDrawable run(IDrawable input) { if (!(input is PointSet)) { throw new Exception("PolygonTest. Input is not PolygonTest."); } var inp = input as PointSet; Point c = inp[0]; Point d = inp[1]; Point e = inp[2]; Point fe = inp[3]; ConvexPolygon f1 = new ConvexPolygon(new Point((c.X + d.X) / 2, c.Y), new Point(d.X, (c.Y + d.Y) / 3), new Point(d.X, 2 * ((d.Y + c.Y) / 3)), new Point((c.X + d.X) / 2, d.Y), new Point(c.X, 2 * ((d.Y + c.Y) / 3)), new Point(c.X, ((d.Y + c.Y) / 3))); ConvexPolygon f2 = new ConvexPolygon(new Point((e.X + fe.X) / 2, e.Y), new Point(fe.X, (e.Y + fe.Y) / 3), new Point(fe.X, 2 * ((fe.Y + e.Y) / 3)), new Point((e.X + fe.X) / 2, fe.Y), new Point(e.X, 2 * ((fe.Y + e.Y) / 3)), new Point(e.X, ((fe.Y + e.Y) / 3))); var x = Intersect.GetIntersection(f1, f2); if (x.Count > 0) { return(new DrawableSet(new List <IDrawable>() { new PointSet(x.ToArray()), new PolygonSet(f1, f2), DrawableElement.Text(0, 0, "Vse horosho") })); } else { return(new DrawableSet(new List <IDrawable>() { new PointSet(x.ToArray()), new PolygonSet(f1, f2), DrawableElement.Text(0, 0, "Vse ploho") })); } }
IDrawable run(IDrawable input) { if (!(input is PointSet)) { throw new Exception("PointPolygonTest. Input is not PointPolygonTest."); } var inp = input as PointSet; Point a = inp[0]; Point c = inp[1]; Point d = inp[2]; var b = new ConvexPolygon(new Point(c.X, c.Y), new Point(d.X, c.Y), new Point(d.X, d.Y), new Point(c.X, d.Y)); var x = Intersect.IsIntersected(a, b); //var x = Intersect.GetIntersection(b, a); if (x) { return(new DrawableSet(new List <IDrawable>() { new PointSet(), new PolygonSet(b), DrawableElement.Text(0, 0, "Vse horosho") })); } else { return(new DrawableSet(new List <IDrawable>() { new PointSet(), new PolygonSet(b), DrawableElement.Text(0, 0, "Vse ploho") })); } //return new PointSet(x.ToArray()); }
private void Update() { ConvexPolygon p1 = polygon1.Polygon; ConvexPolygon p2 = polygon2.Polygon; if (p1 == null || p2 == null) { return; } ConvexPolygon polygon = IntersectionOperation.Execute(p1, p2, lineFactory); //DrawLine if (polygon == null) { return; } List <Vector3> vertices = polygon.GetVertices3Copy(); vertices.Add(vertices[0]); //末尾に先頭を追加 if (line != null) { lineFactory.DeleteLine(line); } //line = lineFactory.CreateLine(vertices, Color.green); //DrawEdgeLine //DrawEdgeLine(p1, leftEdge); }
// ===== #region Constructors // Default constructor public RigidBody(Scene scene, ConvexPolygon shape, String material, float mass) { // Get ID this.id = nextID++; // Entry logging #if IS_LOGGING_METHODS Log.Write(String.Format("Entering method for {0}", this.Name)); #endif this.scene = scene; this.geometry = shape; this.material = material; this.mass = mass; this.velocity = Vector2.Zero; this.angularVelocity = 0; this.rotationalAxis = this.Geometry.Centroid; this.momentOfInertia = this.Geometry.GetMomentAbout(this.RotationalAxis, this.Mass); this.contacts = new List <Contact>(); this.appliedImpulses = new List <Impulse>(); this.sweep = new Sweep(this); this.rank = -1; this.isSleeping = false; this.isTranslatable = true; this.isRotatable = true; // Exit logging #if IS_LOGGING_METHODS Log.Write(String.Format("Exiting method for {0}", this.Name)); #endif }
/// <summary> /// ボロノイ図の生成 /// </summary> public List <ConvexPolygon> Execute(ConvexPolygon area, List <Vector2> sites) { List <ConvexPolygon> result = new List <ConvexPolygon>(); foreach (Vector2 s1 in sites) { ConvexPolygon region = null; //途中計算結果格納用の領域 foreach (Vector2 s2 in sites) { if (s1 == s2) { continue; } //s1とs2の垂直二等分線を求める Line line = Line.PerpendicularBisector(s1, s2); //垂直二等分線による半平面のうち,s1を含む方を求める ConvexPolygon halfPlane = halfPlaneGenerator.Execute(line, s1); if (region == null) { //初回計算時 region = IntersectionOperation.Execute(area, halfPlane); } else { //二回目以降 region = IntersectionOperation.Execute(region, halfPlane); } } //最終的な計算結果をボロノイ領域とする result.Add(region); } return(result); }
/// <summary> /// 図の更新 /// </summary> private void UpdateDiagram(List <Vector2> sites) { //ボロノイ図の作成 areaPolygon = ConvexPolygon.SquarePolygon(10f); voronoiGenerator = new VoronoiDiagramGenerator(); regions = voronoiGenerator.Execute(areaPolygon, sites); //線の削除 for (int i = 0; i < lines.Count; ++i) { lineFactory.DeleteLine(lines[i]); } lines.Clear(); for (int i = 0; i < regions.Count; ++i) { ConvexPolygon region = regions[i]; //線の描画 if (drawRegionLine) { List <Vector3> vertices = region.GetVertices3Copy(); vertices.Add(vertices[0]); lines.Add(lineFactory.CreateLine(vertices)); } //メッシュ meshes[i] = region.Scale(sites[i], 0.5f).ToMesh(); //AngleSubdivisionOperation.Execute(region, 170f).Scale(sites[i], 1f).ToMesh(); //あたり判定の設定 colliders[i].sharedMesh = meshes[i]; } }
/// <summary> /// Searches the given poly for it's vertex that is closest to the given point. /// </summary> private static Point ClosestVertexTo(Point pt, ConvexPolygon poly) { FixedPoint?minDist = null; Point ret = default; for (var i = 0; i < poly.NumVertices; i++) { var v = poly.GetVertex(i); var diff = new Vector(v.X - pt.X, v.Y - pt.Y); if (diff.DeltaX * diff.DeltaX + diff.DeltaY * diff.DeltaY < 0) { continue; } if (!diff.TryMagnitude(out var dist)) { continue; } if (minDist == null || dist < minDist) { minDist = dist; ret = v; } } return(ret); }
/// <summary> /// ボロノイ図生成コルーチン /// </summary> private IEnumerator Voronoi() { PseudoHalfPlaneGenerator halfPlaneGenerator = new PseudoHalfPlaneGenerator(100f); while (true) { List <Vector2> sites = new List <Vector2>(siteTranses.Select(elem => (Vector2)elem.position)); List <ConvexPolygon> results = new List <ConvexPolygon>(); List <ChainLine> lines = new List <ChainLine>(); for (int i = 0; i < sites.Count; ++i) { Vector3 s1 = sites[i]; ConvexPolygon region = null; //途中計算結果格納用の領域 for (int j = 0; j < sites.Count; ++j) { Vector3 s2 = sites[j]; if (i == j) { continue; } //s1とs2の垂直二等分線を求める Line line = Line.PerpendicularBisector(s1, s2); //垂直二等分線による半平面のうち,s1を含む方を求める ConvexPolygon halfPlane = halfPlaneGenerator.Execute(line, s1); if (region == null) { //初回計算時 region = IntersectionOperation.Execute(areaPolygon, halfPlane); } else { //二回目以降 region = IntersectionOperation.Execute(region, halfPlane); } Debug.Log(region + " : " + halfPlane); //halfPlaneを可視化 List <Vector3> vertices = halfPlane.GetVertices3Copy(); vertices.Add(vertices[0]); //末尾を追加 ChainLine subl = lineFactory.CreateLine(vertices, subColor); //regionを可視化 vertices = region.GetVertices3Copy(); vertices.Add(vertices[0]); //末尾を追加 ChainLine l = lineFactory.CreateLine(vertices, lineColor.Evaluate((float)j / sites.Count)); yield return(StartCoroutine(Wait())); lineFactory.DeleteLine(subl); lineFactory.DeleteLine(l); } } Debug.Log("Complete"); yield return(StartCoroutine(Wait())); } }
private static bool DoTheyCollide(ConvexPolygon shapeA, ConvexPolygon shapeB, Body bodyA, Body bodyB, out Vector2 impactNormal, out float penetration) { Vector2[] pointsA = shapeA.GetAdjustedPointPositions(bodyA.Position, bodyA.Rotation); Vector2[] pointsB = shapeB.GetAdjustedPointPositions(bodyB.Position, bodyB.Rotation); return(DoTheyCollide(pointsA, pointsA, out impactNormal, out penetration)); }
public Cell(int _i, int _j, CellGrid _grid) { i = _i; j = _j; grid = _grid; value = 0; rectangleBuffer = ConvexPolygon.Square(_grid.CellSize).GetFillBuffer();//new ColoredRectangleBuffer(X, Y, _grid.CellSize, _grid.CellSize, -1.5f); }
public void SetUp() { SetPoints(); vertices = new List <Point> { topLeft, bottomRight, bottomLeft, topRight }; poly = new ConvexPolygon(vertices); }
/// <summary> /// /// Создаёт юнит по по области его расположения /// </summary> /// <param name="polygon"></param> public Unit(ConvexPolygon polygon) { figures = new List <Figure> { polygon }; Polygon = polygon; unitCommander = new AutomaticCommander(""); }
public void Activated() { // Put the character in the center of a random polygon. ConvexPolygon randomPoly = _scene.NavMesh.PolygonList[_random.Next(_scene.NavMesh.PolygonList.Count)]; _playerCharacter.SetPosition(randomPoly.CalculateCentroid()); _playerCharacter.FaceDown(); }
public Teleport(Point center) : base(Physics.Material.Adamantium, new Point(0, 0), false, null) { teleported = null; Activated = false; Enabled = true; Shape = ConvexPolygon.Rectangle(center, Width, Height); }
/// <summary> /// ボロノイ図生成コルーチン /// </summary> private IEnumerator Voronoi() { while (true) { List <Vector2> sites = new List <Vector2>(siteTranses.Select(elem => (Vector2)elem.position)); List <ConvexPolygon> results = new List <ConvexPolygon>(); List <ChainLine> lines = new List <ChainLine>(); foreach (Vector2 s1 in sites) { ConvexPolygon region = null; //途中計算結果格納用の領域 foreach (Vector2 s2 in sites) { if (s1 == s2) { continue; } //ウェイト yield return(StartCoroutine(WaitClick())); //s1とs2の垂直二等分線を求める Line line = Line.PerpendicularBisector(s1, s2); //垂直二等分線による半平面のうち,s1を含む方を求める ConvexPolygon halfPlane = halfPlaneGenerator.Execute(line, s1); //線を描画 lines.Add(lineFactory.CreateLine(halfPlane.GetVertices3Copy())); if (region == null) { //初回計算時 region = IntersectionOperation.Execute(areaPolygon, halfPlane); } else { //二回目以降 region = IntersectionOperation.Execute(region, halfPlane); } } results.Add(region); } for (int i = 0; i < results.Count; ++i) { lines.Add(lineFactory.CreateLine(results[i].GetVertices3Copy(), Color.red)); } Debug.Log("Complete"); yield return(StartCoroutine(WaitClick())); for (int i = 0; i < lines.Count; ++i) { lineFactory.DeleteLine(lines[i]); } lines.Clear(); } }
/// <summary> /// создаёт юнит с заданными областью расположения, свойствами и указанным боевым командиром /// </summary> /// <param name="polygon">Область расположения</param> /// <param name="features">Свойства</param> /// <param name="commander">Боевой командир</param> public Unit(ConvexPolygon polygon, UnitFeatures features, AutomaticCommander commander) { figures = new List <Figure> { polygon }; Polygon = polygon; props = features; unitCommander = commander; }
/// <summary> /// 凸多角形の交差領域の抽出 /// </summary> public static ConvexPolygon Execute(ConvexPolygon polygon1, ConvexPolygon polygon2) { //どちらかがnullならnullを返す if (polygon1 == null || polygon2 == null) { return(null); } //ステータスなど下準備 Status status = new Status(); List <Edge> leftEdge = new List <Edge>(); //左側の計算結果 List <Edge> rightEdge = new List <Edge>(); //右側の計算結果 //一回目のイベントを処理 StepResult result = FirstPass(polygon1, polygon2, status, leftEdge, rightEdge); //二回目以降のイベントを処理 while (result.mustContinue) { //二番目以降のイベントを処 result = SecondPass(status, leftEdge, rightEdge); } //左側と右側の計算結果を統合するリスト List <Edge> totalEdge = new List <Edge>(); totalEdge.AddRange(leftEdge); rightEdge.Reverse(); //反転して連結 totalEdge.AddRange(rightEdge); //交差凸多角形の交点リスト List <Vector2> resultPoints = new List <Vector2>(); Vector2 lastPoint = Vector2.one * float.NaN; int totalSize = totalEdge.Count; for (int i = 0; i < totalSize; ++i) { Edge e1 = totalEdge[i]; Edge e2 = totalEdge[(i + 1) % totalSize]; Vector2 p = Vector2.zero; if (e1.GetIntersectionPoint(e2, ref p)) { resultPoints.Add(p); } } //頂点が3つ以上なら凸多角形を作成 if (resultPoints.Count >= 3) { return(new ConvexPolygon(resultPoints)); } else { return(null); } }
/// <summary> /// Создаёт юнит по области его расположения и заданным особенностям /// </summary> /// <param name="polygon">Область расположения</param> /// <param name="features">Свойства юнита</param> public Unit(ConvexPolygon polygon, UnitFeatures features) { figures = new List <Figure> { polygon }; Polygon = polygon; props = features; unitCommander = new AutomaticCommander("", CommanderType.Common, this); }
private void Update() { List <Vector2> sites = new List <Vector2>(siteTranses.Select(elem => (Vector2)elem.position)); List <ConvexPolygon> results = new List <ConvexPolygon>(); //線の削除 if (lines.Count > 0) { for (int i = 0; i < lines.Count; ++i) { lineFactory.DeleteLine(lines[i]); } lines.Clear(); } foreach (Vector2 s1 in sites) { ConvexPolygon region = null; //途中計算結果格納用の領域 foreach (Vector2 s2 in sites) { if (s1 == s2) { continue; } //s1とs2の垂直二等分線を求める Line line = Line.PerpendicularBisector(s1, s2); //垂直二等分線による半平面のうち,s1を含む方を求める ConvexPolygon halfPlane = halfPlaneGenerator.Execute(line, s1); if (region == null) { //初回計算時 region = IntersectionOperation.Execute(areaPolygon, halfPlane); } else { //二回目以降 region = IntersectionOperation.Execute(region, halfPlane); } } if (region != null) { results.Add(region); } else { Debug.Log("Region is null"); } } for (int i = 0; i < results.Count; ++i) { results[i].Scale(sites[i], 0.9f); List <Vector3> vertices = results[i].GetVertices3Copy(); vertices.Add(vertices[0]); lines.Add(lineFactory.CreateLine(vertices, Color.green)); } }
public Area(List <object> fig) { var figs = fig.ConvertAll(x => (Figure)x); figures = figs; var points = new List <Point>(); foreach (var figure in figs) { if (figure is Point) { points.Add((Point)figure); } else if (figure is ConvexPolygon) { points.AddRange(((ConvexPolygon)figure).Points); } else if (figure is Circle) { points.Add(new Point(((Circle)figure).Center.X + ((Circle)figure).Radius, ((Circle)figure).Center.Y)); points.Add(new Point(((Circle)figure).Center.X, ((Circle)figure).Center.Y + ((Circle)figure).Radius)); points.Add(new Point(((Circle)figure).Center.X - ((Circle)figure).Radius, ((Circle)figure).Center.Y)); points.Add(new Point(((Circle)figure).Center.X, ((Circle)figure).Center.Y - ((Circle)figure).Radius)); } } double minX = points[0].X, maxX = points[0].X, minY = points[0].Y, maxY = points[0].Y; foreach (var point in points) { if (point.X < minX) { minX = point.X; } if (point.X > maxX) { maxX = point.X; } if (point.Y < minY) { minY = point.Y; } if (point.Y > maxY) { maxY = point.Y; } } var listpo = new List <Point>() { new Point(minX, maxY), new Point(minX, minY), new Point(maxX, minY), new Point(maxX, maxY) }; poly = new ConvexPolygon(listpo); }
public Swarmer(float _x, float _y, Color4 _color) : base(ConvexPolygon.Regular(3, 10, (float) - Math.PI / 2), _x, _y) { instinct = new SwarmInstinct(this); SpeedMax = 60; Speed = 60; Angle = (float)Basics.Utils.RandomAngleRad(); angleNext = (float)Basics.Utils.RandomAngleRad(); color = _color; BoundingBox = new BoundingBox(20, 20); }
/// <summary> /// スケールや再分割度の設定 /// </summary> private void Evaluate(float par) { float scale = scaleCurve.Evaluate(par); int division = (int)divisionCurve.Evaluate(par); float t = tCurve.Evaluate(par); ConvexPolygon p = polygonObject.Origin.Scaled(transform.position, scale); //polygonObject.UpdatePolygon(AngleSubdivisionOperation.Execute(p, division)); polygonObject.UpdatePolygon(LerpSubdivisionOperation.Execute(p, division, t)); }
public ConvexPolygon GetEnemyBounds() { List <Vector3> enemyLocations = new List <Vector3>(); enemyLocations.AddRange(hiddenEnemies.Select(enemy => enemy.GetEnemyMarker().GetLocation())); enemyLocations.AddRange(viewableEnemies.Keys.Select(enemy => enemy.InfoGetCenterBottom())); List <Vector2> enemyLocations2D = enemyLocations.Select(location => new Vector2(location.x, location.z)).ToList(); ConvexPolygon enemyBounds = new ConvexPolygon(enemyLocations2D); return(enemyBounds); }
public void Update(double elapsedTime) { _selectedPolygon = _navMesh.FindNearestPolygon(_input.Mouse.Position); if (_input.Mouse.LeftPressed) { if (_selectedPolygon != null) { _selectedPolygon.TryToAddVertex(_input.Mouse.Position); } } }
/// <summary> /// 凸多角形の「左側」または「右側」の上から下に向かう連結辺を作成する /// </summary> public static Edge CreateEdgeChain(ConvexPolygon polygon, bool left) { //凸多角形のy座標最小/最大値の頂点番号を取得 int minYIndex = 0, maxYIndex = 0; polygon.GetYMinMaxindex(ref minYIndex, ref maxYIndex); //凸多角形の辺配列をを前進するか後退するかを決定 bool ccw = polygon.rotation == ConvexPolygon.Rotation.CCW; bool forward = (ccw && left) || (!ccw && !left); //要素の準備 int size = polygon.GetEdgeCount(); int nextIndex = 0; Edge firstEdge = null; Edge lastEdge = null; //最上点の位置から開始し,最下点に到達するまで続ける for (int i = maxYIndex; i != minYIndex; i = nextIndex) { Edge edge = new Edge(); if (forward) { //前進 nextIndex = (i + 1) % size; edge.segment = polygon.GetEdge(i); edge.index = i; } else { //後退 nextIndex = (i + size - 1) % size; edge.segment = polygon.GetEdge(nextIndex); edge.index = nextIndex; } //辺の始点と終点 edge.startPoint = polygon.GetVertex(i); edge.endPoint = polygon.GetVertex(nextIndex); //辺の連結処理 if (firstEdge == null) { firstEdge = edge; } else { lastEdge.next = edge; } lastEdge = edge; } return(firstEdge); }
/// <summary> /// Метод серилизации для Полигона /// </summary> /// <param name="polygon">Полигон</param> /// <returns>Xml Element</returns> public static XElement Serialize(this ConvexPolygon polygon) { var el = new XElement("ConvexPolygon"); var points = polygon.Points.Select(x => x.X.ToString() + " " + x.Y.ToString()).ToList().Aggregate((x, y) => x + " " + y); var normals = polygon.Normals.Select(x => x.X.ToString() + " " + x.Y.ToString()).ToList().Aggregate((x, y) => x + " " + y); el.SetAttributeValue("Points", points); el.SetAttributeValue("Normals", normals); return(el); }
public void AddExistingData( List<RecProductionFormStd> existingData ) { if( existingData == null || existingData.Count == 0 ) { return; } // We assume that we have cast ONLY on a singe bed on a certain day & shiff List<RecTMElement> elements = GetElements( existingData ); if( elements != null && elements.Count > 0 ) { ConvexPolygonList polygons = new ConvexPolygonList( elements ); polygons.Sort(delegate(ConvexPolygon p1, ConvexPolygon p2) { return p1.MaxX.CompareTo(p2.MaxX); }); LastExistingPolygon = polygons[polygons.Count - 1]; } }
public void CastShadow(ConvexPolygon poly, Vector2 position, bool penumbra) { // get the line that blocks light for the blocker and light combination // move the light position towards blocker by its sourceradius to avoid // popping of penumbrae int[] edgeIndices = poly.GetBackfacingEdgeIndices((this.Position + Vector2.Multiply(Vector2.Normalize(position - this.Position), this.Size)) - position); Vector2[] shadowLine = new Vector2[edgeIndices.Length + 1]; shadowLine[0] = position + poly[edgeIndices[0]]; for (int i = 0; i < edgeIndices.Length; i++) shadowLine[i + 1] = position + poly.NextVertex(edgeIndices[i]); // if the light source is completely surrounded by the blocker, don't draw its shadow if (shadowLine.Length == poly.Count + 1) return; // // build penumbrae (soft shadows), cast from the edges // Penumbra rightpenumbra; { Vector2 startdir = extendDir(shadowLine[0] - (this.Position - getLightDisplacement(position, shadowLine[0]))); rightpenumbra.sections = new List<Penumbra.Section>(); rightpenumbra.sections.Add(new Penumbra.Section(shadowLine[0], startdir, 0)); for (int i = 0; i < shadowLine.Length - 1; ++i) { float wanted = Math.Abs(MathUtils.AngleBetween(startdir, getTotalShadowStartDirection(position, shadowLine[i]))); float available = Math.Abs(MathUtils.AngleBetween(startdir, shadowLine[i + 1] - shadowLine[i])); if (wanted < available) { rightpenumbra.sections.Add(new Penumbra.Section( shadowLine[i], getTotalShadowStartDirection(position, shadowLine[i]), 1)); break; } else { rightpenumbra.sections.Add(new Penumbra.Section( shadowLine[i + 1], extendDir(shadowLine[i + 1] - shadowLine[i]), available / wanted)); } } } Penumbra leftpenumbra; { Vector2 startdir = extendDir(shadowLine[shadowLine.Length - 1] - (this.Position - getLightDisplacement(position, shadowLine[shadowLine.Length - 1]))); leftpenumbra.sections = new List<Penumbra.Section>(); leftpenumbra.sections.Add(new Penumbra.Section( shadowLine[shadowLine.Length - 1], startdir, 0)); for (int i = 0; i < shadowLine.Length - 1; ++i) { float wanted = Math.Abs(MathUtils.AngleBetween(startdir, getTotalShadowStartDirection(position, shadowLine[shadowLine.Length - i - 1]))); float available = Math.Abs(MathUtils.AngleBetween(startdir, shadowLine[shadowLine.Length - i - 2] - shadowLine[shadowLine.Length - i - 1])); if (wanted < available) { leftpenumbra.sections.Add(new Penumbra.Section( shadowLine[shadowLine.Length - i - 1], getTotalShadowStartDirection(position, shadowLine[shadowLine.Length - i - 1]), 1)); break; } else { leftpenumbra.sections.Add(new Penumbra.Section( shadowLine[shadowLine.Length - i - 2], extendDir(shadowLine[shadowLine.Length - i - 2] - shadowLine[shadowLine.Length - i - 1]), available / wanted)); } } } // // build umbrae (hard shadows), cast between the insides of penumbrae // Umbra umbra; umbra.sections = new List<Umbra.Section>(); umbra.sections.Add(new Umbra.Section(rightpenumbra.sections.Last()._base, rightpenumbra.sections.Last().direction)); for (int i = rightpenumbra.sections.Count - 1; i < shadowLine.Length - leftpenumbra.sections.Count + 1; i++) umbra.sections.Add(new Umbra.Section(shadowLine[i], extendDir(Vector2.Multiply(leftpenumbra.sections.Last().direction + rightpenumbra.sections.Last().direction, 0.5f)))); umbra.sections.Add(new Umbra.Section(leftpenumbra.sections.Last()._base, leftpenumbra.sections.Last().direction)); // // draw shadows to alpha // umbra.draw(); rightpenumbra.draw(); leftpenumbra.draw(); }
public void PrepareLastElement() { if( null == this.ProductionCast || null == this.ProductionCast.Elements ) { this.lastExistingPolygon = null; return; } this.lastExistingPolygon = this.ProductionCast.LastElement; }
public void AddShadowCaster(Rectangle rect) { ConvexPolygon poly = new ConvexPolygon( new Vector2(-rect.Width/2, -rect.Height/2), new Vector2(rect.Width/2, -rect.Height/2), new Vector2(rect.Width/2, rect.Height/2), new Vector2(-rect.Width/2, rect.Height/2)); casters.Add(new ShadowCaster() { poly = poly, position = new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2) }); }
public void AddShadowCaster(ConvexPolygon poly, Vector2 position) { casters.Add(new ShadowCaster() { poly = poly, position = position }); }