Ray-casting algorithm: Difference between revisions

Content added Content deleted
Line 88: Line 88:


=={{header|C}}==
=={{header|C}}==

Required includes and definitions:
Required includes and definitions:

<lang c>#include <stdio.h>
<lang c>#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
Line 211: Line 209:


The test's output reveals the meaning of <cite>coherent results</cite>: a point on the leftmost vertical side of the square (coordinate 0,5) is considered outside; while a point on the rightmost vertical side of the square (coordinate 10,5) is considered inside, but on the top-right vertex (coordinate 10,10), it is considered outside again.
The test's output reveals the meaning of <cite>coherent results</cite>: a point on the leftmost vertical side of the square (coordinate 0,5) is considered outside; while a point on the rightmost vertical side of the square (coordinate 10,5) is considered inside, but on the top-right vertex (coordinate 10,10), it is considered outside again.
=={{header|D}}==
Modified from the Python version.
<lang d>import std.stdio, std.math, std.algorithm, std.conv, std.string;

struct Point { double x, y; }
struct Edge { Point a, b; } // Figure edge from a to b
struct Figure { string name; Edge[] edges; }

enum double EPS = 0.00001;

bool rayIntersectSeg(Point p, Edge edge) {
with (edge) { // puts a and b in the namespace
if (a.y > b.y)
swap(a, b);
if (p.y == a.y || p.y == b.y)
p = Point(p.x, p.y + EPS);

if ((p.y > b.y || p.y < a.y) || (p.x > max(a.x, b.x)))
return false;

if (p.x < min(a.x, b.x))
return true;
else {
double m_blue, m_red;
if (abs(a.x - b.x) > double.min)
m_red = (b.y - a.y) / (b.x - a.x);
else
m_red = double.max;

if (abs(a.x - p.x) > double.min)
m_blue = (p.y - a.y) / (p.x - a.x);
else
m_blue = double.max;

return m_blue >= m_red;
}
}
}

bool isPointInside(const Point p, const Figure poly) {
int tot;
foreach (edge; poly.edges)
tot += rayIntersectSeg(p, edge);
return tot % 2 == 1;
}

void polyPrettyPrint(Figure poly) {
writefln("Figure(name=\"%s\", edges=(", poly.name);
writeln(" ", to!string(poly.edges, "", "\n ", ""), "\n ))");
}

void main() {
enum polys = [
Figure("Square", [
Edge(Point(0, 0), Point(10, 0)),
Edge(Point(10, 0), Point(10, 10)),
Edge(Point(10, 10), Point(0, 10)),
Edge(Point(0, 10), Point(0, 0))
]),
Figure("Square hole", [
Edge(Point(0, 0), Point(10, 0)),
Edge(Point(10, 0), Point(10, 10)),
Edge(Point(10, 10), Point(0, 10)),
Edge(Point(0, 10), Point(0, 0)),
Edge(Point(2.5, 2.5), Point(7.5, 2.5)),
Edge(Point(7.5, 2.5), Point(7.5, 7.5)),
Edge(Point(7.5, 7.5), Point(2.5, 7.5)),
Edge(Point(2.5, 7.5), Point(2.5, 2.5))
]),
Figure("Strange", [
Edge(Point(0, 0), Point(2.5, 2.5)),
Edge(Point(2.5, 2.5), Point(0, 10)),
Edge(Point(0, 10), Point(2.5, 7.5)),
Edge(Point(2.5, 7.5), Point(7.5, 7.5)),
Edge(Point(7.5, 7.5), Point(10, 10)),
Edge(Point(10, 10), Point(10, 0)),
Edge(Point(10, 0), Point(2.5, 2.5))
]),
Figure("Exagon", [
Edge(Point(3, 0), Point(7, 0)),
Edge(Point(7, 0), Point(10, 5)),
Edge(Point(10, 5), Point(7, 10)),
Edge(Point(7, 10), Point(3, 10)),
Edge(Point(3, 10), Point(0, 5)),
Edge(Point(0, 5), Point(3, 0))
])
];

enum testPoints = [Point(5, 5), Point(5, 8), Point(-10, 5),
Point(0, 5), Point(10, 5), Point(8, 5),
Point(10, 10)];

writeln("Testing whether points are within figures:\n");
foreach (poly; polys) {
polyPrettyPrint(poly);
writeln(" Point inside poly?");
foreach (p; testPoints)
writeln(" ", to!string(p), ": ", isPointInside(p, poly));
writeln();
}
}</lang>
Output:
<pre>Testing whether points are within figures:

Figure(name="Square", edges=(
Edge(Point(0, 0), Point(10, 0))
Edge(Point(10, 0), Point(10, 10))
Edge(Point(10, 10), Point(0, 10))
Edge(Point(0, 10), Point(0, 0))
))
Point inside poly?
Point(5, 5): true
Point(5, 8): true
Point(-10, 5): false
Point(0, 5): false
Point(10, 5): true
Point(8, 5): true
Point(10, 10): false

Figure(name="Square hole", edges=(
Edge(Point(0, 0), Point(10, 0))
Edge(Point(10, 0), Point(10, 10))
Edge(Point(10, 10), Point(0, 10))
Edge(Point(0, 10), Point(0, 0))
Edge(Point(2.5, 2.5), Point(7.5, 2.5))
Edge(Point(7.5, 2.5), Point(7.5, 7.5))
Edge(Point(7.5, 7.5), Point(2.5, 7.5))
Edge(Point(2.5, 7.5), Point(2.5, 2.5))
))
Point inside poly?
Point(5, 5): false
Point(5, 8): true
Point(-10, 5): false
Point(0, 5): false
Point(10, 5): true
Point(8, 5): true
Point(10, 10): false

Figure(name="Strange", edges=(
Edge(Point(0, 0), Point(2.5, 2.5))
Edge(Point(2.5, 2.5), Point(0, 10))
Edge(Point(0, 10), Point(2.5, 7.5))
Edge(Point(2.5, 7.5), Point(7.5, 7.5))
Edge(Point(7.5, 7.5), Point(10, 10))
Edge(Point(10, 10), Point(10, 0))
Edge(Point(10, 0), Point(2.5, 2.5))
))
Point inside poly?
Point(5, 5): true
Point(5, 8): false
Point(-10, 5): false
Point(0, 5): false
Point(10, 5): true
Point(8, 5): true
Point(10, 10): false

Figure(name="Exagon", edges=(
Edge(Point(3, 0), Point(7, 0))
Edge(Point(7, 0), Point(10, 5))
Edge(Point(10, 5), Point(7, 10))
Edge(Point(7, 10), Point(3, 10))
Edge(Point(3, 10), Point(0, 5))
Edge(Point(0, 5), Point(3, 0))
))
Point inside poly?
Point(5, 5): true
Point(5, 8): true
Point(-10, 5): false
Point(0, 5): false
Point(10, 5): true
Point(8, 5): true
Point(10, 10): false

</pre>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==