Example #1
0
        arma::vec2 Quad::getEdgePoints(double y) const {
            // create the horizontal intersection line
            ParametricLine<> scanLine;
            scanLine.setFromDirection({1, 0}, {0, y});

            // create a line-segment for each side of the quad
            std::vector<ParametricLine<>> lines = {ParametricLine<>(tl, tr, true),
                                                   ParametricLine<>(tr, br, true),
                                                   ParametricLine<>(bl, br, true),
                                                   ParametricLine<>(bl, tl, true)};

            // loop through lines and intersect it with the horizontal scan line
            std::vector<double> values;
            for (auto& line : lines) {
                try {
                    values.push_back(scanLine.intersect(line)[0]);
                }
                catch (std::domain_error&) {
                    // did not intersect, ignore
                }
            }

            // only two should intersect if there is a solution
            if (values.size() != 2) {
                throw std::domain_error("Could not find the edges points");
            }

            // return the minX and maxX
            return {std::min(values[0], values[1]), std::max(values[0], values[1])};
        }
    // Use the raycasting method: any plane (equivalent to a line in 2D, but a plane for programming reasons)
    // throught the point will intersect an even number of times with edges of the polygon iff the point lies
    // within the polygon
	bool Polygon::pointContained(const arma::vec2& p) const{
		ParametricLine<2> ray;
		int intersectionCount = 0;
		ray.setFromDirection(arma::vec2{1,0}, p, arma::vec2({0,std::numeric_limits<double>::infinity()}));
		arma::vec2 lastIntersection = {0,0};
		bool hadPreviousIntersection = false;
		for(auto& edge : edges){
			try {
				arma::vec2 intersection = ray.intersect(edge);
				if(hadPreviousIntersection){
					if(arma::norm(intersection - lastIntersection) > 1e-6){
						intersectionCount++;
					}
				} else {
					intersectionCount++;
				}
				hadPreviousIntersection = true;
				lastIntersection = intersection;
			} catch (const std::domain_error& e){
				//We didnt intersect with the line!
				//I know, seems kind of silly to use an exception here, but it works nicely with everything else
			}
		}
		return (intersectionCount % 2) == 1;
	}