我想为我的两个形状Rock和Triangle创建一个边界圆Region。当它们关闭时,我要执行相交测试,并将两者从窗体中删除。
我已经创建了一个区域链接列表,但是当我渲染它们时,它会在通过表单时留下形状的路径。我想在形状的点周围画一个圆,以显示相交是否会发生。
abstract class ShapeBase
{
double min = -3.00;
double max = 3.00;
double minX = -2.5;
double maxX = 2.5;
public double m_fRot;
public double m_fRotInc;
//x velocity
public double m_fXSpeed;
//y velocity
public double m_fYSpeed;
public static Random s_rnd;
//size
public const int TILESIZE = 100;
bool IsMarkedForDeath
{
get { return IsMarkedForDeath; }
set {IsMarkedForDeath = value; }
}
public PointF Pos
{
get;
private set;
}
//contructor should accept a PointF for position
public ShapeBase(PointF p)
{
s_rnd = new Random();
Pos = p; //position as the provided position
m_fRot = 0; //current rotation as 0
m_fRotInc = s_rnd.NextDouble() * (max - min) + min; //rotation increment from -3.00 to 3.00
m_fXSpeed = s_rnd.NextDouble() * (maxX - minX) + minX;//x/y speed values fro -2.5 to 2.5
m_fYSpeed = s_rnd.NextDouble() * (maxX - minX) + minX;
}
//makes original graphicspath
static public GraphicsPath GenModel(int vertices, float variance)
{
double dAngle = 0;
PointF[] triPoints = new PointF[vertices];
Random rnd = new Random();
//rock
if (variance > 1)
{
for (int i = 0; i < vertices; ++i, dAngle += (2 * Math.PI) / vertices)
{
triPoints[i] = new PointF((float)Math.Cos(dAngle) * TILESIZE * (float)(rnd.NextDouble() * 0.5 + 0.1), (float)Math.Sin(dAngle) * TILESIZE * (float)(rnd.NextDouble() * 0.5 + 0.1));
}
}
//triangle
else
{
for (int i = 0; i < vertices; ++i, dAngle += (2 * Math.PI) / vertices)
{
triPoints[i] = new PointF((float)Math.Cos(dAngle) * TILESIZE, (float)Math.Sin(dAngle) * TILESIZE);
}
}
GraphicsPath ModelPath = new GraphicsPath();
ModelPath.AddPolygon(triPoints);
ModelPath.CloseFigure();
return ModelPath;
}
//produce graphics path for rendering
//clone genmodel path
virtual public GraphicsPath GetPath()
{
////srt in here
GraphicsPath _Path = new GraphicsPath();
//matrix is used to apply a transformation
//SRT - scale rotate transform
//Matrix m = new Matrix();
//m.Rotate(m_fRot);
//_Path.Transform(new Matrix());
return _Path;
}
//render method will fill getpath return value with a provided colour
public void Render(Graphics g, Color colour)
{
g.FillPath(new SolidBrush(colour), GetPath());
}
//accept a size and move the shape according to current speed values
//for any violation of bounds, speed value will flip
public void Tick(Size _size)
{
m_fRot += m_fRotInc;
Pos = new PointF((float)(Pos.X + m_fXSpeed), (float)(Pos.Y + m_fYSpeed));
if (Pos.X + TILESIZE > _size.Width || Pos.X + TILESIZE < 0)
{
m_fXSpeed *= -1;
m_fYSpeed *= -1;
}
if (Pos.Y + TILESIZE > _size.Height || Pos.Y + TILESIZE < 0)
{
m_fXSpeed *= -1;
m_fYSpeed *= -1;
}
}
public static double Distance(ShapeBase shape1, ShapeBase shape2)
{
double a = (shape2.Pos.X - shape1.Pos.X);
double b = (shape2.Pos.Y - shape1.Pos.Y);
double c = Math.Pow(a, 2) + Math.Pow(b, 2);
return Math.Sqrt(c); //c= √a^2+b^2
}
}
class Triangle : ShapeBase
{
static readonly GraphicsPath s_model; //hold model for triangle shape
static Triangle()
{
//generate model
s_model = GenModel(3, 0);
}
//set the position to the provided pointf
public Triangle(PointF position) : base(position)
{
}
public override GraphicsPath GetPath()
{
GraphicsPath workingCopy = (GraphicsPath)s_model.Clone();
Matrix mat = new Matrix();
mat.Reset();
mat.Translate(Pos.X, Pos.Y);
mat.Rotate((float)m_fRot);
workingCopy.Transform(mat);
return workingCopy;
}
}
class Rock : ShapeBase
{
public GraphicsPath _model;
//send in location to base class (ShapeBase)
public Rock(PointF location): base(location)
{
_model = GenModel(s_rnd.Next(4,13),2);
}
public override GraphicsPath GetPath()
{
GraphicsPath wCopy = (GraphicsPath)_model.Clone();
Matrix mat = new Matrix();
mat.Reset();
mat.Translate(Pos.X, Pos.Y);
mat.Rotate((float)m_fRot);
wCopy.Transform(mat);
return wCopy;
}
}
}```
``` public partial class Form1 : Form
{
int count = 1000;
LinkedList<Region> Regions = new LinkedList<Region>();
List<ShapeBase> ShapeList = new List<ShapeBase>();//collection of your choosing
LinkedList<Region> Intersections = new LinkedList<Region>(); //hold all intersections
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
Random random = new Random();
PointF coordinates = Form.MousePosition;
if (e.Button == MouseButtons.Left)
{
//if shift key pressed, create a Rock
if (ModifierKeys == Keys.Shift)
{
Rock r = new Rock(coordinates);
if (!ShapeList.Contains(r))
{
ShapeList.Add(r);
}
}
//otherwise, create a Triangle
else
{
ShapeList.Add(new Triangle(coordinates));
}
}
if (e.Button == MouseButtons.Right)
{
//if shift key pressed, create a Rock
if (ModifierKeys == Keys.Shift)
{
Rock r = new Rock(new PointF(random.Next(ClientRectangle.Width), random.Next(ClientRectangle.Height)));
if (!ShapeList.Contains(r))
{
while (count > 0)
{
ShapeList.Add(r);
count--;
}
}
}
//otherwise, create a Triangle
else
{
ShapeList.Add(new Triangle(coordinates));
}
}
}
private void Timer1_Tick(object sender, EventArgs e)
{
Graphics gr = CreateGraphics();
using (BufferedGraphicsContext bgc = new BufferedGraphicsContext())
{
// bind a back-buffer to the primary surface, spec size to create as client size
using (BufferedGraphics bg = bgc.Allocate(gr, this.DisplayRectangle))
{
//clear the back buffer
bg.Graphics.Clear(Color.Black);
// render all previous intersections between shapes in dark blue
//tick each shape
//render the shapes
foreach(ShapeBase shape in ShapeList)
{
shape.Tick(ClientRectangle.Size);
//triangle is aqua
if (shape is Triangle)
{
shape.Render(bg.Graphics, Color.Aqua);
}
//rock is green
if (shape is Rock)
{
shape.Render(bg.Graphics, Color.Green);
}
Regions.AddFirst(new Region(shape.GetPath()).Clone());
if (ShapeBase.Distance(shape, ShapeList.ne)
Text = $"{shape.Pos.X} , {shape.Pos.Y}";
}
//perform intersection test for each shape against every other shape
//make region for shape from getpath
// flip back-buffer to front buffer
bg.Render();
//remove all shapes that have been marked for removal with a lambda
}
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
}
}```