I'm new on C++ and OOP. I wrote the following QuadTree implementation (I didn't wrote the remove object part yet).
please take a look on it and provide feedback, mainly about C++ OOP design, seperating my code to files, public vs. privte, shared_pt and etc...
QuadTree.h:
#pragma once
#include <iostream>
#include <utility>
#include <memory>
using namespace std;
class Point {
public:
Point(double _x, double _y) : x(_x), y(_y) {};
double x, y;
void printPoint() { std::cout << "(" << x << "," << y << ")" << std::endl; }
};
class LifeFoam {
int attribute;
Point location;
public:
LifeFoam(Point _location, int _attribute) : location(_location), attribute(_attribute) {};
Point getLocation() { return(location); }
int getAttribute() { return(attribute); }
};
class Node {
private:
const Point lowerLeftCorner, upperRightCorner;
const shared_ptr<Node> parent;
shared_ptr<Node> upperRightChildPtr = nullptr, upperLeftChildPtr = nullptr, lowerRightChildPtr = nullptr, lowerLeftChildPtr = nullptr;
LifeFoam* objectPtr = nullptr;
//private helper methods
Node* findRegion(Point point);
bool bIsLeaf() { return(upperRightChildPtr == nullptr);}
bool bPointInRegion(Point point) { return(point.x >= lowerLeftCorner.x && point.x <= upperRightCorner.x && point.y >= lowerLeftCorner.y && point.y <= upperRightCorner.y); }
Node* findSubRegion(Point point);
void seperateRegion(Node* nodeToSeperate);
void moveCurrObjectToSubRegion();
public:
void insertObject(LifeFoam* objPtr);
//void removeObject(LifeFoam& obj);
Node(const Point _lowerLeftCorner, const Point _upperRightCorner, const shared_ptr<Node> _parent) : lowerLeftCorner(_lowerLeftCorner), upperRightCorner(_upperRightCorner), parent(_parent) {};
//public helper methods
std::pair<const Point, const Point> getNodeVerticies() { return(make_pair(lowerLeftCorner, upperRightCorner)); };
bool bIsEmpty() { return(objectPtr == nullptr); }
int getObjectVal() { return(objectPtr->getAttribute()); }
void setObject(LifeFoam* _objectPtr) { objectPtr = _objectPtr; }
void setChildren(Node _upperRightChild, Node _upperLeftChild, Node _lowerRightChild, Node _lowerLeftChild) {
upperRightChildPtr = make_shared<Node>(_upperRightChild);
upperLeftChildPtr = make_shared<Node>(_upperLeftChild);
lowerRightChildPtr = make_shared<Node>(_lowerRightChild);
lowerLeftChildPtr = make_shared<Node>(_lowerLeftChild);
}
};
class QuadTree {
private:
Node root;
public:
QuadTree() : root(Point(0, 0), Point(100, 100), nullptr) {};
QuadTree(Point upperRightEdge, Point lowerLeftEdge) : root(lowerLeftEdge, upperRightEdge, nullptr) {};
};
QuadTree.cpp:
#include <iostream>
#include <cassert>
#include "QuadTree.h"
using namespace std;
#define assertm(msg, exp)
Node* Node::findSubRegion(Point point) {
assertm("out of bounds", bPointInRegion(x, y));
Point refPoint = Point((lowerLeftCorner.x + upperRightCorner.x) / 2, (lowerLeftCorner.y + upperRightCorner.y) / 2);
Node* subRegionPtr;
if (point.x >= refPoint.x) {
subRegionPtr = (point.y >= refPoint.y ? upperRightChildPtr.get() : lowerRightChildPtr.get());
} else {
subRegionPtr = (point.y >= refPoint.y ? upperLeftChildPtr.get() : lowerLeftChildPtr.get());
}
return(subRegionPtr);
}
Node* Node::findRegion(Point point) {
assertm("out of bounds", bPointInRegion(point));
if (bIsLeaf()) return(this);
Node* subRegionPtr = findSubRegion(point);
return(subRegionPtr->findRegion(point));
}
void Node::seperateRegion(Node* nodeToSeperate) {
const std::pair<const Point, const Point> nodeToSeperateVerticies= nodeToSeperate->getNodeVerticies();
const Point midVertex = Point((nodeToSeperateVerticies.first.x+ nodeToSeperateVerticies.second.x) / 2,
(nodeToSeperateVerticies.first.y + nodeToSeperateVerticies.second.y) / 2);
shared_ptr<Node> pp(nodeToSeperate);
Node upperRightSubRegion = Node(midVertex, nodeToSeperateVerticies.second, pp);
Node upperLeftSubRegion = Node(Point(nodeToSeperateVerticies.first.x, midVertex.y), Point(midVertex.x, nodeToSeperateVerticies.second.y), pp);
Node lowerRightSubRegion = Node(Point(midVertex.x, nodeToSeperateVerticies.first.y), Point(nodeToSeperateVerticies.second.x, midVertex.y), pp);
Node lowerLeftSubRegion = Node(nodeToSeperateVerticies.first, midVertex, pp);
nodeToSeperate->setChildren(upperRightSubRegion, upperLeftSubRegion, lowerRightSubRegion, lowerLeftSubRegion);
}
void Node::moveCurrObjectToSubRegion() {
Node* subRegionPtrForCurrentObject = findSubRegion(objectPtr->getLocation());
subRegionPtrForCurrentObject->setObject(objectPtr);
objectPtr = nullptr;
}
void Node::insertObject(LifeFoam* objPtr) {
Point point = objPtr->getLocation();
Node* currRegionForPoint = findRegion(point);
if (currRegionForPoint->bIsEmpty()) {
currRegionForPoint->setObject(objPtr);
}
else {
seperateRegion(currRegionForPoint);
currRegionForPoint->moveCurrObjectToSubRegion();
Node* subRegionPtr = findSubRegion(point);
subRegionPtr->insertObject(objPtr);
}
}