Completed Shapes
This commit is contained in:
parent
1e62ef5688
commit
05b49929ba
4 changed files with 120 additions and 61 deletions
|
|
@ -1,4 +1,7 @@
|
|||
using System.Numerics;
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using SimpleDrawing;
|
||||
|
||||
namespace Shapes.Shapes;
|
||||
|
||||
|
|
@ -7,33 +10,40 @@ public sealed class Circle : Shape
|
|||
private const int RadiusMin = 5;
|
||||
private const int RadiusMax = 100;
|
||||
|
||||
public Circle(Vector2 position, Vector2 scale)
|
||||
: base(position, new Vector2(
|
||||
Math.Clamp(scale.X, RadiusMin, RadiusMax),
|
||||
Math.Clamp(scale.Y, RadiusMin, RadiusMax)))
|
||||
public Circle(Point position, Point scale,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
: base(position, new Point(Math.Clamp(scale.X, RadiusMin, RadiusMax),
|
||||
Math.Clamp(scale.Y, RadiusMin, RadiusMax)),
|
||||
lineThickness, lineColor, fillColor)
|
||||
{
|
||||
// Clamp the scale values directly in the base ctor
|
||||
// Just clamping the size.Y as default. Not actually needed
|
||||
}
|
||||
|
||||
public override bool DrawSelf(Vector2 position = default, Vector2 scale = default)
|
||||
public override bool DrawSelf(Point position = default, Point scale = default,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
{
|
||||
if (position == default)
|
||||
{
|
||||
position = Position;
|
||||
}
|
||||
|
||||
if (scale == default)
|
||||
{
|
||||
scale = Scale;
|
||||
}
|
||||
double lineThicknessUsed = lineThickness ?? LineThickness ?? DefaultLineThickness;
|
||||
IBrush? lineColorUsed = lineColor ?? LineColor;
|
||||
IBrush? fillColorUsed = fillColor ?? FillColor;
|
||||
|
||||
// TODO
|
||||
return false;
|
||||
return LeoCanvas.DrawCircle(new Point(position.X, position.Y), scale.X,
|
||||
lineThicknessUsed, lineColorUsed, fillColorUsed);
|
||||
}
|
||||
|
||||
public override bool PointInShape(Vector2 mousePoint)
|
||||
public override bool PointInShape(Point mousePoint)
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
double distanceSquared = Math.Pow(mousePoint.X - Position.X, 2) + Math.Pow(mousePoint.Y - Position.Y, 2);
|
||||
|
||||
double radiusSquared = Math.Pow(Scale.X, 2);
|
||||
return distanceSquared <= radiusSquared;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Numerics;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using SimpleDrawing;
|
||||
|
||||
namespace Shapes.Shapes;
|
||||
|
|
@ -8,40 +9,46 @@ public sealed class Rectangle : Shape
|
|||
private const int SideLengthMin = 10;
|
||||
private const int SideLengthMax = 150;
|
||||
|
||||
public Rectangle(Vector2 position, Vector2 scale)
|
||||
: base(position, new Vector2(
|
||||
Math.Clamp(scale.X, SideLengthMin, SideLengthMax),
|
||||
Math.Clamp(scale.Y, SideLengthMin, SideLengthMax)))
|
||||
public Rectangle(Point position, Point scale,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
: base(position, new Point(Math.Clamp(scale.X, SideLengthMin, SideLengthMax),
|
||||
Math.Clamp(scale.Y, SideLengthMin, SideLengthMax)),
|
||||
lineThickness, lineColor, fillColor)
|
||||
{
|
||||
// Clamp the scale values directly in the base ctor
|
||||
}
|
||||
|
||||
public override bool DrawSelf(Vector2 position = default, Vector2 scale = default)
|
||||
public override bool DrawSelf(Point position = default, Point scale = default,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
{
|
||||
if (position == default)
|
||||
{
|
||||
position = Position;
|
||||
}
|
||||
|
||||
if (scale == default)
|
||||
{
|
||||
scale = Scale;
|
||||
}
|
||||
|
||||
return LeoCanvas.DrawRectangle(new(position.X - scale.X/2, position.Y - scale.Y/2), new(scale.X, scale.Y));
|
||||
double lineThicknessUsed = lineThickness ?? LineThickness ?? DefaultLineThickness;
|
||||
IBrush? lineColorUsed = lineColor ?? LineColor;
|
||||
IBrush? fillColorUsed = fillColor ?? FillColor;
|
||||
|
||||
var topLeft = new Point(position.X - scale.X/2, position.Y - scale.Y/2);
|
||||
var bottomRight = new Point(position.X + scale.X/2, position.Y + scale.Y/2);
|
||||
return LeoCanvas.DrawRectangle(topLeft, bottomRight,
|
||||
lineThicknessUsed, lineColorUsed, fillColorUsed);
|
||||
}
|
||||
|
||||
public override bool PointInShape(Vector2 mousePoint)
|
||||
public override bool PointInShape(Point mousePoint)
|
||||
{
|
||||
float halfWidth = Scale.X / 2;
|
||||
float halfHeight = Scale.Y / 2;
|
||||
double halfWidth = Scale.X / 2;
|
||||
double halfHeight = Scale.Y / 2;
|
||||
|
||||
float left = Position.X - halfWidth;
|
||||
float right = Position.X + halfWidth;
|
||||
float top = Position.Y - halfHeight;
|
||||
float bottom = Position.Y + halfHeight;
|
||||
double left = Position.X - halfWidth;
|
||||
double right = Position.X + halfWidth;
|
||||
double top = Position.Y - halfHeight;
|
||||
double bottom = Position.Y + halfHeight;
|
||||
|
||||
// If point is inside shape
|
||||
return mousePoint.X >= left && mousePoint.X <= right &&
|
||||
mousePoint.Y >= top && mousePoint.Y <= bottom;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Numerics;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using SimpleDrawing;
|
||||
|
||||
namespace Shapes.Shapes;
|
||||
|
|
@ -7,39 +8,48 @@ public sealed class Square : Shape
|
|||
{
|
||||
private const int SideLengthMin = 10;
|
||||
private const int SideLengthMax = 120;
|
||||
|
||||
public Square(Vector2 position, Vector2 scale)
|
||||
: base(position, new Vector2(
|
||||
Math.Clamp(scale.X, SideLengthMin, SideLengthMax),
|
||||
Math.Clamp(scale.Y, SideLengthMin, SideLengthMax)))
|
||||
|
||||
public Square(Point position, Point scale,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
: base(position, new Point(Math.Clamp(scale.X, SideLengthMin, SideLengthMax),
|
||||
Math.Clamp(scale.Y, SideLengthMin, SideLengthMax)),
|
||||
lineThickness, lineColor, fillColor)
|
||||
{
|
||||
// Clamp the scale values directly in the base ctor
|
||||
// Just clamping the size.Y as default. Not actually needed
|
||||
}
|
||||
|
||||
public override bool DrawSelf(Vector2 position = default, Vector2 scale = default)
|
||||
|
||||
public override bool DrawSelf(Point position = default, Point scale = default,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
{
|
||||
if (position == default)
|
||||
{
|
||||
position = Position;
|
||||
}
|
||||
|
||||
if (scale == default)
|
||||
{
|
||||
scale = Scale;
|
||||
}
|
||||
double lineThicknessUsed = lineThickness ?? LineThickness ?? DefaultLineThickness;
|
||||
IBrush? lineColorUsed = lineColor ?? LineColor;
|
||||
IBrush? fillColorUsed = fillColor ?? FillColor;
|
||||
|
||||
return LeoCanvas.DrawRectangle(new(position.X - scale.X/2, position.Y - scale.Y/2), new(scale.X, scale.Y));
|
||||
double size = scale.X;
|
||||
var topLeft = new Point(position.X - size/2, position.Y - size/2);
|
||||
var bottomRight = new Point(position.X + size/2, position.Y + size/2);
|
||||
return LeoCanvas.DrawRectangle(topLeft, bottomRight,
|
||||
lineThicknessUsed, lineColorUsed, fillColorUsed);
|
||||
}
|
||||
|
||||
public override bool PointInShape(Vector2 mousePoint)
|
||||
{
|
||||
float halfWidth = Scale.X / 2;
|
||||
float halfHeight = Scale.Y / 2;
|
||||
|
||||
float left = Position.X - halfWidth;
|
||||
float right = Position.X + halfWidth;
|
||||
float top = Position.Y - halfHeight;
|
||||
float bottom = Position.Y + halfHeight;
|
||||
public override bool PointInShape(Point mousePoint)
|
||||
{
|
||||
double halfWidth = Scale.X / 2;
|
||||
double halfHeight = Scale.Y / 2;
|
||||
|
||||
double left = Position.X - halfWidth;
|
||||
double right = Position.X + halfWidth;
|
||||
double top = Position.Y - halfHeight;
|
||||
double bottom = Position.Y + halfHeight;
|
||||
|
||||
// If point is inside shape
|
||||
return mousePoint.X >= left && mousePoint.X <= right &&
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using System.Numerics;
|
||||
using Avalonia;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using SimpleDrawing;
|
||||
|
||||
namespace Shapes.Shapes;
|
||||
|
|
@ -9,33 +9,65 @@ public sealed class Triangle : Shape
|
|||
private const int SideLengthMin = 10;
|
||||
private const int SideLengthMax = 150;
|
||||
|
||||
public Triangle(Vector2 position, Vector2 scale)
|
||||
: base(position, new Vector2(
|
||||
Math.Clamp(scale.X, SideLengthMin, SideLengthMax),
|
||||
Math.Clamp(scale.Y, SideLengthMin, SideLengthMax)))
|
||||
public Triangle(Point position, Point scale,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
: base(position, new Point(Math.Clamp(scale.X, SideLengthMin, SideLengthMax),
|
||||
Math.Clamp(scale.Y, SideLengthMin, SideLengthMax)),
|
||||
lineThickness, lineColor, fillColor)
|
||||
{
|
||||
// Clamp the scale values directly in the base ctor
|
||||
}
|
||||
|
||||
public override bool DrawSelf(Vector2 position = default, Vector2 scale = default)
|
||||
public override bool DrawSelf(Point position = default, Point scale = default,
|
||||
double? lineThickness = null, IBrush? lineColor = null, IBrush? fillColor = null)
|
||||
{
|
||||
if (position == default)
|
||||
{
|
||||
position = Position;
|
||||
}
|
||||
|
||||
if (scale == default)
|
||||
{
|
||||
scale = Scale;
|
||||
}
|
||||
double lineThicknessUsed = lineThickness ?? LineThickness ?? DefaultLineThickness;
|
||||
IBrush? lineColorUsed = lineColor ?? LineColor;
|
||||
IBrush? fillColorUsed = fillColor ?? FillColor;
|
||||
|
||||
// TODO
|
||||
return false;
|
||||
var vertices = CalculateTriangleVertices(position, scale.X);
|
||||
return LeoCanvas.DrawPolygonByPath(vertices, lineThicknessUsed, lineColorUsed, fillColorUsed);
|
||||
}
|
||||
|
||||
public override bool PointInShape(Vector2 mousePoint)
|
||||
public override bool PointInShape(Point mousePoint)
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
var vertices = CalculateTriangleVertices(Position, Scale.X);
|
||||
return IsPointInTriangle(mousePoint, vertices[0], vertices[1], vertices[2]);
|
||||
}
|
||||
|
||||
private static Point[] CalculateTriangleVertices(Point center, double sideLength)
|
||||
{
|
||||
double height = sideLength * Math.Sqrt(3) / 2;
|
||||
double yOffset = height / 3;
|
||||
|
||||
var vertices = new Point[3];
|
||||
vertices[0] = new Point(center.X, center.Y - height + yOffset);
|
||||
vertices[1] = new Point(center.X - sideLength / 2, center.Y + yOffset);
|
||||
vertices[2] = new Point(center.X + sideLength / 2, center.Y + yOffset);
|
||||
|
||||
return vertices;
|
||||
}
|
||||
|
||||
// Ripped from https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
|
||||
// very nice & self written code :)
|
||||
// Double is used instead of float to avoid casting. Unfortunately, float isn't supported in Avalonia.Base.Point
|
||||
// Double is worse in performance than float, if you don't need high precision and run it in a loop like GameDev
|
||||
private static bool IsPointInTriangle(Point p, Point a, Point b, Point c)
|
||||
{
|
||||
double d = (b.Y - c.Y) * (a.X - c.X) + (c.X - b.X) * (a.Y - c.Y);
|
||||
|
||||
double alpha = ((b.Y - c.Y) * (p.X - c.X) + (c.X - b.X) * (p.Y - c.Y)) / d;
|
||||
double beta = ((c.Y - a.Y) * (p.X - c.X) + (a.X - c.X) * (p.Y - c.Y)) / d;
|
||||
double gamma = 1 - alpha - beta;
|
||||
|
||||
return alpha >= 0 && beta >= 0 && gamma >= 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue