My last question was closed after 2 minutes. I am simply asking for help with the member functions. I should have member functions checking the following:
whether the square is external to another;
whether the square contains another square;
whether the square is contained into another square;
whether the square is tangent externally to another square (that is,
whether their borders are in contact but, except those border
points, they are external to each other);
whether the square is tangent internally to another square (that is,
they have points on the borders in common but, except those border
points, one square is contained into the other one);
whether the border of the square intersects the border of another
square.
my private members are: double x,y;
Should i have the public member functions then, using both x and y to compute the perimeter and area?
This is what i have so far:
the header file
#include <iostream>
#include <cmath>
class Square
{
int x, y;
int size;
public:
Square(int x, int y, int size) : x(x), y(y), size(size) { }
~Square() {};
bool isExternal(const Square& rhs);
bool contains(const Square& otherSquare);
bool iscontained(const Square& otherSquare);
bool borderintersect (const Square& otherSquare);
bool bordertangent (const Square& otherSquare);
}
The implementation
#include "Square.h"
bool Square::isExternal(const Square& rhs) const {
return (((x < rhs.x) || ((x + size) > (rhs.x + rhs.size)) && ((y < rhs.y) || ((y + size) > (rhs.y + rhs.size))
};
bool Square::contains(const Square& otherSquare)const {
};
bool Square::iscontained(const Square& otherSquare)const {
};
bool borderintersect(const Square& othersquare)
{
// If this square's bottom is greater than the other square's top
if ((this->y - (this->size / 2)) > (othersquare->y + (othersquare->size / 2)))
{
return (false);
}
// the reverse
if ((this->y + (this->size / 2)) < (othersquare->y - (othersquare->size / 2)))
{
return (false);
}
// If this square's left is greater than the other square's right
if ((this->x - (this->size / 2)) > (othersquare->x + (othersquare->size / 2)))
{
return (false);
}
if ((this->x + (this->size / 2)) < (othersquare->x - (othersquare->size / 2)))
{
return (false);
}
return (true);
bool Square::bordertangent (const Square& otherSquare)const {
};
The test program
#include "Square.h"
#include <iostream>
using namespace std;
int main() {
Square sq1(0, 0, 10);
Square sq2(1, 1, 10);
if(sq1.isExternal(sq2)) {
cout<<"Square 1 is external to square 2"<<endl;
}
if(sq1.contains(sq2){
cout<<"Square 1 contains square 2"<<endl;
return 0;
}
Should i include this in the header file in order to get both the x and y of the coordinate and the size?
double getX( ) const { return x; }
double getY( ) const { return y; }
double getSize( ) const { return size; }
It seems like you're tripping up on where to start with implementing the class so I'll give you some guidance there. All of your questions deal with checking the relative positions of two squares in some coordinate space. To answer them, you will need to know two things about each square:
Position (x, y coordinates (often a corner of the square))
Size (size)
Assuming you definitely mean square, then the width and height are equal, so you only need one variable to store the size. If you can actually have rectangles, then you'll need width and height. These will need to be members of your Square class because each Square should have its own position and size. You do not need to store the coordinates of each corner of your square because you can work them out from the position and size - storing data that you can work out from data you already have is known as redundancy and is generally something you want to avoid. Here is how that would look in two different coordinate systems (one where y goes down and the other where y goes up):
x-->
y size
| (x,y).___________________
v | |
| |
| |
| |
size | |
| |
| |
| |
|___________________| (x+size, y+size)
___________________ (x+size, y+size)
| |
| |
| |
| |
size | |
| |
| |
^ | |
| (x,y).___________________|
y size
x-->
As an alternative, you could store two positions which are two opposite corners of your square. However, if you really are dealing with squares, not rectangles, you will need to manually enforce the invariant that the points must be the same distance away from each other along both axes. Rectangles would not have this invariant so this would be more applicable for them, but then operations such as translation become more complicated (you would now have to move two points rather than just one).
You will not need perimeter or area member functions. None of the questions require you to know either of these things. All of the questions can be answered by doing simple comparison between the positions and sizes of the two squares.
Whether you have them be private or not is a design issue. By making them private, you can control access to them through the Square's interface. You could then provide public member functions so that you can check for answers to some of your questions, such as bool Square::contains(const Square& otherSquare) which you would call like square.contains(otherSquare). Here's the beginnings of a possible class definition:
class Square
{
private:
int x, y, size;
public:
Square(int x, int y, int size) : x(x), y(y), size(size) { }
bool contains(const Square& other)
{
// Do comparisons between x, y, size and other.x, other.y, other.size
}
// ...
};
Alternatively, you could have the functions at namespace scope (not members of Square) and either make them friends of Square or make the position and size members of Square public. For such a simple example, this will not be a problem.
Should I include this in the header file in order to get both the x and y of the coordinate and the size?
double getX( ) const { return x; }
double getY( ) const { return y; }
double getSize( ) const { return size; }
These kinds of functions are commonly known as getters. They provide access to private member variables of a class. In your case, you do not need to provide these getters because the functions you are writing are member functions of Square. The member functions of Square have access to the private members of any other Square, so you don't need to get access through these getters.
However, if you wanted some other class to access the x, y, and size values for a given Square, then you would need to provide getters (or make the members public).
Start with something like this, and go from there
class Square
{
double m_x, m_y;
double m_length;
public:
Square(double x, double y, double length) : m_x(x), m_y(y), m_length(length) {}
~Square() {};
bool isExternal(const Square& rhs);
}
--- implementation
bool Square::isExternal(const Square& rhs)
{
bool retval = true;
// do some calculations ..
return retval;
}
--- main
int main(void)
{
Square sq1(0, 0, 10);
Square sq1(1, 1, 10);
if(sq1.isExternal(sq2) {
}
}
Related
I am currently mapping a Graph to a Minesweeper like grid, where every Block represents a node.
Here is my Graph class:
class Graph : public sf::Drawable
{
public:
Graph(uint32_t numNodesWidth, uint32_t numNodesHeight);
[[nodiscard]] std::vector<Node> & operator[](std::size_t i)
{ return data[i]; }
[[nodiscard]] sf::Vector2u dimension() const
{ return {static_cast<uint32_t>(data.size()),
static_cast<uint32_t>(data[0].size())};}
...
...
private:
std::vector<std::vector<Node>> data;
};
here is the implementation of the constructor:
Graph::Graph(uint32_t numNodesWidth, uint32_t numNodesHeight)
{
data.resize(numNodesHeight);
for(auto & row : data)
{
row.resize(numNodesWidth);
}
}
Somewhere in another class I read mouse coordinates and convert them to "Graph Coordinates":
sf::Vector2u translatedCoords = toGraphCoords(sf::Mouse::getPosition(window), nodeSize_);
bool inBounds = checkGraphBounds(translatedCoords, graph.dimension());
Here are the helper functions:
sf::Vector2u toGraphCoords(sf::Vector2i mouseCoord, sf::Vector2f nodeSize)
{
return {static_cast<uint32_t>(mouseCoord.y / nodeSize.y),
static_cast<uint32_t>(mouseCoord.x / nodeSize.x)};
}
bool checkGraphBounds(sf::Vector2u mouseCoord, sf::Vector2u bounds)
{
return mouseCoord.x >= 0 &&
mouseCoord.y >= 0 &&
mouseCoord.x < bounds.x &&
mouseCoord.y < bounds.y ;
}
Somehow I get the vector subscript out of range 1655 error when I try to use these new checked Coordinates which is somehow strange, can someone explain to me what I am doing wrong. This error always shows when I try to hover beyond the "Bounds" of the Interactive area, slightly behind or in front the first or the last Node.
Thanks in advance.
There is no guarantee that bounds <= num_nodes * node_size. This is especially risky since there are integer divisions involved, which means that you are at the mercy of rounding.
You could shuffle code around until such a guarantee is present, but there's a better way.
If the checkGraphBounds() function operated on the same math that the grid does, you could be sure that the result would be consistent with grid, no matter how that relates to the bounds.
The ideal way to do so would be to actually use toGraphCoords() as part of it:
bool checkGraphBounds(sf::Vector2u mouseCoord, const Graph& graph,
sf::Vector2f nodeSize)
{
auto coord = toGraphCoords(mouseCoord, nodeSize);
return coord.x >= 0 &&
coord.y >= 0 &&
coord.x < graph.dimensions().x &&
coord.y < graph.dimensions().y) ;
}
With this, you can formally guarantee that should a mouseCoord pass that test, static_cast<uint32_t>(mouseCoord.x / nodeSize.x)} will for certain return a value no greater than graph.dimensions().x.
Personally, I would combine both functions as a method of Graph like so:
class Graph : public sf::Drawable {
// Make nodeSize a member of the Graph
sf::Vector2f nodeSize_;
// This is one of the cases where caching an inferable value is worth it.
sf::Vector2u dimensions_;
public:
std::optional<sf::Vector2u> toGraphCoords(sf::Vector2i mouseCoord) {
sf::Vector2u coord{
static_cast<uint32_t>(mouseCoord.y / nodeSize_.y),
static_cast<uint32_t>(mouseCoord.x / nodeSize_.x)};
};
// No need to compare against 0, we are dealing with unsigned ints
if(coord.x < dimensions_.x &&
coord.y < dimensions_.y ) {
return coord;
}
return std::nullopt;
}
// ...
};
Usage:
void on_click(sf::Vector2i mouse_loc) {
auto maybe_graph_coord = the_graph.toGraphCoords(mouse_loc);
if(maybe_graph_coord) {
sf::Vector2u graph_coord = *maybe_graph_coord;
// ...
}
}
Im currently making a voxel game like Minecraft for fun with DirectX11.
Game works with chunk system like any other voxel game, but my current algorithm for generating chunk mesh is not expandable.
Block class has a few attributes like is block full and mesh type.
class Block
{
public:
bool isFull = true;
MeshType type = MeshType::FullBlock;
Vector2i texture = { 9, 1 };
Vector2i topTexture = { 9, 1 };
const char* sound;
Block(){}
Block(bool isFull, MeshType type, Vector2i texture, Vector2i topTexture, const char* sound): isFull(isFull), type(type), texture(texture), topTexture(topTexture), sound(sound){}
Block(bool isFull, MeshType type, Vector2i texture, const char* sound) : isFull(isFull), type(type), texture(texture), topTexture(texture), sound(sound) {}
Block(bool isFull, MeshType type, Vector2i texture) : isFull(isFull), type(type), texture(texture), topTexture(texture) {}
};
Every block is then initialised in a vector
blocks.reserve(64);
Block air(false, MeshType::Empty, {0 ,0});
blocks.emplace_back(air);
Block grass(true, MeshType::FullBlock, { 3, 0 }, { 0, 0 }, "Audio/grass1.ogg");
blocks.emplace_back(grass);
Block stone(true, MeshType::FullBlock, { 1, 0 }, "Audio/stone1.ogg");
blocks.emplace_back(stone);
Block rose(false, MeshType::Cross, { 12 ,0 }, "Audio/grass1.ogg");
blocks.emplace_back(rose);
Block wheat(false, MeshType::Hash, { 8 ,3 });
blocks.emplace_back(wheat);
//and so on...
I have a function that accepts a vector of vertices and chunk data.
That function loops through all the blocks with a few optimisations and emplaces data back into the vector that gets sent to the buffer.
for (int x = 0; x < ChunkWidth; x++)
{
for (int y = 0; y < ChunkHeight; y++)
{
for (int z = 0; z < ChunkWidth; z++)
{
if (IsDrawable[x][y][z] == 1)
{
switch (blocks[chunk->BlockID[x + 16 * y + 16 * 256 * z]].type)
{
case MeshType::FullBlock:
BuildBlock(chunk, vertices, x, y, z);
break;
case MeshType::Cross:
FillCross(vertices, blocks[chunk->BlockID[x + 16 * y + 16 * 256 * z]], x + chunk->x * ChunkWidth, y, z + chunk->z * ChunkWidth);
break;
case MeshType::Hash:
FillHash(vertices, blocks[chunk->BlockID[x + 16 * y + 16 * 256 * z]], x + chunk->x * ChunkWidth, y, z + chunk->z * ChunkWidth);
break;
}
}
}
}
}
With every new mesh type the switch statement gets bigger and I think that is not the way to go.
Im asking if there are better ways of doing this.
I thank you in advance.
I think making different derived classes with a common parent class Block is the way to go here. You add a virtual method in it whose behaviour is overridden in the derived classes. Then you place them in a polymorphic vector of std::shared_ptr<Block> and call them. If you are afraid that for some reason this might be too slow you might replace the virtual functions with the Curiously Recurring Template Pattern (CRTP) to achieve static polymorphism. So something like:
Implementatin of the base class Block: Can stay roughly the same bout you add a virtual method draw(...) which is the common interface for all derived classes:
class Block {
public:
bool isFull = true;
Vector2i texture = { 9, 1 };
Vector2i topTexture = { 9, 1 };
const char* sound;
Block() {
return;
}
Block(bool isFull, Vector2i const& texture, Vector2i const& topTexture, const char* sound)
: isFull(isFull), texture(texture), topTexture(topTexture), sound(sound) {
return;
}
Block(bool isFull, Vector2i const& texture, const char* sound)
: isFull(isFull), texture(texture), topTexture(texture), sound(sound) {
return;
}
Block(bool const& isFull, Vector2i const& texture)
: isFull(isFull), texture(texture), topTexture(texture) {
return;
}
// Virtual method that every derived class should override
// Could contain default behaviour but here I declared it as pure virtual method (therefore the = 0)
// Didn't know the data types for chunk and vertices so I used Chunk and Vertices respectively
virtual void draw(Chunk const& chunk, Vertices const& vertices, int x, int y, int z, int chunkWidth) = 0;
};
The different types of blocks are introduced as derived classes that inherit the constructor (or you might implement a new one as well) and override the behaviour of the draw(...) class. If you are not planning to inherit from this derived class then you can mark it as final or if you won't be overriding draw in a derived class you can mark only draw as final
class Empty: public Block {
public:
using Block::Block; // Use the constructor of the base class
// Overwrite behaviour of the base class here
void draw(Chunk const& chunk, Vertices const& vertices, int x, int y, int z, int chunkWidth) override {
return;
}
};
class FullBlock: public Block {
public:
using Block::Block;
void draw(Chunk const& chunk, Vertices const& vertices, int x, int y, int z, int chunkWidth) override {
// Move contents of BuildBlock here
BuildBlock(chunk, vertices, x, y, z);
return;
}
};
class Cross final: public Block {
public:
using Block::Block;
void draw(Chunk const& chunk, Vertices const& vertices, int x, int y, int z, int chunkWidth) override {
// Move contents of FillCross here! No need to pass blocks[i] or rewrite FillCross to take something else than a Block, e.g. a std::shared_ptr<Block>
FillCross(vertices, *this, x + chunk->x * chunkWidth, y, z + chunk->z * chunkWidth);
return;
}
};
class Hash final: public Block {
public:
using Block::Block;
void draw(Chunk const& chunk, Vertices const& vertices, int x, int y, int z, int chunkWidth) override {
// Same here
FillHash(vertices, *this, x + chunk->x * chunkWidth, y, z + chunk->z * chunkWidth);
return;
}
};
Then you add all the blocks as std::shared_ptr or better std::unique_ptr if the resources are not shared! (a wrapper for a plain pointer from #include <memory>)
// Consider using std::unique_ptr if you are not using the individual objects outside of the std::vector
std::vector<std::shared_ptr<Block>> blocks = {};
blocks.reserve(64);
auto air = std::make_shared<Empty>(false, {0 ,0});
blocks.emplace_back(air);
auto grass = std::make_shared<FullBlock>(true, { 3, 0 }, { 0, 0 }, "Audio/grass1.ogg");
blocks.emplace_back(grass);
auto stone = std::make_shared<FullBlock>(true, { 1, 0 }, "Audio/stone1.ogg");
blocks.emplace_back(stone);
auto rose = std::make_shared<Cross>(false, { 12 ,0 }, "Audio/grass1.ogg");
blocks.emplace_back(rose);
auto wheat = std::make_shared<Hash>(false, { 8 ,3 });
blocks.emplace_back(wheat);
You can call then the implementation of the different derived classes as follows:
for (int x = 0; x < chunkWidth; x++) {
for (int y = 0; y < chunkHeight; y++) {
for (int z = 0; z < chunkWidth; z++) {
if (IsDrawable[x][y][z] == 1) {
blocks[chunk->BlockID[x + 16 * y + 16 * 256 * z]]->draw(chunk, vertices, x, y, z, chunkWidth);
}
}
}
}
Here I put together a simplified working example to play around with in an online compiler.
I'm working on programming my own little game which should have a visibility effect as described here. My world consists of Polygons which each have a list of Edges (sorted CW). I now want (as described in the article) to cast Rays towards the Edges of the polygons, find the intersections and retrieve a Polygon that defines the visible area.
So I wrote a classes for Vectors, Points, Edges and Polygons and adjusted the intersection-algorithm so it works with my code.
I then tested it and everything worked fine, but as I ran the Intersection algorithm in a for-loop to simulate a large amount of Edges processed(starting with 100, until 1000) the fps dropped drastically, with 100 Edges "only" 300fps (3000 before), and with 300 it dropped below 60 i think. This seems to be way to much drop for me as i wanted to reuse this code for my Lightsources and then i think i would quickly come up with processing way more than 300 Edges and it should run fast on way less powerful processors(i got an xeon e1230v3).
I figured out that only calling the EdgeIntersection the program runs many times faster, but I definitely need to loop through the Edges in my polygons so this is no option.
My Source-Code:
Vector.h/.cpp: Basic Vector class with two floats(X,Y), getters&setters, rotating
Vertex.h/.cpp: Basic Point class with a Position Vector, getters&setters and a boolean that indicates whether it is a Intersection Vertex
Edge.h/.cpp Basic Edge class with start/end-Verticies, getters&setters and rotating function(uses Vector.rotate())
Polygon.h:
#pragma once
#include <vector>
#include "Edge.h"
namespace geo
{
class Polygon
{
private:
std::vector<Edge> edges;
public:
Polygon();
Polygon(std::vector<Edge> edges);
~Polygon();
std::vector<Edge> getEdges();
Edge getEdge(int index);
int getEdgeCount();
void setEdges(std::vector<Edge> edges);
void setEdge(Edge e, int index);
void addEdge(Edge e);
void removeEdge(int index);
};
}
Ray.h:
#pragma once
#include "Vertex.h"
class Ray
{
private:
geo::Vertex origin;
geo::Vector dir;
public:
Ray();
Ray(geo::Vertex origin, geo::Vector dir);
~Ray();
geo::Vertex getOrigin();
geo::Vector getDirection();
void setOrigin(geo::Vertex origin);
void setDirection(geo::Vector dir);
};
LightModule.h:
#pragma once
#include "Polygon.h"
#include "Ray.h"
class LightModule
{
private:
//List of blocking Polygons
std::vector<geo::Polygon>* blockingPolygons;
std::vector<Ray> rays;
geo::Polygon bounds;
geo::Polygon visible;
/*geo::Polygon blocked;*/
//HitDetection Class later
geo::Vertex getIntersection(Ray r, geo::Edge* e);
geo::Vertex getClosestIntersection(Ray r, geo::Polygon *p);
public:
LightModule();
LightModule(std::vector<geo::Polygon>* blockingPolygons);
~LightModule();
//Set the Blocking Polygons
void setBlockingPolygons(std::vector<geo::Polygon>* blockingPolygons);
geo::Vertex callCI(Ray r, geo::Polygon* p);
geo::Vertex callI(Ray r, geo::Edge* e);
//Cast Rays towards Vertecies and store them in rays
void updateRays();
//Update Visibility Polygon
void updateVisible();
//Return Visibility Polygon
geo::Polygon* getVisible();
};
LightMModule.cpp:
#include "LightModule.h"
LightModule::LightModule()
{
rays.clear();
}
LightModule::LightModule(std::vector<geo::Polygon>* blockingPolygons)
{
this->blockingPolygons = blockingPolygons;
rays.clear();
}
LightModule::~LightModule()
{
}
void LightModule::setBlockingPolygons(std::vector<geo::Polygon>* blockingPolygons)
{
this->blockingPolygons = blockingPolygons;
}
//Test-cast a Ray (will follow mouse in the Test)
void LightModule::updateRays()
{
Ray r(geo::Vertex(geo::Vector(200, 100)), geo::Vector(-100, 0));
rays.push_back(r);
}
void LightModule::updateVisible()
{
}
//Both for Testing will later be part of a seperate class
geo::Vertex LightModule::callCI(Ray r, geo::Polygon *p)
{
return this->getClosestIntersection(r, p);
}
geo::Vertex LightModule::callI(Ray r, geo::Edge* e)
{
return this->getIntersection(r, e);
}
//TEST
geo::Vertex LightModule::getIntersection(Ray r, geo::Edge* e)
{
geo::Vertex v;
v.setIntersectVert(false);
float r_px = r.getOrigin().getPosition().getX();
float r_py = r.getOrigin().getPosition().getY();
float r_dx = r.getDirection().getX();
float r_dy = r.getDirection().getY();
float s_px = e->getOrigin().getPosition().getX();
float s_py = e->getOrigin().getPosition().getY();
float s_dx = e->getDirection().getX();
float s_dy = e->getDirection().getY();
float r_mag = sqrt(r_dx*r_dx + r_dy*r_dy);
float s_mag = sqrt(s_dx*s_dx + s_dy*s_dy);
if (r_dx / r_mag == s_dx / s_mag && r_dy / r_mag == s_dy / s_mag)
{
return v;
}
float T2 = (r_dx*(s_py - r_py) + r_dy*(r_px - s_px)) / (s_dx*r_dy - s_dy*r_dx);
float T1 = (s_px + s_dx*T2 - r_px) / r_dx;
if (T1 < 0 /*|| T1 > 1 For Lines*/)
{
return v;
}
if (T2 < 0 || T2 > 1)
{
return v;
}
v.setIntersectVert(true);
v.setPosition(geo::Vector(r_px + r_dx*T1, r_py + r_dy*T1));
return v;
}
geo::Vertex LightModule::getClosestIntersection(Ray r, geo::Polygon *p)
{
geo::Vertex v;
v.setIntersectVert(false);
geo::Vertex v_nearest(geo::Vector(0, 0));
v_nearest.setIntersectVert(false);
geo::Vector h1;
geo::Vector h2;
for (int i = 0; i < p->getEdges().size(); i++)
{
v = this->getIntersection(r, &p->getEdges().at(i));
h1.setX(v.getPosition().getX() - r.getOrigin().getPosition().getX());
h1.setY(v.getPosition().getY() - r.getOrigin().getPosition().getY());
h2.setX(v_nearest.getPosition().getX() - r.getOrigin().getPosition().getX());
h2.setY(v_nearest.getPosition().getY() - r.getOrigin().getPosition().getY());
if (i < 1)
v_nearest = v;
else if (v.isIntersectVert() == true && h1.getLength() < h2.getLength())
{
v_nearest = v;
}
}
return v_nearest;
}
For the Testing i create a Polygon a LightModule and call updateRays and then call the helper-Function callCI().
I know my code gets pretty messy when i have to cascade my getters and setters, ill have to fix that but for the Rest i hope everything is understandable and if not feel free to ask. And just to have mentioned it, I Test-draw my Objects with Vertex-Arrays but I don't need Graphical output of the intersection process, i just need the visible polygon.
Just to point out again: I need a faster way of finding the Intersection-Point between a Ray and a Polygon and as I didn't know if i did something wrong in my code I posted it all here so someone can maybe help me making my code more efficient or show me a different method to solve my problem.
Have a nice day and thank you for your answers :)
Paul
EDIT: Would it be meaningfully faster to first triangulate my polygons and then do a Ray-Triangle intersection Test?
I can't speak to the algorithm (which is possibly what you need) but some immediate thoughts on speeding up what you have.
First off you can define all your getters and setters inline (put them in the class in the header, not the separate source file) so the compiler can optimize the function calls away.
Then these changes might buy you a few frames:
// make sure your getters and setters are inline so the compiler
// can optimize them away
geo::Vertex LightModule::getClosestIntersection(Ray r, geo::Polygon* p)
{
geo::Vertex v;
v.setIntersectVert(false);
geo::Vector h1;
geo::Vector h2;
// cache these
Vector ray_position = r.getOrigin().getPosition();
geo::Vertex v_nearest(geo::Vector(0, 0));
v_nearest.setIntersectVert(false);
// cache size (don't dereference each time)
size_t size = p->getEdges().size();
// avoid acces violation
if(!size)
return v_nearest;
// preset item 0
v_nearest = this->getIntersection(r, &p->getEdges()[0]);
// start from 1 not 0
for(int i = 1; i < size; i++)
{
// don't use at() its slower
// v = this->getIntersection(r, &p->getEdges().at(i));
v = this->getIntersection(r, &p->getEdges()[i]);
// used cached ray position rather than call functions
h1.setX(v.getPosition().getX() - ray_position.getX());
h1.setY(v.getPosition().getY() - ray_position.getY());
h2.setX(v_nearest.getPosition().getX() - ray_position.getX());
h2.setY(v_nearest.getPosition().getY() - ray_position.getY());
// this if not needed because presetting item 0
//if(i < 1)
// v_nearest = v;
if(v.isIntersectVert() == true && h1.getLength() < h2.getLength())
{
v_nearest = v;
}
}
return v_nearest;
}
I removed one of the if statements by calculating the 0 item before the loop and starting the loop from 1, the rest is just caching a much used value and avoiding at() which is slower because it does bound-checking.
I'm making a application for school in which I have to click a particular object.
EDIT: This is being made in 2D
I have a rectangle, I rotate this rectangle by X.
The rotation of the rectangle has made my rectangles (x,y,width,height) become a new rectangle around the rotated rectangle.
http://i.stack.imgur.com/MejMA.png
(excuse me for my terrible paint skills)
The Black lines describe the rotated rectangle, the red lines are my new rectangle.
I need to find out if my mouse is within the black rectangle or not. Whatever rotation I do I already have a function for getting the (X,Y) for each corner of the black rectangle.
Now I'm trying to implement this Check if point is within triangle (The same side technique).
So I can either check if my mouse is within each triangle or if theres a way to check if my mouse is in the rotated rectangle that would be even better.
I practically understand everything written in the triangle document, but I simply don't have the math skills to calculate the cross product and the dot product of the 2 cross products.
This is supposed to be the cross product:
a × b = |a| |b| sin(θ) n
|a| is the magnitude (length) of vector a
|b| is the magnitude (length) of vector b
θ is the angle between a and b
n is the unit vector at right angles to both a and b
But how do I calculate the unit vector to both a and b?
And how do I get the magnitude of a vector?
EDIT:
I forgot to ask for the calculation of the dotproduct between 2 cross products.
function SameSide(p1,p2, a,b)
cp1 = CrossProduct(b-a, p1-a)
cp2 = CrossProduct(b-a, p2-a)
if DotProduct(cp1, cp2) >= 0 then return true
else return false
Thank you everyone for your help I think I got the hang of it now, I wish I could accept multiple answers.
If you are having to carry out loads of check, I would shy away from using square root functions: they are computationally expensive. for comparison purposes, just multiply everything by itself and you can bypass the square rooting:
magnitude of vector = length of vector
If vector is defined as float[3] length can be calculated as follows:
double magnitude = sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] );
However that is expensive computationally so I would use
double magnitudeSquared = a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
Then modify any comparative calculations to use the squared version of the distance or magnitude and it will be more performant.
For the cross product, please forgive me if this maths is shaky, it has been a couple of years since I wrote functions for this (code re-use is great but terrible for remembering things):
double c[3];
c[0] = ( a[1]*b[2] - a[2]*b[1] );
c[1] = ( a[2]*b[0] - a[0]*b[2] );
c[2] = ( a[0]*b[1] - a[1]*b[0] );
To simplify it all I would put a vec3d in a class of its own, with a very simple representation being:
class vec3d
{
public:
float x, y, z;
vec3d crossProduct(vec3d secondVector)
{
vec3d retval;
retval.x = (this.y * secondVector.z)-(secondVector.y * this.z);
retval.y = -(this.x * secondVector.z)+(secondVector.x * this.z);
retval.z = (this.x * secondVector.y)-(this.y * secondVector.x);
return retval;
}
// to get the unit vector divide by a vectors length...
void normalise() // this will make the vector into a 1 unit long variant of itself, or a unit vector
{
if(fabs(x) > 0.0001){
x= x / this.magnitude();
}
if(fabs(y) > 0.0001){
y= y / this.magnitude();
}
if(fabs(z) > 0.0001){
z = / this.magnitude();
}
}
double magnitude()
{
return sqrt((x*x) + (y*y) + (z*z));
}
double magnitudeSquared()
{
return ((x*x) + (y*y) + (z*z));
}
};
A fuller implementation of a vec3d class can be had from one of my old 2nd year coding excercises: .h file and .cpp file.
And here is a minimalist 2d implementation (doing this off the top of my head so forgive the terse code please, and let me know if there are errors):
vec2d.h
#ifndef VEC2D_H
#define VEC2D_H
#include <iostream>
using namespace std;
class Vec2D {
private:
double x, y;
public:
Vec2D(); // default, takes no args
Vec2D(double, double); // user can specify init values
void setX(double);
void setY(double);
double getX() const;
double getY() const;
double getMagnitude() const;
double getMagnitudeSquared() const;
double getMagnitude2() const;
Vec2D normalize() const;
double crossProduct(Vec2D secondVector);
Vec2D crossProduct(Vec2D secondVector);
friend Vec2D operator+(const Vec2D&, const Vec2D&);
friend ostream &operator<<(ostream&, const Vec2D&);
};
double dotProduct(const Vec2D, const Vec2D);
#endif
vec2d.cpp
#include <iostream>
#include <cmath>
using namespace std;
#include "Vec2D.h"
// Constructors
Vec2D::Vec2D() { x = y = 0.0; }
Vec2D::Vec2D(double a, double b) { x = a; y = b; }
// Mutators
void Vec2D::setX(double a) { x = a; }
void Vec2D::setY(double a) { y = a; }
// Accessors
double Vec2D::getX() const { return x; }
double Vec2D::getY() const { return y; }
double Vec2D::getMagnitude() const { return sqrt((x*x) + (y*y)); }
double Vec2D::getMagnitudeSquared() const { return ((x*x) + (y*y)); }
double Vec2D::getMagnitude2 const { return getMagnitudeSquared(); }
double Vec2d::crossProduct(Vec2D secondVector) { return ((this.x * secondVector.getY())-(this.y * secondVector.getX()));}
Vec2D crossProduct(Vec2D secondVector) {return new Vec2D(this.y,-(this.x));}
Vec2D Vec2D::normalize() const { return Vec2D(x/getMagnitude(), y/getMagnitude());}
Vec2D operator+(const Vec2D& a, const Vec2D& b) { return Vec2D(a.x + b.x, a.y + b.y);}
ostream& operator<<(ostream& output, const Vec2D& a) { output << "(" << a.x << ", " << a.y << ")" << endl; return output;}
double dotProduct(const Vec2D a, const Vec2D b) { return a.getX() * b.getX() + a.getY() * b.getY();}
Check if a point is inside a triangle described by three vectors:
float calculateSign(Vec2D v1, Vec2D v2, Vec2D v3)
{
return (v1.getX() - v3.getX()) * (v2.getY() - v3.getY()) - (v2.getX() - v3.getX()) * (v1.getY() - v3.getY());
}
bool isPointInsideTriangle(Vec2D point2d, Vec2D v1, Vec2D v2, Vec2D v3)
{
bool b1, b2, b3;
// the < 0.0f is arbitrary, could have just as easily been > (would have flipped the results but would compare the same)
b1 = calculateSign(point2d, v1, v2) < 0.0f;
b2 = calculateSign(point2d, v2, v3) < 0.0f;
b3 = calculateSign(point2d, v3, v1) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}
In the code above if calculateSign is in the triangle you will get a true returned :)
Hope this helps, let me know if you need more info or a fuller vec3d or 2d class and I can post:)
Addendum
I have added in a small 2d-vector class, to show the differences in the 2d and 3d ones.
The magnitude of a vector is its length. In C++, if you have a vector represented as a double[3], you would calculate the length via
#include <math.h>
double a_length = sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] );
However, I understand what you actually want is the cross product? In that case, you may want to calculate it directly. The result is a vector, i.e. c = a x b.
You code it like this for example:
double c[3];
c[0] = ( a[2]*b[3] - a[3]*b[2] );
c[1] = ( a[3]*b[1] - a[1]*b[3] );
c[2] = ( a[1]*b[2] - a[2]*b[1] );
You can calculate the magnitude of vector by sqrt(x*x + y*y). Also you can calculate the crossproduct simpler: a x b = a.x * b.y - a.y * b.x. Checking that a point is inside triangle can be done by counting the areas for all 4 triangles. For example a is the area of the source triangle, b,c,d are areas of other ones. If b + c + d = a then the point is inside. Counting the area of triangle is simple: we have vectors a, b that are vertexes of triangle. The area of triangle then is (a x b) / 2
One simple way without getting into vectors is to check for area.
For example ,lets say you have a rectangle with corners A,B,C,D. and point P.
first calculate the area of rectangle, simply find height and width of the rectangle and multiply.
B D
| /
| /
|/____ C
A
For calculating the height,width take one point lets say A, find its distance from all other three points i.e AB,AC,AD 1st and 2nd minimum will be width,and height, max will be diagonal length.
Now store the points from which you get the height, width, lets says those points are B,C.
So now you know how rectangle looks, i.e
B _____ D
| |
|_____|
A C
Then calculate the sum of area of triangles ACP,ABP,BDP,CDP (use heros formula to compute area of rectangle), if it equals to the area of rectangle, point P is inside else outside the rectangle.
I've implemented a 3D strange attractor explorer which gives float XYZ outputs in the range 0-100, I now want to implement a colouring function for it based upon the displacement between two successive outputs.
I'm not sure of the data structure to use to store the colour values for each point, using a 3D array I'm limited to rounding to the nearest int which gives a very coarse colour scheme.
I'm vaguely aware of octtrees, are they suitable in this siutation?
EDIT: A little more explanation:
to generate the points i'm repeatedly running this:
(a,b,c,d are random floats in the range -3 to 3)
x = x2;
y = y2;
z = z2;
x2 = sin(a * y) - z * cos(b * x);
y2 = z2 * sin(c * x) - cos(d * y);
z2 = sin(x);
parr[i][0]=x;
parr[i][1]=y;
parr[i][2]=z;
which generates new positions for each axis each run, to colour the render I need to take the distance between two successive results, if I just do this with a distance calculation between each run then the colours fade back and forth in equilibrium so I need to take running average for each point and store it, using a 3dimenrsionl array is too coarse a colouring and I'm looking for advice on how to store the values at much smaller increments.
Maybe you could drop the 2-dim array off and use an 1-dim array of
struct ColoredPoint {
int x;
int y;
int z;
float color;
};
so that the code would look like
...
parr[i].x = x;
parr[i].y = y;
parr[i].z = z;
parr[i].color = some_computed_color;
(you may also wish to encapsulate the fields and use class ColoredPoint with access methods)
I'd probably think bout some kind of 3-d binary search tree.
template <class KEY, class VALUE>
class BinaryTree
{
// some implementation, probably available in libraries
public:
VALUE* Find(const KEY& key) const
{
// real implementation is needed here
return NULL;
}
};
// this tree nodes wil actually hold color
class BinaryTree1 : public BinaryTree<double, int>
{
};
class BinaryTree2 : public BinaryTree<double, BinaryTree1>
{
};
class BinaryTree3 : public BinaryTree<double, BinaryTree2>
{
};
And you function to retreive the color from this tree would look like that
bool GetColor(const BinaryTree3& tree, double dX, double dY, double& dZ, int& color)
{
BinaryTree2* pYTree = tree.Find(dX);
if( NULL == pYTree )
return false;
BinaryTree1* pZTree = pYTree->Find(dY);
if( NULL == pZTree )
return false;
int* pCol = pZTree->Find(dZ);
if( NULL == pCol )
return false;
color = *pCol;
return true;
}
Af course you will need to write the function that would add color to this tree, provided 3 coordinates X, Y and Z.
std::map appears to be a good candidate for base class.