11#ifndef JAU_MATH_GEOM_GEOM2F_HPP_
12#define JAU_MATH_GEOM_GEOM2F_HPP_
23 using namespace jau::math;
43 return (b.
x - a.
x) * (c.
y - a.
y) - (b.
y - a.
y) * (c.
x - a.
x);
50 const double area =
tri_area(a, b, c);
92 :
p0( p0_ ),
p1( p1_ ) {}
108 constexpr float length() const noexcept {
116 return (
p1 -
p0).angle();
124 const Vec2f b = o.p1 - o.p0;
130 const float a_move =
angle();
136 std::string
toString() const noexcept
override {
return "L[" +
p0.toString() +
", " +
p1.toString() +
"]"; }
146 bool is_on_line(
const Point2f& p2)
const noexcept {
150 const float perpDotProduct = (p0.
x - p2.x) * (p1.
y - p2.y) - (p0.
y - p2.y) * (p1.
x - p2.x);
154 bool is_on_line2(
const Point2f& p2)
const noexcept {
155 if ( p2.x <= std::max(p0.
x, p1.
x) && p2.x >= std::min (p0.
x, p1.
x) &&
156 p2.y <= std::max(p0.
y, p2.y) && p2.y >= std::min (p0.
y, p1.
y) )
169 if ( !( (
p0.x <= p2.x && p2.x <=
p1.x ) || (
p1.x <= p2.x && p2.x <=
p0.x ) ) ) {
173 if ( !( (
p0.y <= p2.y && p2.y <=
p1.y ) || (
p1.y <= p2.y && p2.y <=
p0.y ) ) ) {
177 return is_on_line(p2);
187 const Point2f& q,
const Point2f& q2,
const bool do_collinear=
false)
190 constexpr const float eps = std::numeric_limits<float>::epsilon();
191 const Vec2f r = p2 - p;
192 const Vec2f s = q2 - q;
193 const float rxs = r.
cross(s);
196 if ( do_collinear ) {
197 const Vec2f q_p = q - p;
198 const float qpxr = q_p.
cross(r);
204 const float qp_dot_r = q_p.
dot(r);
205 const float pq_dot_s = p_q.
dot(s);
208 if ( ( eps <= qp_dot_r && qp_dot_r - r.
dot(r) <= eps ) ||
209 ( eps <= pq_dot_s && pq_dot_s - s.
dot(s) <= eps ) )
229 const Vec2f q_p = q - p;
230 const float qpxr = q_p.
cross(r);
236 const float t = q_p.
cross(s) / rxs;
239 const float u = qpxr / rxs;
242 if ( (eps <= t && t - 1 <= eps) && (eps <= u && u - 1 <= eps) )
245 result = p + (
t * r);
276 const pixel::orientation_t or_3 =
orientation(o.p0, o.p1,
p0);
277 const pixel::orientation_t or_4 =
orientation(o.p0, o.p1,
p1);
280 if (or_1 != or_2 && or_3 != or_4) {
281 pixel::log_printf(
"i-g-0: %s with %s\n",
toString().c_str(), o.toString().c_str());
289 if (or_1 == pixel::orientation_t::COL && is_on_line (o.p0)) {
290 pixel::log_printf(
"i-s-1: %s with %s\n",
toString().c_str(), o.toString().c_str());
295 if (or_2 == pixel::orientation_t::COL && is_on_line (o.p1)) {
296 pixel::log_printf(
"i-s-2: %s with %s\n",
toString().c_str(), o.toString().c_str());
301 if (or_3 == pixel::orientation_t::COL && o.is_on_line (
p0)) {
302 pixel::log_printf(
"i-s-3: %s with %s\n",
toString().c_str(), o.toString().c_str());
307 if (or_4 == pixel::orientation_t::COL && o.is_on_line (
p1)) {
308 pixel::log_printf(
"i-s-4: %s with %s\n",
toString().c_str(), o.toString().c_str());
328 const float l2 =
p1.dist_sq(
p0);
329 if( l2 < std::numeric_limits<float>::epsilon() ) {
338 const float t = std::max(0.0f, std::min(1.0f, pv.
dot(wv) / l2));
340 return p.dist(projection);
347 const Vec2f aabb_center = (
box.bl +
box.tr) * 0.5f;
348 const Vec2f lseg_center =
p0 + d;
349 const Vec2f c = lseg_center - aabb_center;
350 const Vec2f ad(std::abs(d.
x), std::abs(d.
y));
351 if (std::abs(c.
x) > e.
x + ad.
x) {
354 if (std::abs(c.
y) > e.
y + ad.
y) {
365 if (std::abs(d.
x * c.
y - d.
y * c.
x) > e.
x * ad.
y + e.
y * ad.
x + std::numeric_limits<float>::epsilon()) {
377 cross_normal = (
p1 -
p0).normal_ccw().normalize();
378 const Vec2f v_in = cross_point - in.p0;
379 reflect_out = v_in - ( 2.0f * v_in.
dot(cross_normal) * cross_normal );
394 if( lt.
intersection(reflect_out, cross_normal, cross_point, *
this) ) {
397 if( lb.
intersection(reflect_out, cross_normal, cross_point, *
this) ) {
401 if( lb.
intersection(reflect_out, cross_normal, cross_point, *
this) ) {
404 if( lt.
intersection(reflect_out, cross_normal, cross_point, *
this) ) {
413 const float dl = ll.distance(
p0 );
415 if( lr.
intersection(reflect_out, cross_normal, cross_point, *
this) ) {
418 if( ll.intersection(reflect_out, cross_normal, cross_point, *
this) ) {
422 if( ll.intersection(reflect_out, cross_normal, cross_point, *
this) ) {
425 if( lr.
intersection(reflect_out, cross_normal, cross_point, *
this) ) {
444 virtual void rotate(
const float rad)
noexcept = 0;
447 virtual void move(
const float dx,
const float dy)
noexcept = 0;
448 virtual bool tick(
const float dt)
noexcept { (void)dt;
return true; }
478 return "disk[c " +
center.toString() +
479 ", r " + std::to_string(
radius) +
498 return o.intersects(
box());
502 return box().intersects(o);
506 return box().intersects(o.box());
510 if( !in.intersects(
box() ) ) {
514 const float dx = in.p1.x - in.p0.x;
515 const float dy = in.p1.y - in.p0.y;
516 cross_normal =
Vec2f(-dy, dx).normalize();
517 const Vec2f v_in = in.p1 - in.p0;
519 reflect_out = -1.0f * v_in;
523 void rotate(
const float rad)
noexcept override {
536 void move(
const float dx,
const float dy)
noexcept override {
566 Rect2f(
const Point2f& tl_,
const float width,
const float height,
const float radians)
noexcept
615 void move(
const float dx,
const float dy)
noexcept override {
623 void rotate(
const float radians)
noexcept override {
627 const float cos = std::cos(radians);
628 const float sin = std::sin(radians);
629 p_a.rotate(sin, cos, p);
630 p_b.rotate(sin, cos, p);
631 p_c.rotate(sin, cos, p);
632 p_d.rotate(sin, cos, p);
638 const float dx = p.
x -
p_a.x;
639 const float dy = p.
y -
p_a.y;
644 return box().contains(o);
648 return o.intersects(
box());
652 return box().intersects(o);
656 return box().intersects(o.box());
663 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
670 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
677 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
684 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
695 const Vec2f added_size = (l.p1 - l.p0).normal_ccw().normalize() * in_radius;
698 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
705 const Vec2f added_size = (l.p1 - l.p0).normal_ccw().normalize() * in_radius;
708 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
715 const Vec2f added_size = (l.p1 - l.p0).normal_ccw().normalize() * in_radius;
718 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
725 const Vec2f added_size = (l.p1 - l.p0).normal_ccw().normalize() * in_radius;
728 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
736 return "rect[a " +
p_a.toString() +
737 ", b " +
p_b.toString() +
738 ", c " +
p_c.toString() +
739 ", d " +
p_d.toString() +
767 for(
size_t i=0; i<
p_list.size()-1; ++i) {
776 this->p_center = c /
static_cast<float>(n);
802 void move(
const float dx,
const float dy)
noexcept override {
809 void rotate(
const float radians)
noexcept override {
810 const float cos = std::cos(radians);
811 const float sin = std::sin(radians);
814 for(
size_t i=0; i<
p_list.size(); ++i) {
832 return box().contains(o);
836 return o.intersects(
box());
840 return box().intersects(o);
844 return box().intersects(o.box());
852 for(
size_t i=1; i<
p_list.size(); ++i) {
855 if( l.intersects(o) ) {
864 const LineSeg2f& in)
const noexcept override {
869 for(
size_t i=1; i<
p_list.size(); ++i) {
872 if( l.intersection(reflect_out, cross_normal, cross_point, in) ) {
881 return "linestrip[center " +
p_center.toString() +
882 ", points " + std::to_string(
p_list.size())+
"]"; }
constexpr value_type cross(const Vector2F &o) const noexcept
Returns cross product of this vectors and the given one, i.e.
constexpr_cxx26 value_type angle() const noexcept
Return the direction angle of this vector in radians.
constexpr value_type dot(const Vector2F &o) const noexcept
Return the dot product of this vector and the given one.
static constexpr_cxx26 Vector2F from_length_angle(const value_type magnitude, const value_type radians) noexcept
Axis Aligned Bounding Box.
AABBox2f & resize(const AABBox2f &o) noexcept
Resize the AABBox to encapsulate another AABox.
Animated geometric object.
virtual void move(const float dx, const float dy) noexcept=0
virtual void move(const Point2f &d) noexcept=0
virtual void move_dir(const float d) noexcept=0
virtual void rotate(const float rad) noexcept=0
virtual bool tick(const float dt) noexcept
void move(const float dx, const float dy) noexcept override
void rotate(const float rad) noexcept override
void move(const Point2f &d) noexcept override
Disk2f(const Point2f &c_, const float r_)
Point2f center
Imagine a circle ;-)
std::string toString() const noexcept override
bool intersection(Vec2f &reflect_out, Vec2f &cross_normal, Point2f &cross_point, const LineSeg2f &in) const noexcept override
Return whether this object intersects with the given line segment and if intersecting,...
void move_dir(const float d) noexcept override
bool intersects(const AABBox2f &o) const noexcept override
bool intersects(const LineSeg2f &o) const noexcept override
float dir_angle
direction angle in radians
Disk2f(float x, float y, const float r_)
void set_center(const Point2f &p)
bool intersects(const Geom2f &o) const noexcept override
bool contains(const Point2f &o) const noexcept override
AABBox2f box() const noexcept override
virtual AABBox2f box() const noexcept=0
virtual ~Geom2f()=default
virtual bool intersection(Vec2f &reflect_out, Vec2f &cross_normal, Point2f &cross_point, const LineSeg2f &in) const noexcept=0
Return whether this object intersects with the given line segment and if intersecting,...
virtual std::string toString() const noexcept=0
virtual bool intersects(const LineSeg2f &o) const noexcept=0
virtual bool contains(const Point2f &o) const noexcept=0
bool intersects(const LineSeg2f &o) const noexcept override
Return true if this line segment intersect with the given line segment.
bool contains(const Point2f &p2) const noexcept override
Test intersection between this line segment and the give point.
float angle() const noexcept
Return the angle of this line segment in radians.
constexpr LineSeg2f() noexcept
float angle(const LineSeg2f &o) const noexcept
Return the angle between two line segments in radians.
bool intersection(const AABBox2f &box, Vec2f &reflect_out, Vec2f &cross_normal, Point2f &cross_point) const noexcept
bool intersects(const Geom2f &o) const noexcept override
constexpr float length() const noexcept
Return the length of this line segment, i.e.
bool intersection(Vec2f &reflect_out, Vec2f &cross_normal, Point2f &cross_point, const LineSeg2f &in) const noexcept override
Return whether this object intersects with the given line segment and if intersecting,...
std::string toString() const noexcept override
bool intersects(Point2f &result, const LineSeg2f &o) const noexcept
Compute intersection between two lines segments.
constexpr LineSeg2f(const Point2f &p0_, const Point2f &p1_) noexcept
constexpr LineSeg2f & operator*=(const float s) noexcept
Scale this line segment with given scale factor.
AABBox2f box() const noexcept override
Create an AABBox with given lineseg.
bool intersects(const AABBox2f &box) const noexcept override
float distance(Point2f p) const noexcept
Returns minimum distance between this line segment and given point p.
void rotate(const float radians) noexcept override
bool intersection(Vec2f &reflect_out, Vec2f &cross_normal, Point2f &cross_point, const LineSeg2f &in) const noexcept override
Return whether this object intersects with the given line segment and if intersecting,...
bool intersects(const AABBox2f &o) const noexcept override
void normalize_center() noexcept
bool intersects_lineonly(const LineSeg2f &o) const noexcept
void move_dir(const float d) noexcept override
void move(const Point2f &d) noexcept override
bool contains(const Point2f &o) const noexcept override
void move(const float dx, const float dy) noexcept override
std::string toString() const noexcept override
float dir_angle
direction angle in radians
AABBox2f box() const noexcept override
bool intersects(const Geom2f &o) const noexcept override
void set_center(const Point2f &p)
std::vector< Point2f > p_list
bool intersects(const LineSeg2f &o) const noexcept override
LineStrip2f(const Point2f ¢er, const float angle) noexcept
bool contains(const Point2f &o) const noexcept override
float dir_angle
direction angle in radians
void move(const Point2f &d) noexcept override
Rect2f(const Point2f &tl_, const float width, const float height, const float radians) noexcept
bool intersects(const AABBox2f &o) const noexcept override
bool intersection(Vec2f &reflect_out, Vec2f &cross_normal, Point2f &cross_point, const LineSeg2f &in, const float in_radius) const noexcept
AABBox2f box() const noexcept override
bool intersects(const LineSeg2f &o) const noexcept override
bool intersection(Vec2f &reflect_out, Vec2f &cross_normal, Point2f &cross_point, const LineSeg2f &in) const noexcept override
Return whether this object intersects with the given line segment and if intersecting,...
Rect2f(const Point2f &tl_, const Point2f &tr_, const Point2f &bl_, const Point2f &br_) noexcept
std::string toString() const noexcept override
bool intersects(const Geom2f &o) const noexcept override
Point2f p_c
Unrotated bottom-left.
void move(const float dx, const float dy) noexcept override
void move_dir(const float d) noexcept override
Point2f p_b
Unrotated top-right.
void rotate(const float radians, const Point2f &p) noexcept
Point2f p_d
Unrotated bottom_right.
Point2f p_a
Unrotated, clockwise (CW):
Rect2f(const Point2f &tl_, const float width, const float height) noexcept
void set_top_left(const Point2f &p)
void rotate(const float radians) noexcept override
std::enable_if_t< std::is_floating_point_v< T >, bool > constexpr is_zero(const T &a, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if the given value is less than epsilon, w/ epsilon > 0.
std::shared_ptr< Geom2f > Geom2f_ref
std::vector< AGeom2f_ref > AGeom2f_list
std::vector< Geom2f_ref > Geom2f_list
constexpr orientation_t orientation(const Point2f &a, const Point2f &b, const Point2f &c) noexcept
Return the orientation of the given point triplet a, b and c using triArea()
std::shared_ptr< Disk2f > Disk2f_ref
std::shared_ptr< AGeom2f > AGeom2f_ref
std::shared_ptr< LineStrip2f > LineStrip2f_ref
constexpr double tri_area(const Point2f &a, const Point2f &b, const Point2f &c)
Computes oriented double area of a triangle, i.e.
std::shared_ptr< Rect2f > Rect2f_ref