diff --git a/ProjectReport_Group2.pdf b/ProjectReport_Group2.pdf new file mode 100644 index 0000000..ca75332 Binary files /dev/null and b/ProjectReport_Group2.pdf differ diff --git a/README.md b/README.md index a172f37..3dfbb1c 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,17 @@ Spatial database course extension to PostGRES Currently the build builds all the implementation files and builds postgres_ext.cpp file which includes all interfaces. ```bash +# Get the repo and setup GMP +git clone [URL] +cd PostGRES_ext +wget https://ftp.gnu.org/gnu/gmp/gmp-6.1.2.tar.xz +tar -xf gmp-6.1.2.tar.xz +cd gmp-6.1.2 +./configure --prefix=$HOME/.local --enable-cxx +make +make install +cd .. +# Build PostGRES_ext make clean make ./postgres_ext diff --git a/include/AVLTree.h b/include/AVLTree.h deleted file mode 100644 index 90ca847..0000000 --- a/include/AVLTree.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef AVLTree_H -#define AVLTree_H - -#include -#include - -/* AVL node */ -template -class AVLnode { -public: - T key; - int balance; - AVLnode *left, *right, *parent; - - AVLnode(T k, AVLnode *p) : key(k), balance(0), parent(p), - left(NULL), right(NULL) {} - - ~AVLnode() { - delete left; - delete right; - } -}; - -/* AVL tree */ -template -class AVLtree { -public: - AVLtree(void); - ~AVLtree(void); - bool insert(T key); - void deleteKey(const T key); - void printBalance(); - -private: - AVLnode *root; - - AVLnode* rotateLeft ( AVLnode *a ); - AVLnode* rotateRight ( AVLnode *a ); - AVLnode* rotateLeftThenRight ( AVLnode *n ); - AVLnode* rotateRightThenLeft ( AVLnode *n ); - void rebalance ( AVLnode *n ); - int height ( AVLnode *n ); - void setBalance ( AVLnode *n ); - void printBalance ( AVLnode *n ); - void clearNode ( AVLnode *n ); -}; - -#endif //AVLTree_H diff --git a/include/Evaluate.h b/include/Evaluate.h deleted file mode 100644 index 425e9cf..0000000 --- a/include/Evaluate.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef EVALUATE_H -#define EVALUATE_H - -#include "Point2DImpl.h" -#include "PredicateEnum.h" -#include "Line2DImpl.h" -#include "Region2DImpl.h" -#include - -class Evaluate { -public: - Evaluate(); - ~Evaluate(); - -// std::vector &featureVectorF, std::vector &featureVectorG - static bool validate( Point2DImpl &spatialObj_F, Point2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate); - static bool validate( Point2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate); - static bool validate( Point2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate); - static bool validate( Line2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate); - static bool validate( Line2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate); - static bool validate( Region2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate); - - static Predicate determine( Point2DImpl &spatialObj_F, Point2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ); - static Predicate determine( Point2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ); - static Predicate determine( Point2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ); - static Predicate determine( Line2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ); - static Predicate determine( Line2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ); - static Predicate determine( Region2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ); - -private: - std::vector >* IM; -}; - -#endif //EVALUATE_H diff --git a/include/Explore.h b/include/Explore.h deleted file mode 100644 index b352646..0000000 --- a/include/Explore.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef EXPLORE_H -#define EXPLORE_H - -#include "RGP.h" -#include "../include/Point2DImpl.h" -#include "Line2DImpl.h" -#include "Region2DImpl.h" -#include "PlaneSweep.h" -#include - -class Explore -{ -public: - Explore(); - ~Explore(); - - // F and G are spatial objects where F is of same or lower dimension then G - void explore(Point2DImpl &spatialObj_F, Point2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG); - void explore(Point2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG); - void explore(Point2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF); - void explore(Line2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG); - void explore(Line2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG); - void explore(Region2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG); -}; - -#endif diff --git a/include/Line2D.h b/include/Line2D.h index 49ba4b2..d3b14a8 100644 --- a/include/Line2D.h +++ b/include/Line2D.h @@ -1,38 +1,51 @@ #ifndef LINE2D_H #define LINE2D_H -#include "Number.h" #include "RGP.h" +#include "Number.h" +#include "Line2DImpl.h" #include #include class Line2D{ public: // Constructors - Line2D(); - Line2D(std::vector listOfSegments); Line2D(std::string listOfLine2DString); - Line2D(std::ifstream& file); // Send in file for constructor ~Line2D(); + //iterator to run through the list of half segments + class iterator + { + public: + iterator(RGPHalfSegment2D*); + RGPHalfSegment2D operator*(); + RGPHalfSegment2D operator++(int); + RGPHalfSegment2D operator++(); + bool operator!=(const iterator&); + bool operator==(const iterator&); + RGPHalfSegment2D *ptr; + }; + + iterator begin(); // return an iterator to the first element + iterator end(); // return an iterator to the last element + + bool add(RGPSegment2D rgpSeg2d); // Adds a new RGPSegment2D + bool update(iterator it, RGPSegment2D rgpSeg2d); // Updates RGPSegment2D existing at specified index + bool remove(iterator it); // Removes a RGPSegment2D at specified index + // Methods - std::string getLineString(); // Get the line as human readable ASCII string - static bool isEmptyLine(); - static bool isValidLine(); + void printAllLines(); // print all half segments in the vector + bool isEmptyLine(); int getNumberOfSegments(); // Get the total number of RGPSegment2Ds listed - std::vector getBoundingBox(); + bool operator==(const Line2D &l2d); // Override of operator == to check equality of two Line2Ds bool operator!=(const Line2D &l2d); // Override of operator != to check inequality of two Line2Ds - bool add(RGPSegment2D rgpSeg2d); // Adds a new RGPSegment2D - bool update(int index, RGPSegment2D rgpSeg2d); // Updates RGPSegment2D existing at specified index - bool remove(int index); // Removes a RGPSegment2D at specified index - RGPSegment2D operator[](int index); // Retrieves a RGPSegment2D at specified index + RGPSegment2D getBoundingBox(); + private: - class Line2DImpl; - - // Fields - Line2DImpl *impl; + struct Line2DStore; + Line2DStore *handle; }; #endif //LINE2D diff --git a/include/Line2DForProgrammer.h b/include/Line2DForProgrammer.h new file mode 100644 index 0000000..1efce24 --- /dev/null +++ b/include/Line2DForProgrammer.h @@ -0,0 +1,43 @@ +#ifndef LINE2DFORPROGRAMMER_H +#define LINE2DFORPROGRAMMER_H + +#include "Number.h" +#include "RGP.h" +#include "RGPSegment2D.h" +#include +#include +#include + +class Line2DForProgrammer{ +public: + // Constructors + Line2DForProgrammer(std::string listOfLine2DString); + Line2DForProgrammer(std::ifstream& file); // Send in file for constructor + ~Line2DForProgrammer(); + + //iterator to run through the list of half segments + class iterator + { + public: + iterator(RGPHalfSegment2D*); + RGPHalfSegment2D operator*(); + RGPHalfSegment2D operator++(int); + RGPHalfSegment2D operator++(); + bool operator!=(const iterator&); + bool operator==(const iterator&); + RGPHalfSegment2D *ptr; + }; + + iterator begin(); // return an iterator to the first element + iterator end(); // return an iterator to the last element + + bool add(RGPSegment2D rgpSeg2d); // Adds a new RGPSegment2D + bool update(iterator it, RGPSegment2D rgpSeg2d); // Updates RGPSegment2D existing at specified index + bool remove(iterator it); // Removes a RGPSegment2D at specified index + +private: + struct Line2DProgrammerStore; + Line2DProgrammerStore *handle; +}; + +#endif //LINE2D \ No newline at end of file diff --git a/include/Line2DImpl.h b/include/Line2DImpl.h index de84da6..f461e9b 100644 --- a/include/Line2DImpl.h +++ b/include/Line2DImpl.h @@ -1,21 +1,60 @@ #ifndef LINE2DIMPL_H #define LINE2DIMPL_H -#include "RGP.h" -#include "Line2D.h" +#include #include -class Line2DImpl : public Line2D { -public: - - Line2DImpl(); - ~Line2DImpl(); - - std::vector getSequence(); +#include "RGP.h" +#include "RGPSegment2D.h" +#include "RGPHalfSegment2D.h" -private: +class Line2DImpl +{ + public: + // Constructors + Line2DImpl(); // no args + Line2DImpl(std::vector listOfSegments); //send in a vector of segments + Line2DImpl(std::string listOfLine2DString); // send in a string + ~Line2DImpl(); //destructor - std::vector sequence; + //iterator to run through the list of half segments + class iterator + { + public: + iterator(RGPHalfSegment2D*); + RGPHalfSegment2D operator*(); + RGPHalfSegment2D operator++(int); + RGPHalfSegment2D operator++(); + bool operator!=(const iterator&); + bool operator==(const iterator&); + RGPHalfSegment2D *ptr; + }; + + iterator begin(); // return an iterator to the first element + iterator end(); // return an iterator to the last element + + // Methods + void printAllLines(); // print all half segments in the vector + bool isEmptyLine(); // checks if the line object is empty + int getNumberOfSegments(); // Get the total number of RGPSegment2Ds listed + RGPSegment2D getBoundingBox(); // find the bounding box diaginal + std::vector getVectorOfSegments(); + + bool add(RGPSegment2D rgpSeg2d); // Adds a new RGPSegment2D + bool update(iterator it, RGPSegment2D rgpSeg2d); // Updates RGPSegment2D existing at specified index + bool remove(iterator it); // Removes a RGPSegment2D at specified index + + bool operator==(const Line2DImpl &l2d); // Override of operator == to check equality of two Line2Ds + bool operator!=(const Line2DImpl &l2d); // Override of operator != to check inequality of two Line2Ds + Line2DImpl operator[](int index); // Retrieves a RGPSegment2D at specified index + Line2DImpl operator=(const Line2DImpl &l2dImpl); + + private: + struct Line2DImplStore; + Line2DImplStore *handle; + void lineSort(std::vector &bar); + void mergeSort(std::vector &left, std::vector &right, std::vector &bars); + bool parseStringToVectorOfLines(std::string st); }; -#endif //LINE2DIMPL_H +#endif //POINT2DIMPL_H \ No newline at end of file diff --git a/include/Number.h b/include/Number.h index 7cf5578..08649ec 100644 --- a/include/Number.h +++ b/include/Number.h @@ -4,7 +4,6 @@ #include #include - class Number { public: @@ -12,6 +11,9 @@ class Number // Default number value is 0 Number(); + // Copy constructor + Number(const Number &n); + // The string will be converted to a rational number Number(std::string number); @@ -19,33 +21,36 @@ class Number ~Number(); // Override arithmetic operators - Number& operator+(const Number& n) const; - Number& operator+=(const Number& n); - Number& operator-(const Number& n) const; - Number& operator-=(const Number& n); - Number& operator*(const Number& n) const; - Number& operator*=(const Number& n); - Number& operator/(const Number& n) const; - Number& operator/=(const Number& n); - Number& operator^(const int n) const; + Number operator=(const Number &n); + Number operator+(const Number &n) const; + Number operator+=(const Number &n); + Number operator-(const Number &n) const; + Number operator-=(const Number &n); + Number operator*(const Number &n) const; + Number operator*=(const Number &n); + Number operator/(const Number &n) const; + Number operator/=(const Number &n); + Number operator^(const int n) const; // Override comparison operators - bool operator<(const Number& n) const; - bool operator<=(const Number& n) const; - bool operator>(const Number& n) const; - bool operator>=(const Number& n) const; - bool operator==(const Number& n) const; - bool operator!=(const Number& n) const; + bool operator<(const Number &n) const; + bool operator<=(const Number &n) const; + bool operator>(const Number &n) const; + bool operator>=(const Number &n) const; + bool operator==(const Number &n) const; + bool operator!=(const Number &n) const; + Number sqrt() const; + Number sqrt(size_t digits) const; - Number& sqrt() const; + std::string to_string(size_t digits) const; // Overriding the output and input operator - friend std::ostream& operator<<(std::ostream& os, const Number& n); - friend std::istream& operator>>(std::istream& is, Number& n); + friend std::ostream &operator<<(std::ostream &os, const Number &n); + friend std::istream &operator>>(std::istream &is, Number &n); private: struct NumberImpl; - NumberImpl* p; + struct NumberImpl *p; }; #endif // NUMBER_H diff --git a/include/Optional.h b/include/Optional.h deleted file mode 100644 index 9f7f160..0000000 --- a/include/Optional.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef OPTIONAL_H -#define OPTIONAL_H - -// Optional definition -#ifdef __has_include - -// Check for standard library -# if __has_include() -# include - using std::optional; - using std::make_optional; - using std::nullopt; - -// Check for exprimental version (bug fix for Xcode on macOS) -# elif __has_include() -# include - using std::experimental::optional; - using std::experimental::make_optional; - using std::experimental::nullopt; - -// Not found -# else -# error "Missing " -# endif -#endif - -#endif //OPTIONAL_H diff --git a/include/PlaneSweep.h b/include/PlaneSweep.h deleted file mode 100644 index b84f895..0000000 --- a/include/PlaneSweep.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef PLANESWEEP_H -#define PLANESWEEP_H - -#include "RGP.h" -#include "AVLTree.h" -#include -#include -#include - -// Object - ObjectSelected -enum class ObjectSelected {OBJ_F, OBJ_G, BOTH, NONE}; -// Status - TraversalStatus -enum class TraversalStatus {END_OF_F, END_OF_G, END_OF_BOTH, END_OF_NONE}; - -// template -// class PointerWrapper{ -// -// PointerWrapper(typename std::vector::iterator dynamicIterator) { -// myIterator = dynamicIterator; -// } -// typename std::vector::iterator myIterator; -// -// bool operator>(const PointerWrapper &pw)const { -// return true; -// } -// }; - -template -class PlaneSweep { -public: - PlaneSweep(typename std::vector::iterator startIteratorF, typename std::vector::iterator endIteratorF, - typename std::vector::iterator startIteratorG, typename std::vector::iterator endIteratorG); - - PlaneSweep(const std::vector& seqF, const std::vector& seqG); - - ObjectSelected object; - TraversalStatus status; - - ~PlaneSweep(); - - void select_first(); - void select_next(); - - // Get event returns the element to which the logical pointer of a point - // or half segment sequence of an object points to - // typename std::vector::const_iterator getEventF(); - // typename std::vector::const_iterator getEventG(); - F getEventF(); - G getEventG(); - - // Checks whether a given point lies on/in any segment of the sweep line status - bool pointOnSegment(RGPPoint2D p); - bool pointInSegment(RGPPoint2D p); - - // Inserts/Removes a segment from the sweep line status when it's left/right half segment is encountered - void insert(RGPSegment2D s); - void remove(RGPSegment2D s); - - // Check if the dominant points of the given halfsegment and the next halfsegment - // (after the current index) of the indicated sequence are equal - bool lookAheadF(RGPHalfSegment2D h); - bool lookAheadG(RGPHalfSegment2D h); - - // Atribute - whether a segment is inside a region - // Returns the nearest annotated halfsegment, from the sweep line status, below a given point, if there is one - optional getAttributeOfSegmentBelow(RGPPoint2D p); - // Returns the overlap numbers of the predecessor to the given segment in the sweep line status - optional> getOverlapNumbersOfPredecessor(RGPSegment2D s); - // Returns the overlap numbers of the given segment in the sweep line status - optional> getOverlapNumbersOf(RGPSegment2D s); - -private: - // Stores event points - std::queue eventPointSchedule; - - // PointerWrapper() iteratorPtr; - // Holds the state of the intersection of the sweep line - - AVLtree sweepLineStatus; - //Sets an attribute for a segment in the sweep line status - void set_attr(AVLtree &sweepLineStatus, bool attribute); - //Gets an attribute from a segment in the sweep line status - bool get_attr(AVLtree &sweepLineStatus); - //Yields the attribute from the prdecessor of a segment in the sweepline status - bool get_pred_attr(AVLtree &sweepLineStatus, RGPHalfSegment2D segment); - //Checks for a segment in the sweepLineStatus to check if it hasa predecessor - bool pred_exists(AVLtree &sweepLineStatus, RGPHalfSegment2D segment); - //Checks for a neighbor segment - bool common_point_exists(AVLtree &sweepLineStatus, RGPHalfSegment2D segment); - //Tests whether such a segment exists - bool current_exists(AVLtree &sweepLineStatus); - //Stores left segment component into the segment sequence of the sweep line status - bool add_left(); - //Removes a segment component from the segment sequence of the sweep line status - bool del_right(); - //Returns new sweep line status - AVLtree new_sweep(); - - // template - // References to the spatial object sequences - const std::vector& staticSequenceF; - const std::vector& staticSequenceG; - std::vector dynamicSequenceF; - std::vector dynamicSequenceG; - typename std::vector::iterator staticIteratorF; - typename std::vector::iterator staticIteratorG; - // Iterators to check if we are at the end of vector - // typename std::vector::iterator startStaticIteratorF; - // typename std::vector::iterator startStaticIteratorG; - typename std::vector::iterator endStaticIteratorF; - typename std::vector::iterator endStaticIteratorG; - typename std::vector::iterator dynamicIteratorF; - typename std::vector::iterator dynamicIteratorG; - -}; - -#endif //PLANESWEEP diff --git a/include/Point2D.h b/include/Point2D.h index 499e809..96ea9b1 100644 --- a/include/Point2D.h +++ b/include/Point2D.h @@ -1,3 +1,5 @@ +// PUBLIC HEADER FILE + #ifndef POINT2D_H #define POINT2D_H @@ -9,32 +11,41 @@ class Point2D{ public: - // Fields - // Constructors - Point2D(); - Point2D(std::vector listOfPoints); // Create the Point2D as a vector of RGPPoint2Ds - Point2D(std::ifstream& file); // Take input from a file, convert the data into a Point2D Point2D(std::string listOfPoint2DString); // Read the string as a vector of RGPPoint2D and form a Point2D ~Point2D(); + class iterator + { + public: + iterator(RGPPoint2D*); + RGPPoint2D operator*(); + RGPPoint2D operator++(int); + RGPPoint2D operator++(); + bool operator!=(const iterator&); + bool operator==(const iterator&); + RGPPoint2D *ptr; + }; + + iterator begin(); + iterator end(); + // Methods - std::string getPointString(); // Get the point as human readable ASCII string - static bool isEmptyPoint(); // Checks if the Point2D object is empty - static bool isValidPoint(); // Checks if the Point2D object is empty - bool operator==(const Point2D &p2d); // Override of operator == to check equality of two Point2Ds - bool operator!=(const Point2D &p2d); // Override of operator != to check inequality of two Point2Ds + bool isEmptyPoint(); // Checks if the Point2D object is empty int getNumberOfPoints(); // Get the total number of RGPPoint2Ds listed - std::vector getBoundingBox(); + void printAllPoints(); bool add(RGPPoint2D rgpp2d); // Adds a new RGPPoint2D to the existing Point2D object - bool update(int index, RGPPoint2D rgpp2d); // Updates RGPPoint2D existing at specified index - bool remove(int index); // Removes a RGPPoint2D at specified index - RGPPoint2D operator[](int index); // Retrieves a RGPPoint2D at specified index + bool update(iterator it, RGPPoint2D rgpp2d); // Updates RGPPoint2D existing at specified index + bool remove(iterator it); // Removes a RGPPoint2D at specified index + + + bool operator==(const Point2D &p2d); // Override of operator == to check equality of two Point2Ds + bool operator!=(const Point2D &p2d); // Override of operator != to check inequality of two Point2Ds + RGPSegment2D getBoundingBox(); private: - class Point2DImpl; - // Fields - Point2DImpl *impl; + struct Point2DStore; + Point2DStore *handle; }; #endif //POINT2D_H diff --git a/include/Point2DForProgrammer.h b/include/Point2DForProgrammer.h new file mode 100644 index 0000000..25606e3 --- /dev/null +++ b/include/Point2DForProgrammer.h @@ -0,0 +1,46 @@ +// PUBLIC HEADER FILE + +#ifndef POINT2DFORPROGRAMMER_H +#define POINT2DFORPROGRAMMER_H + +#include "Number.h" +#include "RGP.h" +#include +#include +#include + +class Point2DForProgrammer{ +public: + // Constructors + Point2DForProgrammer(std::vector); // Take input from a file, convert the data into a Point2DForProgrammer + Point2DForProgrammer(std::string listOfPoint2DString); // Read the string as a vector of RGPPoint2D and form a Point2DForProgrammer + ~Point2DForProgrammer(); + + //iterator + class iterator + { + public: + iterator(RGPPoint2D*); + RGPPoint2D operator*(); + RGPPoint2D operator++(int); + RGPPoint2D operator++(); + bool operator!=(const iterator&); + bool operator==(const iterator&); + RGPPoint2D *ptr; + }; + + iterator begin(); + iterator end(); + + + // Methods + bool add(RGPPoint2D rgpp2d); // Adds a new RGPPoint2D to the existing Point2D object + bool update(iterator it, RGPPoint2D rgpp2d); // Updates RGPPoint2D existing at specified index + bool remove(iterator it); // Removes a RGPPoint2D at specified index + +private: + struct Point2DProgrammerStore; + Point2DProgrammerStore *handle; +}; + +#endif //POINT2D_H diff --git a/include/Point2DImpl.h b/include/Point2DImpl.h index 73e3b5b..4c6e6bc 100644 --- a/include/Point2DImpl.h +++ b/include/Point2DImpl.h @@ -1,20 +1,56 @@ #ifndef POINT2DIMPL_H #define POINT2DIMPL_H -#include "RGP.h" -#include "Point2D.h" #include +#include "RGPPoint2D.h" +#include "Line2DImpl.h" +#include "RGPSegment2D.h" -class Point2DImpl : public Point2D { -public: - Point2DImpl(); - ~Point2DImpl(); +class Point2DImpl +{ + public: + Point2DImpl(); + Point2DImpl(std::ifstream& file); // Take input from a file, convert the data into a Point2D + Point2DImpl(std::vector pointVector); + Point2DImpl(std::string listOfPoint2DString); // Read the string as a vector of RGPPoint2D and form a Point2D + ~Point2DImpl(); + class iterator + { + public: + iterator(RGPPoint2D*); + RGPPoint2D operator*(); + RGPPoint2D operator++(int); + RGPPoint2D operator++(); + bool operator!=(const iterator&); + bool operator==(const iterator&); + RGPPoint2D *ptr; + }; - std::vector getSequence(); + // Methods + std::string getPointString(); // Get the point as human readable ASCII string + void printAllPoints(); // prints all the points in the object + bool isEmptyPoint(); // Checks if the Point2D object is empty + int getNumberOfPoints(); // Get the total number of RGPPoint2Ds listed + std::vector getVectorOfPoints(); + iterator begin(); //returns iterator to the first point + iterator end(); // return iterator to the last point + RGPSegment2D getBoundingBox(); //returns the bounding box of the set od points -private: + bool add(RGPPoint2D rgpp2d); // Adds a new RGPPoint2D to the existing Point2D object + bool update(iterator it, RGPPoint2D rgpp2d); // Updates RGPPoint2D existing at specified index + bool remove(iterator it); // Removes a RGPPoint2D at specified index - std::vector sequence; + bool operator==(const Point2DImpl &p2d); // Override of operator == to check equality of two Point2Ds + bool operator!=(const Point2DImpl &p2d); // Override of operator != to check inequality of two Point2Ds + Point2DImpl operator[](int index); // Retrieves a RGPPoint2D at specified index + Point2DImpl operator=(const Point2DImpl &p2dImpl); + + private: + struct Point2DImplStore; + Point2DImplStore *handle; + void pointSort(std::vector &bar); // private methods for sort + void mergeSort(std::vector &left, std::vector &right, std::vector &bars); + bool parseStringToVectorOfPoints(std::string st); // private method to parse }; #endif //POINT2DIMPL_H diff --git a/include/PredicateEnum.h b/include/PredicateEnum.h deleted file mode 100644 index f849a68..0000000 --- a/include/PredicateEnum.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef POSTGRES_EXT_PREDICATEENUM_H -#define POSTGRES_EXT_PREDICATEENUM_H - -enum class Predicate { disjoint, meet, overlap, covers, contains, equal, inside, coveredBy }; - -#endif //POSTGRES_EXT_PREDICATEENUM_H diff --git a/include/RGPHalfSegment2D.h b/include/RGPHalfSegment2D.h index 5189b4f..7bfaa8f 100644 --- a/include/RGPHalfSegment2D.h +++ b/include/RGPHalfSegment2D.h @@ -1,53 +1,47 @@ #ifndef RGPHALFSEGMENT2D_H #define RGPHALFSEGMENT2D_H -#include "RGPSegment2D.h" #include "RGPPoint2D.h" -#include "Optional.h" +#include "RGPSegment2D.h" -class RGPHalfSegment2D -{ +class RGPHalfSegment2D { public: + // Members - // Members - - RGPSegment2D segment; - RGPPoint2D dominantPoint; - - // Constructors + RGPSegment2D segment; + RGPPoint2D dominantPoint; + bool isLeftFlag; + Number m; // Slope - RGPHalfSegment2D(RGPSegment2D s, RGPPoint2D dp); - ~RGPHalfSegment2D(); + // Constructors - // Methods + RGPHalfSegment2D(RGPSegment2D s, RGPPoint2D dp); + ~RGPHalfSegment2D(); - bool operator==(const RGPHalfSegment2D &rhs) const; - bool operator!=(const RGPHalfSegment2D &rhs) const; - bool operator<(const RGPHalfSegment2D &rhs) const; - bool operator<=(const RGPHalfSegment2D &rhs) const; - bool operator>(const RGPHalfSegment2D &rhs) const; - bool operator>=(const RGPHalfSegment2D &rhs) const; - - bool operator<(const RGPPoint2D &rhs) const; - bool operator>(const RGPPoint2D &rhs) const; + // Methods + bool operator==(const RGPHalfSegment2D &rhs); + bool operator!=(const RGPHalfSegment2D &rhs); + bool operator<(const RGPHalfSegment2D &rhs); + bool operator<=(const RGPHalfSegment2D &rhs); + bool operator>(const RGPHalfSegment2D &rhs); + bool operator>=(const RGPHalfSegment2D &rhs); + bool isLeft(); + Number sqLen() const; // Square of length }; -class RGPAnnotatedHalfSegment2D : public RGPHalfSegment2D -{ +class RGPAnnotatedHalfSegment2D : public RGPHalfSegment2D { public: + // Members - // Members - - bool interiorIsAbove; - - // Constructors + bool insideIsAbove; - RGPAnnotatedHalfSegment2D(RGPSegment2D s, RGPPoint2D dp, bool regAbove); - ~RGPAnnotatedHalfSegment2D(); + // Constructors - // Methods + RGPAnnotatedHalfSegment2D(RGPSegment2D s, RGPPoint2D dp, bool regAbove); + ~RGPAnnotatedHalfSegment2D(); + // Methods }; -#endif //RGPHALFSEGMENT2D_H +#endif // RGPHALFSEGMENT2D_H diff --git a/include/RGPOperations2D.h b/include/RGPOperations2D.h index 4416471..ba60007 100644 --- a/include/RGPOperations2D.h +++ b/include/RGPOperations2D.h @@ -6,15 +6,42 @@ #ifndef RGPOPERATIONS2D_H #define RGPOPERATIONS2D_H +// Optional definition +#ifdef __has_include + +// Check for standard library +#if __has_include() +#include +using std::optional; + +// Check for exprimental version (bug fix for Xcode on macOS) +#elif __has_include() +#include +using std::experimental::optional; + +// Not found +#else +#error "Missing " +#endif +#endif + +#include "RGPHalfSegment2D.h" #include "RGPPoint2D.h" #include "RGPSegment2D.h" -#include "RGPHalfSegment2D.h" -class RGPOperations2D -{ +#define COLLINEAR 1 +#define CLOCKWISE 2 +#define COUNTERCLOCKWISE 3 + +class RGPOperations2D { +private: + // Helper Function + static int orientation(RGPPoint2D point1, RGPPoint2D point2, + RGPPoint2D point3); + static RGPPoint2D intersection(RGPSegment2D s1, RGPSegment2D s2); + public: - static optional intersectionOf(RGPSegment2D s1, - RGPSegment2D s2); + static optional intersectionOf(RGPSegment2D s1, RGPSegment2D s2); }; -#endif //RGPOPERATIONS2D_H +#endif // RGPOPERATIONS2D_H diff --git a/include/RGPPoint2D.h b/include/RGPPoint2D.h index 1a822ac..3303df8 100644 --- a/include/RGPPoint2D.h +++ b/include/RGPPoint2D.h @@ -6,45 +6,33 @@ #define RGPPOINT2D_H #include "Number.h" -#include "Optional.h" -class RGPPoint2D -{ +class RGPPoint2D { public: + // Members - // Members + Number x, y; - Number x, y; + // Constructors - // Constructors + RGPPoint2D(Number x, Number y); + ~RGPPoint2D(); - RGPPoint2D(Number x, Number y); - ~RGPPoint2D(); + // Methods - // Methods + bool operator==(const RGPPoint2D &rhs); + bool operator!=(const RGPPoint2D &rhs); + bool operator<(const RGPPoint2D &rhs); + bool operator<=(const RGPPoint2D &rhs); + bool operator>(const RGPPoint2D &rhs); + bool operator>=(const RGPPoint2D &rhs); - bool operator==(const RGPPoint2D &rhs) const; - bool operator!=(const RGPPoint2D &rhs) const; - bool operator<(const RGPPoint2D &rhs) const; - bool operator<=(const RGPPoint2D &rhs) const; - bool operator>(const RGPPoint2D &rhs) const; - bool operator>=(const RGPPoint2D &rhs) const; - - // bool operator<(const RGPHalfSegment2D &rhs) const; - // bool operator>(const RGPHalfSegment2D &rhs) const; - - // bool operator<(const RGPAnnotatedHalfSegment2D &rhs) const; - // bool operator>(const RGPAnnotatedHalfSegment2D &rhs) const; - - - - // Allows ouptut of an RGPPoint2D in the format of "(x,y)" - friend std::ostream& operator<<(std::ostream& os, const RGPPoint2D p); - - // Allows input of an RGPPoint2D in the format of "(x,y)" where ',' will be - // the delimiter between the x and y values - friend std::istream& operator>>(std::istream& is, const RGPPoint2D p); + // Allows ouptut of an RGPPoint2D in the format of "(x,y)" + friend std::ostream &operator<<(std::ostream &os, const RGPPoint2D p); + // Allows input of an RGPPoint2D in the format of "(x,y)" where ',' will be + // the delimiter between the x and y values + friend std::istream &operator>>(std::istream &is, RGPPoint2D p); }; -#endif //RGPPOINT2D_H +#endif // RGPPOINT2D_H diff --git a/include/RGPSegment2D.h b/include/RGPSegment2D.h index df62563..55cd0c9 100644 --- a/include/RGPSegment2D.h +++ b/include/RGPSegment2D.h @@ -6,41 +6,35 @@ #define RGPSEGMENT2D_H #include "RGPPoint2D.h" -#include "Optional.h" -class RGPSegment2D -{ +class RGPSegment2D { public: + // Members - // Members + RGPPoint2D point1, point2; - RGPPoint2D point1, point2; + // Constructors - // Constructors + RGPSegment2D(RGPPoint2D p1, RGPPoint2D p2); + ~RGPSegment2D(); - RGPSegment2D(RGPPoint2D p1, RGPPoint2D p2); - ~RGPSegment2D(); + // Methods - // Methods + bool operator==(const RGPSegment2D &rhs); + bool operator!=(const RGPSegment2D &rhs); + bool operator<(const RGPSegment2D &rhs); + bool operator<=(const RGPSegment2D &rhs); + bool operator>(const RGPSegment2D &rhs); + bool operator>=(const RGPSegment2D &rhs); + bool contains(const RGPPoint2D p); - bool operator==(const RGPSegment2D &rhs) const; - bool operator!=(const RGPSegment2D &rhs) const; - bool operator<(const RGPSegment2D &rhs) const; - bool operator<=(const RGPSegment2D &rhs) const; - bool operator>(const RGPSegment2D &rhs) const; - bool operator>=(const RGPSegment2D &rhs) const; - - bool operator<(const RGPPoint2D &rhs) const; - bool operator>(const RGPPoint2D &rhs) const; - - // Allows ouptut of an RGPSegment2D in the format of "(x1,y1),(x2,y2)" - friend std::ostream& operator<<(std::ostream& os, const RGPSegment2D p); - - // Allows input of an RGPSegment2D in the format of "(x1,y1),(x2,y2)" - // where ',' will be the delimiter between the x and y values of point1 - // and point2 - friend std::istream& operator>>(std::istream& is, const RGPSegment2D p); + // Allows ouptut of an RGPSegment2D in the format of "(x1,y1),(x2,y2)" + friend std::ostream &operator<<(std::ostream &os, const RGPSegment2D p); + // Allows input of an RGPSegment2D in the format of "(x1,y1),(x2,y2)" + // where ',' will be the delimiter between the x and y values of point1 + // and point2 + friend std::istream &operator>>(std::istream &is, const RGPSegment2D p); }; -#endif //RGPSEGMENT2D_H +#endif // RGPSEGMENT2D_H diff --git a/include/Region2D.h b/include/Region2D.h index e70124b..d9fd653 100644 --- a/include/Region2D.h +++ b/include/Region2D.h @@ -1,42 +1,42 @@ -#ifndef REGION2D_H -#define REGION2D_H - -#include "Number.h" -#include "RGP.h" -#include -#include - -class Region2D -{ -public: - // Constructors - Region2D(); //Empty constructor - Region2D(std::vector> listOfRegions); - Region2D(std::string listOfRegion2DString); - Region2D(std::ifstream& file); // Send in file for constructor (possibly .txt) - ~Region2D(); - - // Methods - std::string getRegionString(); // Get the region as human readable ASCII string - Number area(); - static bool isEmptyRegion(Region2D region); - static bool isValidRegion(Region2D region); - int getNumberOfFaces(); - std::vector getBoundingBox(); - bool operator==(const Region2D &p2d); - bool operator!=(const Region2D &p2d); - std::vector getCycle(int index); - std::vector getFace(int index); - bool addFace(std::vector); - bool update(int index, std::vector); // Updates a whole region at specified index - bool remove(int index); // Removes a region at specified index - std::vector operator[](int index); // Retrieves a region at specified index - -private: - class Region2DImpl; - - // Fields - Region2DImpl *impl; -}; - -#endif // REGION2D_H +#ifndef REGION2D_H +#define REGION2D_H + +#include "Number.h" +#include "RGP.h" +#include +#include + +class Region2D +{ +public: + // Constructors + Region2D(); //Empty constructor + Region2D(std::vector> listOfRegions); + Region2D(std::string listOfRegion2DString); + Region2D(std::ifstream& file); // Send in file for constructor (possibly .txt) + ~Region2D(); + + // Methods + std::string getRegionString(); // Get the region as human readable ASCII string + Number area(); + static bool isEmptyRegion(Region2D region); + static bool isValidRegion(Region2D region); + int getNumberOfFaces(); + std::vector getBoundingBox(); + bool operator==(const Region2D &p2d); + bool operator!=(const Region2D &p2d); + std::vector getCycle(int index); + std::vector getFace(int index); + bool addFace(std::vector); + bool update(int index, std::vector); // Updates a whole region at specified index + bool remove(int index); // Removes a region at specified index + std::vector operator[](int index); // Retrieves a region at specified index + +private: + class Region2DImpl; + + // Fields + Region2DImpl *impl; +}; + +#endif // REGION2D_H diff --git a/include/Region2DImpl.h b/include/Region2DImpl.h index 99ef0ee..eb7612d 100644 --- a/include/Region2DImpl.h +++ b/include/Region2DImpl.h @@ -1,21 +1,70 @@ -#ifndef REGION2DIMPL_H -#define REGION2DIMPL_H - -#include "RGP.h" -#include "Region2D.h" -#include - -class Region2DImpl : public Region2D { -public: - - Region2DImpl(); - ~Region2DImpl(); - - std::vector getSequence(); - -private: - - std::vector sequence; -}; - -#endif //REGION2DIMPL_H +#ifndef Region2DImpl_H +#define Region2DImpl_H + +#include "Number.h" +#include "RGP.h" +#include +#include + +class Region2DImpl +{ +public: + // Constructors + Region2DImpl(std::string listOfRegion2DString); + ~Region2DImpl(); + + class iteratorforFaces + { + public: + iteratorforFaces(std::vector*); + std::vector operator*(); + std::vector operator++(int); + std::vector operator++(); + bool operator!=(const iteratorforFaces&); + bool operator==(const iteratorforFaces&); + std::vector *ptr; + }; + + class iteratorforHoles + { + public: + iteratorforHoles(std::vector*); + std::vector operator*(); + std::vector operator++(int); + std::vector operator++(); + bool operator!=(const iteratorforHoles&); + bool operator==(const iteratorforHoles&); + std::vector *ptr; + }; + + iteratorforHoles beginHoles(); + iteratorforHoles endHoles(); + iteratorforFaces beginFaces(); + iteratorforFaces endFaces(); + + // Methods + Number area(); + bool isEmptyRegion(); + int getNumberOfFaces(); + int getNumberOfHoles(); + bool operator==(const Region2DImpl &p2d); + bool operator!=(const Region2DImpl &p2d); + bool addFace(std::vector); + bool removeFace(int index); // Removes a region at specified index + RGPSegment2D getBoundingBox(); + +private: + class Region2DImplStore; + Number computeArea(); + void sortAnnotatedHS(std::vector vec); + void mergeSort(std::vector &left, std::vector &right, std::vector &bars); + bool parseWDR(std::string inputString); + Number computeDirection(RGPPoint2D pi, RGPPoint2D pj, RGPPoint2D pk); + bool doSegmentsIntersect(RGPSegment2D a, RGPSegment2D b); + bool validateRegion(); + Number getAreaOfCycle(std::vector vectorOfSegments); + Region2DImplStore *handle; + std::vector constructRegion(std::string formattedInputString); +}; + +#endif // Region2DImpl_H diff --git a/include/Relationship2D.h b/include/Relationship2D.h deleted file mode 100644 index 3e5fb13..0000000 --- a/include/Relationship2D.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef POSTGRES_EXT_RELATIONSHIP2D_H -#define POSTGRES_EXT_RELATIONSHIP2D_H - -#include "PredicateEnum.h" -#include "Point2D.h" -#include "Line2D.h" -#include "Region2D.h" - -class Relationship2D { - -public: - - Relationship2D(); - ~Relationship2D(); - - // Determine relationship - // Reference these from Evaluate.h - // enum PREDICATE { disjoint, meet, overlap, covers, contains, equal, inside, coveredBy }; - static Predicate determine(Point2D &leftOperand, Point2D &rightOperand); - static Predicate determine(Point2D &leftOperand, Line2D &rightOperand); - static Predicate determine(Point2D &leftOperand, Region2D &rightOperand); - static Predicate determine(Line2D &leftOperand, Line2D &rightOperand); - static Predicate determine(Line2D &leftOperand, Region2D &rightOperand); - static Predicate determine(Region2D &leftOperand, Region2D &rightOperand); - - // Disjoint - static bool disjoint(Point2D &leftOperand, Point2D &rightOperand); - static bool disjoint(Point2D &leftOperand, Line2D &rightOperand); - static bool disjoint(Point2D &leftOperand, Region2D &rightOperand); - static bool disjoint(Line2D &leftOperand, Line2D &rightOperand); - static bool disjoint(Line2D &leftOperand, Region2D &rightOperand); - static bool disjoint(Region2D &leftOperand, Region2D &rightOperand); - - // Meet - static bool meet(Point2D &leftOperand, Line2D &rightOperand); - static bool meet(Point2D &leftOperand, Region2D &rightOperand); - static bool meet(Line2D &leftOperand, Line2D &rightOperand); - static bool meet(Line2D &leftOperand, Region2D &rightOperand); - static bool meet(Region2D &leftOperand, Region2D &rightOperand); - - // Overlap - static bool overlap(Point2D &leftOperand, Point2D &rightOperand); - static bool overlap(Point2D &leftOperand, Line2D &rightOperand); - static bool overlap(Point2D &leftOperand, Region2D &rightOperand); - static bool overlap(Line2D &leftOperand, Line2D &rightOperand); - static bool overlap(Line2D &leftOperand, Region2D &rightOperand); - static bool overlap(Region2D &leftOperand, Region2D &rightOperand); - - // Equal - static bool equal(Point2D &leftOperand, Point2D &rightOperand); - static bool equal(Line2D &leftOperand, Line2D &rightOperand); - static bool equal(Region2D &leftOperand, Region2D &rightOperand); - - // Inside - static bool inside(Point2D &leftOperand, Point2D &rightOperand); - static bool inside(Point2D &leftOperand, Line2D &rightOperand); - static bool inside(Point2D &leftOperand, Region2D &rightOperand); - static bool inside(Line2D &leftOperand, Line2D &rightOperand); - static bool inside(Line2D &leftOperand, Region2D &rightOperand); - static bool inside(Region2D &leftOperand, Region2D &rightOperand); - - // Contains - static bool contains(Point2D &leftOperand, Point2D &rightOperand); - static bool contains(Line2D &leftOperand, Line2D &rightOperand); - static bool contains(Region2D &leftOperand, Region2D &rightOperand); - - // Covers - static bool covers(Line2D &leftOperand, Line2D &rightOperand); - static bool covers(Region2D &leftOperand, Region2D &rightOperand); - - // Covered by - static bool coveredBy(Line2D &leftOperand, Line2D &rightOperand); - static bool coveredBy(Line2D &leftOperand, Region2D &rightOperand); - static bool coveredBy(Region2D &leftOperand, Region2D &rightOperand); -}; - -#endif //POSTGRES_EXT_RELATIONSHIP2D_H diff --git a/include/STO.h b/include/STO.h deleted file mode 100644 index f040e69..0000000 --- a/include/STO.h +++ /dev/null @@ -1,10 +0,0 @@ -// Global include for complex spatial types - -#ifndef SPATIALTYPES_H -#define SPATIALTYPES_H - -#include "Point2D.h" -#include "Line2D.h" -#include "Region2D.h" - -#endif //SPATIALTYPES_H \ No newline at end of file diff --git a/include/SpatialOperations.h b/include/SpatialOperations.h deleted file mode 100644 index 1f36c45..0000000 --- a/include/SpatialOperations.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPATIALOPERATIONS_H -#define SPATIALOPERATIONS_H - -#include "STO.h" - -class SpatialOperations{ -public: - SpatialOperations(); - ~SpatialOperations(); - - Point2D union(Point2D F, Point2D G); - Line2D union(Line2D F, Line2D G); - Region2D union(Region2D F, Region2D G); - - Point2D intersection(Point2D F, Point2D G); - Line2D intersection(Line2D F, Line2D G); - Region2D intersection(Region2D F, Region2D G); - Line2D intersection(Region2D F, Line2D G); - - Point2D difference(Point2D F, Point2D G); - Line2D difference(Line2D F, Line2D G); - Region2D difference(Region2D F, Region2D G); -private: - -}; - -#endif //SPATIALOPERATIONS_H diff --git a/makefile b/makefile index 19f4e89..3607826 100644 --- a/makefile +++ b/makefile @@ -1,19 +1,27 @@ SRC_DIR := ./src +TST_DIR := ./test INC_DIR := ./include OBJ_DIR := ./obj CC := g++ CFLAGS := -std=c++17 -g +LDFLAGS := -lgmpxx -lgmp +LDFLAGS_TST := -lgmpxx -lgmp -lboost_unit_test_framework TARGET := postgres_ext -INC := -I include/ +INC := -I include/ -I$(HOME)/.local/include +LIB := -L$(HOME)/.local/lib SRCS := $(wildcard $(SRC_DIR)/*.cpp postgres_ext.cpp) OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRCS)) all: $(TARGET) $(TARGET): $(OBJS) - $(CC) $(CFLAGS) -o $@ $^ + $(CC) $(CFLAGS) $(LIB) -o $@ $^ $(LDFLAGS) $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(CC) $(CFLAGS) -o $@ -c $< $(INC) +test: $(TST_DIR)/NumberTest +$(TST_DIR)/NumberTest: $(OBJ_DIR)/Number.o $(TST_DIR)/NumberTest.cpp + $(CC) $(CFLAGS) $(LIB) -o $@ $^ $(INC) $(LDFLAGS_TST) + ./$(TST_DIR)/NumberTest clean: rm -rf $(TARGET) $(OBJ_DIR)/*.o diff --git a/postgres_ext.cpp b/postgres_ext.cpp index 56cc071..125c4bb 100644 --- a/postgres_ext.cpp +++ b/postgres_ext.cpp @@ -1,14 +1,247 @@ #include "iostream" // Including all headers to test -#include "include/Region2D.h" #include "include/RGPHalfSegment2D.h" #include "include/RGPOperations2D.h" #include "include/RGPPoint2D.h" #include "include/RGPSegment2D.h" +#include "include/Region2D.h" +#include "include/Point2D.h" +#include "include/Region2DImpl.h" + +#include "include/Point2D.h" +#include "include/Line2D.h" + +void callLine(); +int main(void) +{ + //For point2D + std::cout<<"Point implementation from here : "< vec = *it; + std::cout< vec = *it; + std::cout< -void AVLtree::rebalance(AVLnode *n) { - setBalance(n); - - if (n->balance == -2) { - if (height(n->left->left) >= height(n->left->right)) - n = rotateRight(n); - else - n = rotateLeftThenRight(n); - } - else if (n->balance == 2) { - if (height(n->right->right) >= height(n->right->left)) - n = rotateLeft(n); - else - n = rotateRightThenLeft(n); - } - - if (n->parent != NULL) { - rebalance(n->parent); - } - else { - root = n; - } -} - -template -AVLnode* AVLtree::rotateLeft(AVLnode *a) { - AVLnode *b = a->right; - b->parent = a->parent; - a->right = b->left; - - if (a->right != NULL) - a->right->parent = a; - - b->left = a; - a->parent = b; - - if (b->parent != NULL) { - if (b->parent->right == a) { - b->parent->right = b; - } - else { - b->parent->left = b; - } - } - - setBalance(a); - setBalance(b); - return b; -} - -template -AVLnode* AVLtree::rotateRight(AVLnode *a) { - AVLnode *b = a->left; - b->parent = a->parent; - a->left = b->right; - - if (a->left != NULL) - a->left->parent = a; - - b->right = a; - a->parent = b; - - if (b->parent != NULL) { - if (b->parent->right == a) { - b->parent->right = b; - } - else { - b->parent->left = b; - } - } - - setBalance(a); - setBalance(b); - return b; -} - -template -AVLnode* AVLtree::rotateLeftThenRight(AVLnode *n) { - n->left = rotateLeft(n->left); - return rotateRight(n); -} - -template -AVLnode* AVLtree::rotateRightThenLeft(AVLnode *n) { - n->right = rotateRight(n->right); - return rotateLeft(n); -} - -template -int AVLtree::height(AVLnode *n) { - if (n == NULL) - return -1; - return 1 + std::max(height(n->left), height(n->right)); -} - -template -void AVLtree::setBalance(AVLnode *n) { - n->balance = height(n->right) - height(n->left); -} - -template -void AVLtree::printBalance(AVLnode *n) { - if (n != NULL) { - printBalance(n->left); - std::cout << n->balance << " "; - printBalance(n->right); - } -} - -template -AVLtree::AVLtree(void) : root(NULL) {} - -template -AVLtree::~AVLtree(void) { - delete root; -} - -template -bool AVLtree::insert(T key) { - if (root == NULL) { - root = new AVLnode(key, NULL); - } - else { - AVLnode - *n = root, - *parent; - - while (true) { - if (n->key == key) - return false; - - parent = n; - - bool goLeft = n->key > key; - n = goLeft ? n->left : n->right; - - if (n == NULL) { - if (goLeft) { - parent->left = new AVLnode(key, parent); - } - else { - parent->right = new AVLnode(key, parent); - } - - rebalance(parent); - break; - } - } - } - - return true; -} - -template -void AVLtree::deleteKey(const T delKey) { - if (root == NULL) - return; - - AVLnode - *n = root, - *parent = root, - *delNode = NULL, - *child = root; - - while (child != NULL) { - parent = n; - n = child; - child = delKey >= n->key ? n->right : n->left; - if (delKey == n->key) - delNode = n; - } - - if (delNode != NULL) { - delNode->key = n->key; - - child = n->left != NULL ? n->left : n->right; - - if (root->key == delKey) { - root = child; - } - else { - if (parent->left == n) { - parent->left = child; - } - else { - parent->right = child; - } - - rebalance(parent); - } - } -} - -template -void AVLtree::printBalance() { - printBalance(root); - std::cout << std::endl; -} diff --git a/src/Evaluate.cpp b/src/Evaluate.cpp deleted file mode 100644 index 3102b92..0000000 --- a/src/Evaluate.cpp +++ /dev/null @@ -1,1260 +0,0 @@ -#include "Evaluate.h" -#include "PredicateEnum.h" - -Evaluate::Evaluate() {} - -Evaluate::~Evaluate() {} - -// ------------ Validate ----------------- - -bool Evaluate::validate( Point2DImpl &spatialObj_F, Point2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate) -{ - if( Evaluate::determine(spatialObj_F, spatialObj_G, featureVectorF, featureVectorG) == predicate ) { return true; } else { return false; } -} - -bool Evaluate::validate( Point2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate) -{ - if( Evaluate::determine(spatialObj_F, spatialObj_G, featureVectorF, featureVectorG) == predicate ) { return true; } else { return false; } -} - -bool Evaluate::validate( Point2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate) -{ - if( Evaluate::determine(spatialObj_F, spatialObj_G, featureVectorF, featureVectorG) == predicate ) { return true; } else { return false; } -} - -bool Evaluate::validate( Line2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate) -{ - if( Evaluate::determine(spatialObj_F, spatialObj_G, featureVectorF, featureVectorG) == predicate ) { return true; } else { return false; } -} - -bool Evaluate::validate( Line2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate) -{ - if( Evaluate::determine(spatialObj_F, spatialObj_G, featureVectorF, featureVectorG) == predicate ) { return true; } else { return false; } -} - -bool Evaluate::validate( Region2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG, Predicate predicate) -{ - if( Evaluate::determine(spatialObj_F, spatialObj_G, featureVectorF, featureVectorG) == predicate ) { return true; } else { return false; } -} - -// ------------ Determine ----------------- - -Predicate Evaluate::determine( Point2DImpl &spatialObj_F, Point2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ) -{ - enum VectorFlag {poi_shared, poi_disjoint}; - - if ( featureVectorF[poi_disjoint] ) { // A0B- - if ( featureVectorF[poi_shared] ) { // A0B0, moved right - if ( featureVectorG[poi_disjoint] ) { // A-B0 - return Predicate::overlap; // 5 - } else { - return Predicate::contains; // 4 - } - } else { - return Predicate::disjoint; // 1 - } - } else { // A-B0, moved left - if ( featureVectorG[poi_disjoint] ) { // vg[poi_disjoint] - return Predicate::inside; // 3 - } else { - return Predicate::equal; // 2 - } - - } -} - -Predicate Evaluate::determine( Point2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ) -{ - enum VectorFlag {poi_disjoint, poi_on_interior, poi_on_bound, bound_poi_disjoint}; - - if( featureVectorF[poi_on_interior] ) { // A0B0 - if( featureVectorF[poi_on_bound] ) { // A0&B (boundary B) - if( featureVectorF[poi_disjoint] ) { // A0B- - if ( featureVectorG[bound_poi_disjoint] ) { // A-&B - return Predicate::overlap; // 14 - } else { - return Predicate::overlap; //13 - } - } else { - if ( featureVectorG[bound_poi_disjoint] ) { // A-&B - return Predicate::inside; // 12 - } else { - return Predicate::inside; // 11 - } - } - } else { - if ( featureVectorF[poi_disjoint]) { // A0B- - if ( featureVectorG[bound_poi_disjoint] ) { // A-&B - return Predicate::overlap; // 9 - } else { - return Predicate::overlap; // 10 - } - } else { - if ( featureVectorG[bound_poi_disjoint] ) { // A-&B - return Predicate::inside; // 7 - } else { - return Predicate::inside; // 8 - } - } - } - } else { - if( featureVectorF[poi_on_bound] ) { // A0&B - if ( featureVectorF[poi_disjoint] ) { // A0B- - if ( featureVectorG[bound_poi_disjoint] ) { // A-&B - return Predicate::meet; // 6 - } else { - return Predicate::meet; // 5 - } - } else { - if ( featureVectorG[bound_poi_disjoint] ) { // A-&B - return Predicate::meet; // 4 - } else { - return Predicate::meet; // 3 - } - } - } else { // A-&B - if ( featureVectorG[bound_poi_disjoint] ) { - return Predicate::disjoint; // 2 - } else { - return Predicate::disjoint; // 1 - } - } - } -} - -Predicate Evaluate::determine( Point2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG) -{ - enum VectorFlag {poi_inside, poi_on_bound, poi_outside}; - - if ( featureVectorF[poi_inside] ) { // A0B0 - if ( featureVectorF[poi_on_bound] ) { // A0&B - if ( featureVectorF[poi_outside] ) { // A0B- - return Predicate::overlap; // 7 - } else { - return Predicate::inside; // 6 - } - } else { - if ( featureVectorF[poi_outside] ) { // A0B- - return Predicate::inside; // 4 - } else { - return Predicate::overlap; // 5 - } - } - } else { - if ( featureVectorF[poi_on_bound] ) { // A0&B - if ( featureVectorF[poi_outside] ) { //A0B- - return Predicate::meet; // 3 - } else { - return Predicate::meet; // 2 - } - } else { - return Predicate::disjoint; // 1 - } - } -} - -Predicate Evaluate::determine( Line2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ) -{ - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - if (featureVectorF[bound_shared]) - { - if (featureVectorG[bound_on_interior]) - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorF[bound_disjoint]) - { - if (featureVectorF[seg_unshared]) - { - if (featureVectorG[seg_unshared]) - { - return Predicate::equal; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::inside; - } - else - { - return Predicate::inside; - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::disjoint; - } - else - { - return Predicate::disjoint; - } - } - else - { - if (featureVectorG[seg_unshared]) - { - return Predicate::contains; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::disjoint; - } - else - { - return Predicate::disjoint; - } - } - else - { - if (featureVectorG[seg_unshared]) - { - return Predicate::contains; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorF[seg_unshared]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorF[seg_unshared]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } - else - { - if (featureVectorF[bound_disjoint]) - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - } - else - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[seg_unshared]) - { - return Predicate::contains; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - } - else - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[seg_unshared]) - { - return Predicate::contains; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } - else - { - if (featureVectorG[bound_on_interior]) - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorF[bound_disjoint]) - { - if (featureVectorF[seg_unshared]) - { - if (featureVectorG[seg_unshared]) - { - return Predicate::equal; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::coveredBy; - } - else - { - return Predicate::coveredBy; - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorG[seg_unshared]) - { - return Predicate::covers; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorG[seg_unshared]) - { - return Predicate::covers; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorF[seg_unshared]) - { - return Predicate::coveredBy; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorF[seg_unshared]) - { - return Predicate::coveredBy; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } - else - { - if (featureVectorF[bound_disjoint]) - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - } - else - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[seg_unshared]) - { - return Predicate::covers; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[interior_poi_shared]) - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - } - else - { - if (featureVectorF[bound_on_interior]) - { - if (featureVectorG[seg_unshared]) - { - return Predicate::covers; - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorG[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } -} - -Predicate Evaluate::determine( Line2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ) -{ - enum VectorFlag {seg_unshared, seg_inside, seg_shared, seg_outside, poi_shared, bound_inside, bound_shared, bound_disjoint}; - - if (featureVectorF[bound_shared]) - { - if (featureVectorF[bound_inside]) - { - if (featureVectorF[seg_inside]) - { - if (featureVectorF[bound_disjoint]) - { - if (featureVectorF[seg_outside]) - { - if (featureVectorG[seg_unshared]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[poi_shared]) - { - return Predicate::disjoint; - } - else - { - if (featureVectorG[seg_unshared]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[poi_shared]) - { - return Predicate::disjoint; - } - else - { - if (featureVectorG[seg_unshared]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[poi_shared]) - { - if (featureVectorF[seg_outside]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorG[seg_unshared]) - { - if (featureVectorF[seg_outside]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorF[seg_outside]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[poi_shared]) - { - if (featureVectorF[seg_outside]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorG[seg_unshared]) - { - if (featureVectorF[seg_outside]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorF[seg_outside]) - { - return Predicate::inside; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } - else - { - if (featureVectorF[seg_shared] || featureVectorF[poi_shared]) - { - if (featureVectorF[bound_inside]) - { - if (featureVectorF[seg_inside]) - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorF[seg_outside]) - { - return Predicate::coveredBy; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - else - { - if (featureVectorF[seg_outside]) - { - return Predicate::coveredBy; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - else - { - if (featureVectorF[seg_inside]) - { - if (featureVectorF[seg_outside]) - { - return Predicate::meet; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::meet; - } - else - { - return Predicate::meet; - } - } - } - else - { - if (featureVectorF[bound_inside]) - { - if (featureVectorF[seg_outside]) - { - return Predicate::coveredBy; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorF[seg_outside]) - { - return Predicate::coveredBy; - } - else - { - if (featureVectorF[bound_disjoint]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } -} - -Predicate Evaluate::determine( Region2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG ) -{ - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - if (featureVectorG[one_two] || featureVectorG[two_one]) - { - if (featureVectorF[zero_one] || featureVectorF[one_zero]) - { - if (featureVectorF[zero_one] || featureVectorF[one_zero] || featureVectorF[one_one] || featureVectorG[one_two] || featureVectorG[two_one]) - { - if (featureVectorF[one_two] || featureVectorF[two_one]) - { - if (featureVectorF[one_two] || featureVectorF[two_one] || featureVectorF[one_one] || featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::equal; - } - else - { - return Predicate::coveredBy; - } - } - else - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_one] || featureVectorF[bound_poi_shared]) - { - return Predicate::inside; - } - else - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::coveredBy; - } - else - { - return Predicate::coveredBy; - } - } - } - } - else - { - if (featureVectorF[one_two] || featureVectorF[two_one]) - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_two] || featureVectorF[two_one] || featureVectorG[one_two] || featureVectorG[two_one]) - { - return Predicate::meet; - } - else - { - return Predicate::overlap; - } - } - else - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - else - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_two] || featureVectorF[two_one] || featureVectorG[one_two] || featureVectorG[two_one]) - { - return Predicate::meet; - } - else - { - if (featureVectorF[one_two] || featureVectorF[two_one]) - { - if (featureVectorF[one_two] || featureVectorF[two_one] || featureVectorF[one_one] || featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::covers; - } - else - { - return Predicate::overlap; - } - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_two] || featureVectorF[two_one] || featureVectorG[one_two] || featureVectorG[two_one]) - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_one] || featureVectorF[bound_poi_shared]) - { - return Predicate::disjoint; - } - else - { - return Predicate::meet; - } - } - else - { - if (featureVectorF[one_two] || featureVectorF[two_one]) - { - return Predicate::overlap; - } - else - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_one] || featureVectorF[bound_poi_shared]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - } - else - { - if (featureVectorF[one_two] || featureVectorF[two_one]) - { - if (featureVectorF[zero_one] || featureVectorF[one_zero]) - { - if (featureVectorF[one_two] || featureVectorF[two_one] || featureVectorF[one_one] || featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::covers; - } - else - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_one] || featureVectorF[bound_poi_shared]) - { - if (featureVectorF[one_two] || featureVectorF[two_one] || featureVectorF[one_one] || featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::contains; - } - else - { - return Predicate::overlap; - } - } - else - { - if (featureVectorF[one_two] || featureVectorF[two_one] || featureVectorF[one_one] || featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::covers; - } - else - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } - else - { - if (featureVectorF[zero_two] || featureVectorF[two_zero] || featureVectorF[one_one] || featureVectorF[bound_poi_shared]) - { - if (featureVectorF[zero_one] || featureVectorF[one_zero]) - { - return Predicate::overlap; - } - else - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - else - { - if (featureVectorF[zero_one] || featureVectorF[one_zero]) - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - else - { - if (featureVectorG[zero_one] || featureVectorG[one_zero]) - { - return Predicate::overlap; - } - else - { - return Predicate::overlap; - } - } - } - } - } -} diff --git a/src/Explore.cpp b/src/Explore.cpp deleted file mode 100644 index 49f7903..0000000 --- a/src/Explore.cpp +++ /dev/null @@ -1,663 +0,0 @@ -#include "Explore.h" - -// Point x Point -void Explore::explore(Point2DImpl &spatialObj_F, Point2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_shared, poi_disjoint}; - - PlaneSweep sweep(spatialObj_F.getSequence(), spatialObj_G.getSequence()); - - sweep.select_first(); - - // Terminates when the end of an object is reached, or all flags are turned on - while (sweep.status == TraversalStatus::END_OF_NONE && !(featureVectorF[poi_disjoint] && featureVectorG[poi_disjoint] && featureVectorF[poi_shared])) - { - if (sweep.object == ObjectSelected::OBJ_F) - { - featureVectorF[poi_disjoint] = true; - } - else if (sweep.object == ObjectSelected::OBJ_G) - { - featureVectorG[poi_disjoint] = true; - } - else if (sweep.object == ObjectSelected::BOTH) - { - featureVectorF[poi_shared] = true; - } - - sweep.select_next(); - } - - if (sweep.status == TraversalStatus::END_OF_F) - { - featureVectorG[poi_disjoint] = true; - } - else if (sweep.status == TraversalStatus::END_OF_G) - { - featureVectorF[poi_disjoint] = true; - } - - return; -} - -// Point x Line -void Explore::explore(Point2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_disjoint, poi_on_interior, poi_on_bound, bound_poi_disjoint}; - - PlaneSweep sweep(spatialObj_F.getSequence(), spatialObj_G.getSequence()); - - optional lastDominantPoint = nullopt; // Empty point - - sweep.select_first(); - - while (sweep.status != TraversalStatus::END_OF_G && sweep.status != TraversalStatus::END_OF_BOTH && - !(featureVectorF[poi_disjoint] && featureVectorF[poi_on_interior] && featureVectorF[poi_on_bound] && featureVectorG[bound_poi_disjoint])) - { - if (sweep.object == ObjectSelected::OBJ_F) - { - RGPPoint2D p = sweep.getEventF(); - - if (sweep.pointInSegment(p)) - { - featureVectorF[poi_on_interior] = true; - } - else - { - featureVectorF[poi_disjoint] = true; - } - } - else if (sweep.object == ObjectSelected::OBJ_G) - { - RGPHalfSegment2D h = sweep.getEventG(); - - if (h.dominantPoint == h.segment.point1) // Left halfsegment - { - sweep.insert(h.segment); - } - else // Right halfsegment - { - sweep.remove(h.segment); - } - - optional dp = make_optional(h.dominantPoint); - - if (lastDominantPoint != dp) - { - lastDominantPoint = dp; - - if (!sweep.lookAheadG(h)) - { - featureVectorG[bound_poi_disjoint] = true; - } - } - } - else // BOTH - { - RGPHalfSegment2D h = sweep.getEventG(); - - if (h.dominantPoint == h.segment.point1) // Left halfsegment - { - sweep.insert(h.segment); - } - else // Right halfsegment - { - sweep.remove(h.segment); - } - - lastDominantPoint = make_optional(h.dominantPoint); - - if (sweep.lookAheadG(h)) - { - featureVectorF[poi_on_interior] = true; - } - else - { - featureVectorF[poi_on_bound] = true; - } - } - - sweep.select_next(); - } - - if (sweep.status == TraversalStatus::END_OF_G) - { - featureVectorF[poi_disjoint] = true; - } -} - -// Point x Region -void Explore::explore(Point2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_inside, poi_on_bound, poi_outside}; - - PlaneSweep sweep(spatialObj_F.getSequence(), spatialObj_G.getSequence()); - - sweep.select_first(); - - while (sweep.status == TraversalStatus::END_OF_NONE && !(featureVectorF[poi_inside] && featureVectorF[poi_on_bound] && featureVectorF[poi_outside])) - { - if (sweep.object == ObjectSelected::OBJ_F) - { - RGPPoint2D p = sweep.getEventF(); - - if (sweep.pointOnSegment(p)) - { - featureVectorF[poi_on_bound] = true; - } - else - { - if (auto attr = sweep.getAttributeOfSegmentBelow(p)) - { - if (*attr) - { - featureVectorF[poi_inside] = true; - } - else - { - featureVectorF[poi_outside] = true; - } - } - else - { - featureVectorF[poi_outside] = true; - } - } - } - else - { - RGPAnnotatedHalfSegment2D ah = sweep.getEventG(); - - if (ah.dominantPoint == ah.segment.point1) // Left halfsegment - { - sweep.insert(ah.segment); - } - else // Right halfsegment - { - sweep.remove(ah.segment); - } - - if (sweep.object == ObjectSelected::BOTH) - { - featureVectorF[poi_on_bound] = true; - } - } - - sweep.select_next(); - } - - if (sweep.status == TraversalStatus::END_OF_G) - { - featureVectorF[poi_outside] = true; - } -} - -// Line x Line -void Explore::explore(Line2DImpl &spatialObj_F, Line2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - PlaneSweep sweep(spatialObj_F.getSequence(), spatialObj_G.getSequence()); - - optional lastDominantPointF = nullopt; - optional lastDominantPointG = nullopt; - optional lastBoundaryPointF = nullopt; - optional lastBoundaryPointG = nullopt; - - sweep.select_first(); - - while (sweep.status != TraversalStatus::END_OF_BOTH && - !(featureVectorF[seg_shared] && featureVectorF[interior_poi_shared] && featureVectorF[seg_unshared] && - featureVectorF[bound_on_interior] && featureVectorF[bound_shared] && featureVectorF[bound_disjoint] && - featureVectorG[bound_disjoint] && featureVectorG[bound_on_interior] && featureVectorG[seg_unshared])) - { - if (sweep.object == ObjectSelected::OBJ_F) - { - RGPHalfSegment2D h = sweep.getEventF(); - - if (h.dominantPoint == h.segment.point1) // Left halfsegment - { - sweep.insert(h.segment); - } - else // Right halfsegment - { - sweep.remove(h.segment); - featureVectorF[seg_unshared] = true; - } - - optional dp = make_optional(h.dominantPoint); - - if (lastDominantPointF != dp) - { - lastDominantPointF = dp; - - if (!sweep.lookAheadF(h)) - { - lastBoundaryPointF = dp; - - if (lastBoundaryPointF == lastBoundaryPointG) - { - featureVectorF[bound_shared] = true; - } - else if (lastBoundaryPointF == lastDominantPointG) - { - featureVectorF[bound_on_interior] = true; - } - else if(!sweep.lookAheadG(h)) - { - featureVectorF[bound_disjoint] = true; - } - } - } - - if (dp != lastBoundaryPointF) - { - if (dp == lastBoundaryPointG) - { - featureVectorG[bound_on_interior] = true; - } - else if (dp == lastDominantPointG) - { - featureVectorF[interior_poi_shared] = true; - } - } - } - else if (sweep.object == ObjectSelected::OBJ_G) - { - RGPHalfSegment2D h = sweep.getEventG(); - - if (h.dominantPoint == h.segment.point1) // Left halfsegment - { - sweep.insert(h.segment); - } - else // Right halfsegment - { - sweep.remove(h.segment); - featureVectorG[seg_unshared] = true; - } - - optional dp = make_optional(h.dominantPoint); - - if (lastDominantPointG != dp) - { - lastDominantPointG = dp; - - if (!sweep.lookAheadG(h)) - { - lastBoundaryPointG = dp; - - if (lastBoundaryPointG == lastBoundaryPointF) - { - featureVectorG[bound_shared] = true; - } - else if (lastBoundaryPointG == lastDominantPointF) - { - featureVectorG[bound_on_interior] = true; - } - else if(!sweep.lookAheadF(h)) - { - featureVectorG[bound_disjoint] = true; - } - } - } - - if (dp != lastBoundaryPointG) - { - if (dp == lastBoundaryPointF) - { - featureVectorF[bound_on_interior] = true; - } - else if (dp == lastDominantPointF) - { - featureVectorG[interior_poi_shared] = true; - } - } - } - else // BOTH - { - RGPHalfSegment2D h = sweep.getEventF(); - featureVectorF[seg_shared] = true; - - if (h.dominantPoint == h.segment.point1) // Left halfsegment - { - sweep.insert(h.segment); - } - else // Right halfsegment - { - sweep.remove(h.segment); - } - - optional dp = make_optional(h.dominantPoint); - - if (lastDominantPointF != dp) - { - lastDominantPointF = dp; - - if (!sweep.lookAheadF(h)) - { - lastBoundaryPointF = dp; - } - } - - if (dp != lastDominantPointG) - { - lastDominantPointG = dp; - - if (!sweep.lookAheadG(h)) - { - lastBoundaryPointG = dp; - } - } - - if (lastBoundaryPointF == lastBoundaryPointG) - { - featureVectorF[bound_shared] = true; - } - else - { - if (lastBoundaryPointF == lastDominantPointG) - { - featureVectorF[bound_on_interior] = true; - } - - if (lastBoundaryPointG == lastDominantPointF) - { - featureVectorG[bound_on_interior] = true; - } - } - } - - if (sweep.status == TraversalStatus::END_OF_F) - { - featureVectorG[seg_unshared] = true; - } - else if (sweep.status == TraversalStatus::END_OF_G) - { - featureVectorF[seg_unshared] = true; - } - - sweep.select_next(); - } -} - -// Line x Region -void Explore::explore(Line2DImpl &spatialObj_F, Region2DImpl &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, seg_inside, seg_shared, seg_outside, poi_shared, bound_inside, bound_shared, bound_disjoint}; - - PlaneSweep sweep(spatialObj_F.getSequence(), spatialObj_G.getSequence()); - - optional lastDominantPointF = nullopt; - optional lastDominantPointG = nullopt; - optional lastBoundaryPointF = nullopt; - - sweep.select_first(); - - while (sweep.status != TraversalStatus::END_OF_F && sweep.status != TraversalStatus::END_OF_BOTH && - !(featureVectorF[seg_inside] && featureVectorF[seg_shared] && featureVectorF[seg_outside] && featureVectorF[poi_shared] && - featureVectorF[bound_inside] && featureVectorF[bound_shared] && featureVectorF[bound_disjoint] && featureVectorG[seg_unshared])) - { - if (sweep.object == ObjectSelected::OBJ_F) - { - RGPHalfSegment2D h = sweep.getEventF(); - - if (h.dominantPoint == h.segment.point1) // Left halfsegment - { - sweep.insert(h.segment); - } - else // Right halfsegment - { - if (auto overlapNums = sweep.getOverlapNumbersOfPredecessor(h.segment)) - { - auto [m,n] = *overlapNums; - - if (n == 1) - { - featureVectorF[seg_inside] = true; - } - else - { - featureVectorF[seg_outside] = true; - } - } - - sweep.remove(h.segment); - } - - optional dp = make_optional(h.dominantPoint); - - if (dp != lastDominantPointF) - { - lastDominantPointF = dp; - - if (!sweep.lookAheadF(h)) - { - lastBoundaryPointF = dp; - - if (lastBoundaryPointF == lastDominantPointG || sweep.lookAheadG(h)) - { - featureVectorF[bound_shared] = true; - } - else - { - if (auto overlapNums = sweep.getOverlapNumbersOfPredecessor(h.segment)) - { - auto [m,n] = *overlapNums; - - if (n == 1) - { - featureVectorF[bound_inside] = true; - } - else - { - featureVectorF[bound_disjoint] = true; - } - } - else - { - featureVectorF[bound_disjoint] = true; - } - } - } - } - - if (dp != lastBoundaryPointF && (dp == lastDominantPointG || sweep.lookAheadG(h))) - { - featureVectorF[poi_shared] = true; - } - } - else if (sweep.object == ObjectSelected::OBJ_G) - { - RGPAnnotatedHalfSegment2D ah = sweep.getEventG(); - - if (ah.dominantPoint == ah.segment.point1) // Left halfsegment - { - sweep.insert(ah.segment); - } - else // Right halfsegment - { - sweep.remove(ah.segment); - featureVectorG[seg_unshared] = true; - } - - optional dp = make_optional(ah.dominantPoint); - - if (dp != lastDominantPointG) - { - lastDominantPointG = dp; - } - } - else // BOTH - { - featureVectorF[seg_shared] = true; - - RGPAnnotatedHalfSegment2D ah = sweep.getEventG(); - - if (ah.dominantPoint == ah.segment.point1) // Left halfsegment - { - sweep.insert(ah.segment); - } - else // Right halfsegment - { - sweep.remove(ah.segment); - } - - optional dp = make_optional(ah.dominantPoint); - - if (dp != lastDominantPointF) - { - lastDominantPointF = dp; - - if (!sweep.lookAheadF(ah)) - { - featureVectorF[bound_shared] = true; - } - else - { - featureVectorF[poi_shared] = true; - } - } - - if (dp != lastDominantPointG) - { - lastDominantPointG = dp; - } - } - - if (sweep.status == TraversalStatus::END_OF_G) - { - featureVectorF[seg_outside] = true; - } - - sweep.select_next(); - } - - if (sweep.status == TraversalStatus::END_OF_F) - { - featureVectorG[seg_unshared] = true; - } -} - -//// Region x Region -//void Explore::explore(Region2D &spatialObj_F, Region2D &spatialObj_G, std::vector &featureVectorF, std::vector &featureVectorG) -//{ -// // Indicates what index in the bool vector represents what flag -// enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; -// -// PlaneSweep sweep(spatialObj_F.getSequence(), spatialObj_G.getSequence()); -// -// optional lastDominantPointF = nullopt; -// optional lastDominantPointG = nullopt; -// -// sweep.select_first(); -// -// while (sweep.status == TraversalStatus::END_OF_NONE && -// !(featureVectorF[zero_one] && featureVectorF[one_zero] && featureVectorF[one_two] && featureVectorF[two_one] && featureVectorF[zero_two] && featureVectorF[two_zero] && -// featureVectorF[one_one] && featureVectorF[bound_poi_shared] && featureVectorG[zero_one] && featureVectorG[one_zero] && featureVectorG[one_two] && featureVectorG[two_one])) -// { -// RGPAnnotatedHalfSegment2D ah; -// -// if (sweep.object == ObjectSelected::OBJ_F) -// { -// ah = sweep.getEventF(); -// lastDominantPointF = make_optional(ah.dominantPoint); -// } -// else if (sweep.object == ObjectSelected::OBJ_G) -// { -// ah = sweep.getEventG(); -// lastDominantPointG = make_optional(ah.dominantPoint); -// } -// else // BOTH -// { -// ah = sweep.getEventF() -// lastDominantPointF = make_optional(ah.dominantPoint); -// lastDominantPointG = make_optional(ah.dominantPoint); -// } -// -// if (lastDominantPointF == lastDominantPointG || sweep.lookAheadG(ah) || sweep.lookAheadF(ah)) -// { -// featureVectorF[bound_poi_shared] = true; -// } -// -// if (h.dominantPoint == h.segment.point2) // Right halfsegment -// { -// VectorFlag flag; -// -// if (auto overlapNums = sweep.getOverlapNumbersOf(ah.segment)) -// { -// auto [m,n] = *overlapNums; -// -// switch(m) -// { -// case 0: -// switch(n) -// { -// case 1: -// flag = zero_one; -// break; -// case 2: -// flag = zero_two; -// break; -// default:return; -// } -// break; -// case 1: -// switch(m) -// { -// case 0: -// flag = one_zero; -// break; -// case 1: -// flag = one_one; -// break; -// case 2: -// flag = one_two; -// break; -// default:return; -// } -// break; -// case 2: -// switch(m) -// { -// case 0: -// flag = two_zero; -// break; -// case 1: -// flag = two_one; -// break; -// default:return; -// } -// break; -// default:return; -// } -// } -// -// if (sweep.object == ObjectSelected::OBJ_F) -// { -// featureVectorF[flag] = true; -// } -// else if (sweep.object == ObjectSelected::OBJ_G) -// { -// featureVectorG[flag] = true; -// } -// else if (sweep.object == ObjectSelected::BOTH) -// { -// featureVectorF[flag] = true; -// featureVectorG[flag] = true; -// } -// -// sweep.remove(ah.segment); -// } -// else // Left halfsegment -// { -// sweep.insert(ah.segment); -// -// -// } -// } -//} diff --git a/src/Line2D.cpp b/src/Line2D.cpp index b4add0a..80dd34f 100644 --- a/src/Line2D.cpp +++ b/src/Line2D.cpp @@ -1,81 +1,184 @@ #include "Line2D.h" +#include "Line2DImpl.h" + +struct Line2D::Line2DStore { + Line2DImpl *implPointer; + // Maintains a dummy copy for iterator to work + std::vector vectorOfSegments; + + Line2DStore(std::string linesString) + { + implPointer = new Line2DImpl(linesString); + vectorOfSegments = implPointer->getVectorOfSegments(); + } +}; + +//constructor for Line2D iterator +Line2D::iterator::iterator(RGPHalfSegment2D *ptr1) +{ + ptr = ptr1; +} -class Line2D::Line2DImpl {}; +//overloading * to get output +RGPHalfSegment2D Line2D::iterator::operator*() +{ + return *ptr; +} -Line2D::Line2D() +//operator overloading ++ (post) for incrementing the iterator +RGPHalfSegment2D Line2D::iterator::operator++(int junk) { - // Emtpy + RGPHalfSegment2D *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; } -Line2D::Line2D(std::vector listOfSegments) +//operator overloading ++ (pre) for incrementing the iterator +RGPHalfSegment2D Line2D::iterator::operator++() { - // Emtpy + ptr++; + return *ptr; } -Line2D::Line2D(std::string listOfLine2DString) +bool Line2D::iterator::operator!=(const iterator &it) { - // Emtpy + if(it.ptr==ptr) + return false; + return true; } -Line2D::Line2D(std::ifstream& file) // Send in file for constructor +//overloading == to check if two iterators are equal +bool Line2D::iterator::operator==(const iterator &it) { - // Emtpy + if(it.ptr!=ptr) + return false; + return true; } -Line2D::~Line2D() +//Line2D begin method, return an iterator to the first segment in the sorted order. +Line2D::iterator Line2D::begin() { - // Emtpy + RGPHalfSegment2D *ptr = &(handle->vectorOfSegments[0]); + return iterator(ptr); } +//Line2D begin method, return an iterator to the last segment in the sorted order. +Line2D::iterator Line2D::end() +{ + int t = handle->vectorOfSegments.size(); + return (iterator(&(handle->vectorOfSegments[t-1]))); +} -// Methods -std::string Line2D::getLineString() // Get the line as human readable ASCII string +//method to add new segments to our list of segments +bool Line2D::add(RGPSegment2D rgpSeg2d) { - // Emtpy + bool res = handle->implPointer->add(rgpSeg2d); + handle->vectorOfSegments = handle->implPointer->getVectorOfSegments(); + return res; } -// static -bool Line2D::isEmptyLine() +//method to update a segment in our current list of segments +bool Line2D::update(Line2D::iterator it, RGPSegment2D rgpSeg2d) { - // Emtpy + Line2DImpl::iterator newIt = handle->implPointer->begin(); + for(Line2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();implit++) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->update(newIt, rgpSeg2d); + handle->vectorOfSegments = handle->implPointer->getVectorOfSegments(); + return result; + } -int Line2D::Line2D::getNumberOfSegments() +//method to remove a segment using an iterator +bool Line2D::remove(Line2D::iterator it) +{ + Line2DImpl::iterator newIt = handle->implPointer->begin(); + for(Line2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();implit++) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->remove(newIt); + handle->vectorOfSegments = handle->implPointer->getVectorOfSegments(); + return result; +} + +Line2D::Line2D(std::string listOfLine2DString) { - // Emtpy + handle = new Line2DStore(listOfLine2DString); } -std::vector Line2D::getBoundingBox() +Line2D::~Line2D() { - // Emtpy + delete handle->implPointer; + delete handle; } -bool Line2D::add(RGPSegment2D rgp2d) +// Methods +bool Line2D::isEmptyLine() { - // Emtpy + return handle->implPointer->isEmptyLine(); } -bool Line2D::remove(int index) +void Line2D::printAllLines() { - // Emtpy + handle->implPointer->printAllLines(); } -bool update(int index, RGPSegment2D rgps2d) +int Line2D::Line2D::getNumberOfSegments() { - // Emtpy + return handle->implPointer->getNumberOfSegments(); } bool Line2D::operator==(const Line2D &l2d) { - // Emtpy + int i = 0; + if(handle->vectorOfSegments.size() != l2d.handle->vectorOfSegments.size()) + { + return false; + } + + while(i < l2d.handle->vectorOfSegments.size()) + { + if(handle->vectorOfSegments[i] != l2d.handle->vectorOfSegments[i]) + { + return false; + } + else + i++; + } + return true; } bool Line2D::operator!=(const Line2D &l2d) { - // Emtpy + int i = 0; + if(handle->vectorOfSegments.size() != l2d.handle->vectorOfSegments.size()) + { + return true; + } + + while(i < l2d.handle->vectorOfSegments.size()) + { + if(handle->vectorOfSegments[i] != l2d.handle->vectorOfSegments[i]) + return true; + else + i++; + } + return false; } -RGPSegment2D Line2D::operator[](int index) +RGPSegment2D Line2D::getBoundingBox() { - // Emtpy -} + return handle->implPointer->getBoundingBox(); +} \ No newline at end of file diff --git a/src/Line2DForProgrammer.cpp b/src/Line2DForProgrammer.cpp new file mode 100644 index 0000000..49c405d --- /dev/null +++ b/src/Line2DForProgrammer.cpp @@ -0,0 +1,128 @@ +#include "Line2D.h" +#include "Line2DImpl.h" +#include "Line2DForProgrammer.h" + +struct Line2DForProgrammer::Line2DProgrammerStore +{ + Line2DImpl *implPointer; + // Maintains a dummy copy for iterator to work + std::vector vectorOfSegments; + Line2DProgrammerStore(std::string linesString) + { + implPointer = new Line2DImpl(linesString); + vectorOfSegments = implPointer->getVectorOfSegments(); + + } +}; + + +//constructor for Line2D iterator +Line2DForProgrammer::iterator::iterator(RGPHalfSegment2D *ptr1) +{ + ptr = ptr1; +} + +//overloading * to get output +RGPHalfSegment2D Line2DForProgrammer::iterator::operator*() +{ + return *ptr; +} + +//operator overloading ++ (post) for incrementing the iterator +RGPHalfSegment2D Line2DForProgrammer::iterator::operator++(int junk) +{ + RGPHalfSegment2D *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; +} + +//operator overloading ++ (pre) for incrementing the iterator +RGPHalfSegment2D Line2DForProgrammer::iterator::operator++() +{ + ptr++; + return *ptr; +} + +bool Line2DForProgrammer::iterator::operator!=(const iterator &it) +{ + if(it.ptr==ptr) + return false; + return true; +} + +//overloading == to check if two iterators are equal +bool Line2DForProgrammer::iterator::operator==(const iterator &it) +{ + if(it.ptr!=ptr) + return false; + return true; +} + +//Line2D begin method, return an iterator to the first segment in the sorted order. +Line2DForProgrammer::iterator Line2DForProgrammer::begin() +{ + RGPHalfSegment2D *ptr = &(handle->vectorOfSegments[0]); + return iterator(ptr); +} + +//Line2D begin method, return an iterator to the last segment in the sorted order. +Line2DForProgrammer::iterator Line2DForProgrammer::end() +{ + int t = handle->vectorOfSegments.size(); + return (iterator(&(handle->vectorOfSegments[t-1]))); +} + +//method to add new segments to our list of segments +bool Line2DForProgrammer::add(RGPSegment2D rgpSeg2d) +{ + bool res = handle->implPointer->add(rgpSeg2d); + handle->vectorOfSegments = handle->implPointer->getVectorOfSegments(); + return res; +} + +//method to update a segment in our current list of segments +bool Line2DForProgrammer::update(Line2DForProgrammer::iterator it, RGPSegment2D rgpSeg2d) +{ + Line2DImpl::iterator newIt = handle->implPointer->begin(); + for(Line2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();implit++) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->update(newIt, rgpSeg2d); + handle->vectorOfSegments = handle->implPointer->getVectorOfSegments(); + return result; + +} + +//method to remove a segment using an iterator +bool Line2DForProgrammer::remove(Line2DForProgrammer::iterator it) +{ + Line2DImpl::iterator newIt = handle->implPointer->begin(); + for(Line2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();implit++) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->remove(newIt); + handle->vectorOfSegments = handle->implPointer->getVectorOfSegments(); + return result; +} + +Line2DForProgrammer::Line2DForProgrammer(std::string listOfLine2DString) +{ + handle = new Line2DProgrammerStore(listOfLine2DString); +} + +Line2DForProgrammer::~Line2DForProgrammer() +{ + delete handle->implPointer; + delete handle; +} diff --git a/src/Line2DImpl.cpp b/src/Line2DImpl.cpp index baad4f5..ac20931 100644 --- a/src/Line2DImpl.cpp +++ b/src/Line2DImpl.cpp @@ -1,16 +1,475 @@ -#include "Line2DImpl.h" +#include "../include/Line2D.h" +#include "../include/Line2DImpl.h" +#include +#include +#include +#include +struct Line2DImpl::Line2DImplStore { + std::vector vectorOfSegments; + std::vector boundingBox; +}; + +//constructor for Line2DImpl iterator +Line2DImpl::iterator::iterator(RGPHalfSegment2D *ptr1) +{ + ptr = ptr1; +} + +//overloading * to get output +RGPHalfSegment2D Line2DImpl::iterator::operator*() +{ + return *ptr; +} + +//operator overloading ++ (post) for incrementing the iterator +RGPHalfSegment2D Line2DImpl::iterator::operator++(int junk) +{ + RGPHalfSegment2D *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; +} + +//operator overloading ++ (pre) for incrementing the iterator +RGPHalfSegment2D Line2DImpl::iterator::operator++() +{ + ptr++; + return *ptr; +} + +bool Line2DImpl::iterator::operator!=(const iterator &it) +{ + if(it.ptr==ptr) + return false; + return true; +} + +//overloading == to check if two iterators are equal +bool Line2DImpl::iterator::operator==(const iterator &it) +{ + if(it.ptr!=ptr) + return false; + return true; +} + +//Line2DImpl begin method, return an iterator to the first segment in the sorted order. +Line2DImpl::iterator Line2DImpl::begin() +{ + RGPHalfSegment2D *ptr = &(handle->vectorOfSegments[0]); + return iterator(ptr); +} + +//Line2DImpl begin method, return an iterator to the last segment in the sorted order. +Line2DImpl::iterator Line2DImpl::end() +{ + int t = handle->vectorOfSegments.size(); + return (iterator(&(handle->vectorOfSegments[t-1]))); +} + +//constructor without arguments, just initializes handle Line2DImpl::Line2DImpl() { + handle = new Line2DImplStore(); +} +//Constructors +//constructor which takes in a vector of segments, converts them into half segments and stores it. +Line2DImpl::Line2DImpl(std::vector listOfSegments) +{ + try{ + handle = new Line2DImplStore; + std::vector halfSegments; + //getting segments and converting them to half segments + for(auto it = listOfSegments.begin(); it!=listOfSegments.end();it++) + { + halfSegments.push_back(RGPHalfSegment2D(*it,(*it).point1)); + halfSegments.push_back(RGPHalfSegment2D(*it,(*it).point2)); + } + //sorts all half segments to store a sorted array of segments + lineSort(halfSegments); + handle->vectorOfSegments = halfSegments; + } + catch(int e) + { + std::cout<<"failed"<vectorOfSegments.clear(); + } +} + +//constructor that takes in a string and creates our required segments +Line2DImpl::Line2DImpl(std::string listOfLine2DString) +{ + handle = new Line2DImplStore; + + //pareses string, if successful prints success else prints failed. + if(parseStringToVectorOfLines(listOfLine2DString)) + std::cout << "success" << std::endl; + else{ + handle->vectorOfSegments.clear(); + std::cout << "failed" << std::endl; + } } Line2DImpl::~Line2DImpl() { + delete handle; +} + +// Methods + +std::vector Line2DImpl::getVectorOfSegments() +{ + return handle->vectorOfSegments; +} + +//method to print all the segments in the object +void Line2DImpl::printAllLines() +{ + std::cout<<"("; + std::vector x = handle->vectorOfSegments; + for(auto i = x.begin(); i!=x.end(); i++) + std::cout<<(*i).segment; + std::cout<<")"; +} +//method to check if our object is empty or has data. +bool Line2DImpl::isEmptyLine() +{ + return handle->vectorOfSegments.empty(); } -std::vector Line2DImpl::getSequence() +//method to get total number of segments in out object +int Line2DImpl::Line2DImpl::getNumberOfSegments() { + return (handle->vectorOfSegments.size())/2; +} + +//method to find bounding box diagonal for the given list of segments +RGPSegment2D Line2DImpl::getBoundingBox() +{ + //we are computing bounding box every time because it may change after adds, updates or removes + std::vector halfSegments; + halfSegments = handle->vectorOfSegments; + + //p1 is the first point of the bounding box segment + RGPPoint2D p1(halfSegments[0].segment.point1.x,halfSegments[0].segment.point1.y); + RGPPoint2D p2(halfSegments[halfSegments.size()-1].segment.point2.x,halfSegments[halfSegments.size()-1].segment.point2.y); + auto maxy = halfSegments[0].segment.point2.y; + + //iterate through the loop to find max y coordinate in the given lis of points + for(auto it = halfSegments.begin();it!= halfSegments.end();it++) + { + if(maxy<(*it).segment.point1.y) + maxy = (*it).segment.point1.y; + if(maxy<(*it).segment.point2.y) + maxy = (*it).segment.point2.y; + } + + //we make the next point taking the x of p2 and maxy found in the above loop + RGPSegment2D seg(p1,RGPPoint2D(p2.x,maxy)); + + //returing the diagonal that tells us the bounding box + return seg; +} + +//method to add new segments to our list of segments +bool Line2DImpl::add(RGPSegment2D rgpSeg2d) +{ + try + { + + //check if the line object is empty + if(isEmptyLine()){ + + //if empty pushback + handle->vectorOfSegments.push_back(RGPHalfSegment2D(rgpSeg2d,rgpSeg2d.point1)); + handle->vectorOfSegments.push_back(RGPHalfSegment2D(rgpSeg2d,rgpSeg2d.point2)); + } + else{ + + //if not empty, add them and sort the segments in the object + handle->vectorOfSegments.push_back(RGPHalfSegment2D(rgpSeg2d,rgpSeg2d.point1)); + handle->vectorOfSegments.push_back(RGPHalfSegment2D(rgpSeg2d,rgpSeg2d.point2)); + lineSort(handle->vectorOfSegments); + } + } + catch(int e) + { + return false; + } + return true; +} + +//method to update a segment in our current list of segments +bool Line2DImpl::update(Line2DImpl::iterator it, RGPSegment2D rgpSeg2d) +{ + try + { + if(isEmptyLine()){ + //check if empty and return false because we cannot update + return false; + } + else{ + + //run through the list, find the segment to be updated and remove that segment + for(std::vector::iterator i = handle->vectorOfSegments.begin(); i!= handle->vectorOfSegments.end() ; i++) + { + if((*i).segment == (*it).segment) + { + int index = it.ptr - &(handle->vectorOfSegments[0]); + handle->vectorOfSegments.erase(handle->vectorOfSegments.begin()+index); + } + } + //add the new segment and sort it + handle->vectorOfSegments.push_back(RGPHalfSegment2D(rgpSeg2d,rgpSeg2d.point1)); + handle->vectorOfSegments.push_back(RGPHalfSegment2D(rgpSeg2d,rgpSeg2d.point2)); + lineSort(handle->vectorOfSegments); + } + } + catch(int e) + { + return false; + } + return true; +} + +//method to remove a segment using an iterator +bool Line2DImpl::remove(Line2DImpl::iterator it) +{ + try + { + if(isEmptyLine()){ + + //return false if the object is empty + return false; + } + else{ + + //run a loop through the vector, find and remove the segment. + for(std::vector::iterator i = handle->vectorOfSegments.begin(); i!= handle->vectorOfSegments.end() ; i++) + { + if((*i).segment == (*it).segment) + { + int index = it.ptr - &(handle->vectorOfSegments[0]); + handle->vectorOfSegments.erase(handle->vectorOfSegments.begin()+index); + } + } + } + } + catch(int e) + { + return false; + } + return true; +} + +//overloading == operator for the Line2DImpl type +bool Line2DImpl::operator==(const Line2DImpl &l2d) +{ + int i = 0; + if(handle->vectorOfSegments.size() != l2d.handle->vectorOfSegments.size()) + { + return false; + } + + while(i < l2d.handle->vectorOfSegments.size()) + { + if(handle->vectorOfSegments[i] != l2d.handle->vectorOfSegments[i]) + { + return false; + } + else + i++; + } + return true; +} + +//overloading != operator for the Line2DImpl type +bool Line2DImpl::operator!=(const Line2DImpl &l2d) +{ + int i = 0; + if(handle->vectorOfSegments.size() != l2d.handle->vectorOfSegments.size()) + { + return true; + } + + while(i < l2d.handle->vectorOfSegments.size()) + { + if(handle->vectorOfSegments[i] != l2d.handle->vectorOfSegments[i]) + return true; + else + i++; + } + return false; +} + +//overloading [] operator for the Line2DImpl type +Line2DImpl Line2DImpl::operator[](int index) +{ + std::vector t; + t.push_back(handle->vectorOfSegments[index].segment); + Line2DImpl temp(t); + return temp; +} + +//overloading = operator for the Line2DImpl type +Line2DImpl Line2DImpl::operator=(const Line2DImpl &l2d) +{ + handle->vectorOfSegments.clear(); + handle->vectorOfSegments = l2d.handle->vectorOfSegments; +} + +//merge sort to sort our vector of halfsegments +void Line2DImpl::lineSort(std::vector &bar) +{ + if (bar.size() <= 1) + return; + + int mid = bar.size() / 2; + std::vector l; + std::vector r; + + for (size_t j = 0; j < mid;j++) + l.push_back(bar[j]); + for (size_t j = 0; j < (bar.size()) - mid; j++) + r.push_back(bar[mid + j]); + + lineSort(l); + lineSort(r); + mergeSort(l, r, bar); +} + + +void Line2DImpl::mergeSort(std::vector &left, std::vector &right, std::vector &bars) +{ + int nL = left.size(); + int nR = right.size(); + int i = 0, j = 0, k = 0; + + while (j < nL && k < nR) + { + if (left[j] <= + right[k]) { + bars[i] = left[j]; + j++; + } + else { + bars[i] = right[k]; + k++; + } + i++; + } + while (j < nL) { + bars[i] = left[j]; + j++; i++; + } + while (k < nR) { + bars[i] = right[k]; + k++; i++; + } +} + +//method to parse a string of segments to make our vector +bool Line2DImpl::parseStringToVectorOfLines(std::string st) +{ + // line2ed format + // (((a1,b1),(c1,d1)),((a2,b2),(c2,d2)),((a3,b3),(c3,d3)),((a4,b4),(c4,d4))) + + int pos,flag = 0; + std::string num1,num2,num3,num4; + std::string s = st; + std::string delimiter = ","; + std::vector segments; + std::vector halfSegments; + + try{ + + //erase first and last (..*) and append a , + s.erase(0,1); + s.erase(s.length()-1,1); + s.append(","); + pos = s.find(delimiter); + std::string a = ""; + + //keep finding the delimiter and get our required numbers + while(pos != std::string::npos) + { + if(flag == 0){ + s.erase(0,1); // delete starting '(' + } + else if(flag == 3){ + s.erase(pos-1,1); // delete ending ')' + flag=-1; + } + + if(flag == 0){ + a = s.substr(0, pos); + } + else if(flag == -1){ + a = s.substr(0, pos-1); + } + else{ + a = s.substr(0, pos+1); + } + + if(a.length() >= 2) + { + try + { + //find num1, num2, num3, num4 + if(a[0]=='(' && flag == 0) + { + num1 = a.substr(1,a.length()-2); + } + else if(!(a.substr(a.length()-2,1)).compare(")") && flag == 1) + { + num2 = a.substr(0,a.length()-2); + } + else if(a[0]=='(' && flag == 2) + { + num3 = a.substr(1,a.length()-2); + } + else if(!(a.substr(a.length()-1,1)).compare(")") && flag == -1) + { + num4 = a.substr(0,a.length()-1); + //make the required segments and half segments and push back into a temporary segment and half segment vector + segments.push_back(RGPSegment2D(RGPPoint2D(Number(num1),Number(num2)),RGPPoint2D(Number(num3),Number(num4)))); + halfSegments.push_back(RGPHalfSegment2D(RGPSegment2D(RGPPoint2D(Number(num1),Number(num2)),RGPPoint2D(Number(num3),Number(num4))),RGPPoint2D(Number(num1),Number(num2)))); + halfSegments.push_back(RGPHalfSegment2D(RGPSegment2D(RGPPoint2D(Number(num1),Number(num2)),RGPPoint2D(Number(num3),Number(num4))),RGPPoint2D(Number(num3),Number(num4)))); + + } + else{ + //return false for an erroneous input + return false; + } + } + catch(int e){ + return false; + } + } + else + { + //return false for an erroneous input + return false; + } + //delete till the first delimiter and continue until we get all the segments + if(flag < 1){ + s.erase(0, pos); + } + else{ + s.erase(0, pos + delimiter.length()); + } + pos = s.find(delimiter); + flag++; + } + //sort the list of half segments obtained and assign them to the vector of segments + lineSort(halfSegments); + handle->vectorOfSegments = halfSegments; + return true; + } + catch(int e){ + return false; + } } \ No newline at end of file diff --git a/src/Number.cpp b/src/Number.cpp index 3932f70..db0ba4f 100644 --- a/src/Number.cpp +++ b/src/Number.cpp @@ -1,44 +1,300 @@ -#include "Number.h" +#include "../include/Number.h" +#include +#include +#include + +struct Number::NumberImpl +{ + mpq_class num; +}; // Constructors // Default number value is 0 -// Number::Number() {} +Number::Number() +{ + p = new NumberImpl; + mpq_class temp; + p->num = temp; +} + +// Copy constructor +Number::Number(const Number &n) +{ + p = new NumberImpl; + p->num = n.p->num; +} // The string will be converted to a rational number -Number::Number(std::string number) {} +Number::Number(std::string number) +{ + std::string denom = "/1"; + std::regex decimal("^-?[0-9]+(\\.[0-9]+)?$"); -// Fraction of the form n/1 -// Number::Number(int n) {} + if (!std::regex_match(number, decimal)) + { + throw std::invalid_argument("Argument should be a decimal number!"); + } -// Fraction of the form n/d -// Number::Number(int n, int d) {} + size_t dec_point_pos = number.find('.'); + if (dec_point_pos != std::string::npos) + { + denom.append(number.length() - dec_point_pos - 1, '0'); + number.replace(dec_point_pos, 1, ""); + } -// Destructor -Number::~Number() {} + p = new NumberImpl; + mpq_class temp(number + denom, 10); + p->num = temp; +} -// Number Impl Struct -struct NumberImpl {}; +// Destructor +Number::~Number() +{ + delete p; +} // Override arithmetic operators -Number& Number::operator+ (const Number& n) const {} -Number& Number::operator+= (const Number& n) {} -Number& Number::operator- (const Number& n) const {} -Number& Number::operator-= (const Number& n) {} -Number& Number::operator* (const Number& n) const {} -Number& Number::operator*= (const Number& n) {} -Number& Number::operator/ (const Number& n) const {} -Number& Number::operator/= (const Number& n) {} -Number& Number::operator^ (const int n) const {} +Number Number::operator=(const Number &n) +{ + p->num = n.p->num; + return *this; +} + +Number Number::operator+(const Number &n) const +{ + Number ret; + ret.p->num = p->num + n.p->num; + return ret; +} + +Number Number::operator+=(const Number &n) +{ + p->num = p->num + n.p->num; + return *this; +} + +Number Number::operator-(const Number &n) const +{ + Number ret; + ret.p->num = p->num - n.p->num; + return ret; +} + +Number Number::operator-=(const Number &n) +{ + p->num = p->num - n.p->num; + return *this; +} + +Number Number::operator*(const Number &n) const +{ + Number ret; + ret.p->num = p->num * n.p->num; + return ret; +} + +Number Number::operator*=(const Number &n) +{ + p->num = p->num *= n.p->num; + return *this; +} + +Number Number::operator/(const Number &n) const +{ + Number ret; + ret.p->num = p->num / n.p->num; + return ret; +} + +Number Number::operator/=(const Number &n) +{ + p->num = p->num /= n.p->num; + return *this; +} + +Number Number::operator^(const int n) const +{ + Number ret; + mpz_pow_ui(ret.p->num.get_num_mpz_t(), p->num.get_num_mpz_t(), + (unsigned long)n); + mpz_pow_ui(ret.p->num.get_den_mpz_t(), p->num.get_den_mpz_t(), + (unsigned long)n); + ret.p->num.canonicalize(); + return ret; +} // Override comparison operators -bool Number::operator< (const Number& n) const {} -bool Number::operator<= (const Number& n) const {} -bool Number::operator> (const Number& n) const {} -bool Number::operator>= (const Number& n) const {} -bool Number::operator== (const Number& n) const {} +bool Number::operator<(const Number &n) const +{ + return p->num < n.p->num; +} + +bool Number::operator<=(const Number &n) const +{ + return p->num <= n.p->num; +} + +bool Number::operator>(const Number &n) const +{ + return p->num > n.p->num; +} + +bool Number::operator>=(const Number &n) const +{ + return p->num >= n.p->num; +} + +bool Number::operator==(const Number &n) const +{ + return p->num == n.p->num; +} + +bool Number::operator!=(const Number &n) const +{ + return p->num != n.p->num; +} + +Number Number::sqrt() const +{ + Number ret; + mpf_class float_num(p->num); + mpf_sqrt(float_num.get_mpf_t(), float_num.get_mpf_t()); + ret.p->num = mpq_class(float_num); + return ret; +} + +Number Number::sqrt(size_t digits) const +{ + std::string quotient = to_string(digits * 2); + if (quotient[0] == '-') + { + throw std::runtime_error("Square root of a negative number is not supported!"); + } + + std::string full_divisor(quotient); + size_t quot_int_len = quotient.find('.'); + full_divisor.replace(quot_int_len, 1, ""); + + if (quot_int_len == std::string::npos) + { + quot_int_len = quotient.length(); + } + + mpz_class curr_divisor; + std::string curr_dividend; + std::string square_root; + if (quot_int_len % 2 != 0) + { + full_divisor = '0' + full_divisor; + quot_int_len++; + } + + for (int i = 0; i < digits + quot_int_len / 2; i++) + { + curr_dividend += full_divisor.substr(i * 2, 2); + for (int j = 0; j < 10; j++) + { + mpz_class curr_dividend_mpz(curr_dividend); + mpz_class temp_divisor = curr_divisor * 10 + j + 1; + if (temp_divisor * (j + 1) > curr_dividend_mpz) + { + curr_dividend_mpz -= (curr_divisor * 10 + j) * j; + curr_divisor = curr_divisor * 10 + 2 * j; + curr_dividend = curr_dividend_mpz.get_str(); + square_root += std::to_string(j); + break; + } + } + } + + square_root.insert(quot_int_len / 2, "."); + Number ret(square_root); + return ret; +} + +std::string Number::to_string(size_t digits) const +{ + mpz_class den_mpz = p->num.get_den(); + std::string num = p->num.get_num().get_str(); + std::string den = p->num.get_den().get_str(); + bool is_negative = num[0] == '-'; + if (is_negative) + { + num.erase(0, 1); + } + + size_t num_int_len = num.find('.'); + if (num_int_len == std::string::npos) + { + num_int_len = num.length(); + } + + std::string curr_div; + std::string quotient; + for (int i = 0; i < num_int_len; i++) + { + curr_div += num.at(i); + mpz_class curr_div_mpz(curr_div); + if (curr_div_mpz > den_mpz) + { + mpz_class quotient_digit = curr_div_mpz / den_mpz; + mpz_class remainder = curr_div_mpz % den_mpz; + quotient += quotient_digit.get_str(); + curr_div = remainder.get_str(); + } + else + { + quotient += '0'; + } + } + + quotient += '.'; + + while (digits > 0) + { + curr_div += '0'; + mpz_class curr_div_mpz(curr_div); + if (curr_div_mpz > den_mpz) + { + mpz_class quotient_digit = curr_div_mpz / den_mpz; + mpz_class remainder = curr_div_mpz % den_mpz; + quotient += quotient_digit.get_str(); + curr_div = remainder.get_str(); + } + else + { + quotient += '0'; + } + digits--; + } + + size_t non_zero_idx = quotient.find_first_not_of('0'); + if (quotient[non_zero_idx] == '.') + { + non_zero_idx--; + } + + quotient.erase(0, non_zero_idx); + + if (is_negative) + { + quotient.insert(0, 1, '-'); + } -Number& Number::sqrt() const {} + return quotient; +} // Overriding the output and input operator -// std::ostream& Number::operator<<(std::ostream& os, const Number& n) {} -// std::istream& Number::operator>>(std::istream& is, Number& n) {} +std::ostream &operator<<(std::ostream &os, const Number &n) +{ + os << n.p->num.get_d(); + return os; +} +std::istream &operator>>(std::istream &is, Number &n) +{ + std::string input; + getline(is, input); + Number temp(input); + n.p->num = temp.p->num; + return is; +} diff --git a/src/PlaneSweep.cpp b/src/PlaneSweep.cpp deleted file mode 100644 index d8ef327..0000000 --- a/src/PlaneSweep.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include "../include/PlaneSweep.h" - -//Constructors -template -PlaneSweep::PlaneSweep(typename std::vector::iterator startIteratorF, typename std::vector::iterator endIteratorF, - typename std::vector::iterator startIteratorG, typename std::vector::iterator endIteratorG) : - staticIteratorF(startIteratorF), endStaticIteratorF(endIteratorF), staticIteratorG(startIteratorG), endStaticIteratorG(endIteratorG) -{ - object = ObjectSelected::NONE; - status = TraversalStatus::END_OF_NONE; -} - -template -PlaneSweep::~PlaneSweep() -{ - //Empty -} - -template -void PlaneSweep::select_first() -{ - if (!staticSequenceF.empty()) - { - if (!staticSequenceG.empty()) - { - if ((*staticIteratorG) > (*staticIteratorF)) - { - object = ObjectSelected::OBJ_F; - } - else if ((*staticIteratorG) < (*staticIteratorF)) - { - object = ObjectSelected::OBJ_G; - } - else - { - object = ObjectSelected::BOTH; - } - status = TraversalStatus::END_OF_NONE; - } - else - { - status = TraversalStatus::END_OF_G; - } - } - else if (!staticSequenceG.empty()) - { - status = TraversalStatus::END_OF_F; - } - else - { - status = TraversalStatus::END_OF_BOTH; - } - return; -} - -template -void PlaneSweep::select_next() { - if (object == ObjectSelected::OBJ_F) - { - if (++staticIteratorF < endStaticIteratorF) - { - if (status != TraversalStatus::END_OF_G) - { - if ( (*staticIteratorG) > (*staticIteratorF)) - { - object = ObjectSelected::OBJ_F; - } - else if ((*staticIteratorG) < (*staticIteratorF)) - { - object = ObjectSelected::OBJ_G; - } - else - { - object = ObjectSelected::BOTH; - } - } - else - { - object = ObjectSelected::OBJ_F; - } - } - else - { - if (status == TraversalStatus::END_OF_G) - { - object = ObjectSelected::NONE; - status = TraversalStatus::END_OF_BOTH; - } - else - { - object = ObjectSelected::OBJ_G; - status = TraversalStatus::END_OF_F; - } - } - } - else if (object == ObjectSelected::OBJ_G) - { - if (++staticIteratorG < endStaticIteratorG) - { - if (status != TraversalStatus::END_OF_F) - { - if ((*staticIteratorG) > (*staticIteratorF)) - { - object = ObjectSelected::OBJ_F; - } - else if ((*staticIteratorG) < (*staticIteratorF)) - { - object = ObjectSelected::OBJ_G; - } - else - { - object = ObjectSelected::BOTH; - } - } - else - { - object = ObjectSelected::OBJ_G; - } - } - else - { - if (status == TraversalStatus::END_OF_F) - { - object = ObjectSelected::NONE; - status = TraversalStatus::END_OF_BOTH; - } - else - { - object = ObjectSelected::OBJ_F; - status = TraversalStatus::END_OF_G; - } - } - } - else if (object == ObjectSelected::BOTH) - { - ++staticIteratorF; - ++staticIteratorG; - - bool check_F = staticIteratorF < endStaticIteratorF; - bool check_G = staticIteratorG < endStaticIteratorG; - - if (check_F && check_G) - { - if ((*staticIteratorG) > (*staticIteratorF)) - { - object = ObjectSelected::OBJ_F; - } - else if ((*staticIteratorG) < (*staticIteratorF)) - { - object = ObjectSelected::OBJ_G; - } - else - { - object = ObjectSelected::BOTH; - } - } - else if (check_F) - { - object = ObjectSelected::OBJ_F; - status = TraversalStatus::END_OF_G; - } - else if (check_G) - { - object = ObjectSelected::OBJ_G; - status = TraversalStatus::END_OF_F; - } - else - { - object = ObjectSelected::NONE; - status = TraversalStatus::END_OF_BOTH; - } - } -} - -template -F PlaneSweep::getEventF() -{ - // Get event returns the element to which the logical pointer of a - // point or half segment sequence of an object points to - return *staticIteratorF; -} - -template -G PlaneSweep::getEventG() -{ - // Get event returns the element to which the logical pointer of a - // point or half segment sequence of an object points to - return *staticIteratorG; -} - -template -bool PlaneSweep::pointOnSegment(RGPPoint2D p) -{ - // Checks whether a given point lies on/in any segment of the sweep line status - -} - -template -bool PlaneSweep::pointInSegment(RGPPoint2D p) -{ - // Checks whether a given point lies on/in any segment of the sweep line status - - -} - -template -// Inserts/Removes a segment from the sweep line status when -// it's left/right half segment is encountered -void PlaneSweep::insert(RGPSegment2D s) -{ - sweepLineStatus.insert(s); -} - - -template -void PlaneSweep::remove(RGPSegment2D s) -{ - sweepLineStatus.deleteKey(s); -} - -template -bool PlaneSweep::lookAheadF(RGPHalfSegment2D h) -{ - // Check if the dominant points of the given halfsegment and the next - // halfsegment (after the current index) of the indicated sequence are equal - if (staticIteratorF == endStaticIteratorF) { - return (*++staticIteratorF) == h; - } else { - return false; - } -} - -template -bool PlaneSweep::lookAheadG(RGPHalfSegment2D h) -{ - // Check if the dominant points of the given halfsegment and the next - // halfsegment (after the current index) of the indicated sequence are equal - if (staticIteratorG == endStaticIteratorG) { - return (*++staticIteratorG) == h; - } else { - return false; - } -} - - -template -optional PlaneSweep::getAttributeOfSegmentBelow(RGPPoint2D p) -{ - // Returns the nearest annotated halfsegment, from the sweep line status, - // below a given point, if there is one - - // Loops through sweep line status, checking if the segment is classified as less than our RGPPoint2D - // Returns the first one that is true - -} - -template -optional> PlaneSweep::getOverlapNumbersOfPredecessor(RGPSegment2D s) -{ - // Returns the overlap numbers of the predecessor to the given segment in the sweep line status - -} - -template -optional> PlaneSweep::getOverlapNumbersOf(RGPSegment2D s) -{ - // Returns the overlap numbers of the given segment in the sweep line status -} diff --git a/src/Point2D.cpp b/src/Point2D.cpp index 8b81f86..8fa1532 100644 --- a/src/Point2D.cpp +++ b/src/Point2D.cpp @@ -1,80 +1,178 @@ #include "Point2D.h" +#include "Point2DImpl.h" + +struct Point2D::Point2DStore +{ + Point2DImpl *implPointer; + // Maintains a dummy copy for iterator to work + std::vector vectorOfPoints; + + Point2DStore(std::string pointsString) + { + implPointer = new Point2DImpl(pointsString); + vectorOfPoints = implPointer->getVectorOfPoints(); + } + + Point2DStore(std::vector pointVector) + { + implPointer = new Point2DImpl(pointVector); + vectorOfPoints = implPointer->getVectorOfPoints(); + } +}; -class Point2D::Point2DImpl {}; -Point2D::Point2D() +Point2D::iterator::iterator(RGPPoint2D *ptr1) { - // Emtpy + ptr = ptr1; } -Point2D::Point2D(std::vector listOfPoints) +RGPPoint2D Point2D::iterator::operator*() { - // Emtpy + return *ptr; } -Point2D::Point2D(std::ifstream& file) +RGPPoint2D Point2D::iterator::operator++(int junk) { - // Emtpy + RGPPoint2D *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; } -Point2D::Point2D(std::string listOfPoint2DString) +RGPPoint2D Point2D::iterator::operator++() { - // Emtpy + ptr++; + return *ptr; } -Point2D::~Point2D() +bool Point2D::iterator::operator!=(const iterator &it) +{ + if(it.ptr==ptr) + return false; + return true; +} +bool Point2D::iterator::operator==(const iterator &it) { - // Emtpy + if(it.ptr!=ptr) + return false; + return true; } +Point2D::iterator Point2D::begin() +{ + RGPPoint2D *ptr = &(handle->vectorOfPoints[0]); + return iterator(ptr); +} -std::string getPointString() // Get the point as human readable ASCII string +Point2D::iterator Point2D::end() { - // Emtpy + int t = handle->vectorOfPoints.size(); + return (iterator(&(handle->vectorOfPoints[t-1]))); } -// static -bool Point2D::isEmptyPoint() + +Point2D::Point2D(std::string listOfPoint2DString) { - // Emtpy + handle = new Point2DStore(listOfPoint2DString); } -bool Point2D::operator==(const Point2D &p2d) +Point2D::~Point2D() { - // Emtpy + delete handle->implPointer; + delete handle; } -bool Point2D::operator!=(const Point2D &p2d) +bool Point2D::isEmptyPoint() { - // Emtpy + return handle->implPointer->isEmptyPoint(); } -RGPPoint2D Point2D::operator[](int index) +void Point2D::printAllPoints() { - // Emtpy + handle->implPointer->printAllPoints(); } int Point2D::getNumberOfPoints() { - // Emtpy + return handle->implPointer->getNumberOfPoints(); } -std::vector Point2D::getBoundingBox() + +//this method is used to add a new point to Point2D object +bool Point2D::add(RGPPoint2D rgpp2d) { - // Emtpy + bool result = handle->implPointer->add(rgpp2d); + handle->vectorOfPoints = handle->implPointer->getVectorOfPoints(); + return result; } -bool Point2D::add(RGPPoint2D rgpp2d) +//this method is used to update a point at a particular index +bool Point2D::update(Point2D::iterator it, RGPPoint2D rgpp2d) +{ + Point2DImpl::iterator newIt = handle->implPointer->begin(); + for(Point2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();implit++) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->update(newIt, rgpp2d); + handle->vectorOfPoints = handle->implPointer->getVectorOfPoints(); + return result; +} + + +//removes a particular point in the vector of points +bool Point2D::remove(Point2D::iterator it) { - // Emtpy + Point2DImpl::iterator newIt = handle->implPointer->begin(); + for(Point2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();implit++) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->remove(newIt); + handle->vectorOfPoints = handle->implPointer->getVectorOfPoints(); + return result; } -bool Point2D::update(int index, RGPPoint2D rgpp2d) +bool Point2D::operator==(const Point2D &p2d) +{ + int i=0; + while(i< p2d.handle->vectorOfPoints.size()) + { + if(handle->vectorOfPoints[i] != p2d.handle->vectorOfPoints[i]) + return false; + else + i++; + } + if(handle->vectorOfPoints.size() == p2d.handle->vectorOfPoints.size()) + return true; + else + return false; +} + +bool Point2D::operator!=(const Point2D &p2d) { - // Emtpy + int i=0; + if(handle->vectorOfPoints.size() != p2d.handle->vectorOfPoints.size()) + return true; + while(i< p2d.handle->vectorOfPoints.size()) + { + if(handle->vectorOfPoints[i] != p2d.handle->vectorOfPoints[i]) + return true; + else + i++; + } + return false; } -bool Point2D::remove(int index) +RGPSegment2D Point2D::getBoundingBox() { - // Emtpy + return handle->implPointer->getBoundingBox(); } diff --git a/src/Point2DForProgrammer.cpp b/src/Point2DForProgrammer.cpp new file mode 100644 index 0000000..93e03f6 --- /dev/null +++ b/src/Point2DForProgrammer.cpp @@ -0,0 +1,129 @@ +#include "Point2DForProgrammer.h" +#include "Point2DImpl.h" + +struct Point2DForProgrammer::Point2DProgrammerStore +{ + Point2DImpl *implPointer; + // Maintains a dummy copy for iterator to work + std::vector vectorOfPoints; + + Point2DProgrammerStore(std::string pointsString) + { + implPointer = new Point2DImpl(pointsString); + vectorOfPoints = implPointer->getVectorOfPoints(); + } + + Point2DProgrammerStore(std::vector pointVector) + { + implPointer = new Point2DImpl(pointVector); + vectorOfPoints = implPointer->getVectorOfPoints(); + } +}; + +Point2DForProgrammer::iterator::iterator(RGPPoint2D *ptr1) +{ + ptr = ptr1; +} + +RGPPoint2D Point2DForProgrammer::iterator::operator*() +{ + return *ptr; +} + +RGPPoint2D Point2DForProgrammer::iterator::operator++(int junk) +{ + RGPPoint2D *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; +} + +RGPPoint2D Point2DForProgrammer::iterator::operator++() +{ + ptr++; + return *ptr; +} + +bool Point2DForProgrammer::iterator::operator!=(const iterator &it) +{ + if(it.ptr==ptr) + return false; + return true; +} +bool Point2DForProgrammer::iterator::operator==(const iterator &it) +{ + if(it.ptr!=ptr) + return false; + return true; +} + +Point2DForProgrammer::iterator Point2DForProgrammer::begin() +{ + RGPPoint2D *ptr = &(handle->vectorOfPoints[0]); + return iterator(ptr); +} + +Point2DForProgrammer::iterator Point2DForProgrammer::end() +{ + int t = handle->vectorOfPoints.size(); + return (iterator(&(handle->vectorOfPoints[t-1]))); +} + + +Point2DForProgrammer::Point2DForProgrammer(std::vector pointVector) +{ + handle = new Point2DProgrammerStore(pointVector); +} + +Point2DForProgrammer::Point2DForProgrammer(std::string listOfPoint2DString) +{ + handle = new Point2DProgrammerStore(listOfPoint2DString); +} + +Point2DForProgrammer::~Point2DForProgrammer() +{ + delete handle->implPointer; + delete handle; +} + +// Adds a new RGPPoint2D to the existing Point2D object +bool Point2DForProgrammer::add(RGPPoint2D rgpp2d) +{ + bool result = handle->implPointer->add(rgpp2d); + handle->vectorOfPoints = handle->implPointer->getVectorOfPoints(); + return result; +} + +// Updates RGPPoint2D existing at specified index +bool Point2DForProgrammer::update(Point2DForProgrammer::iterator it, RGPPoint2D rgpp2d) +{ + Point2DImpl::iterator newIt = handle->implPointer->begin(); + for(Point2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();++implit) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->update(newIt, rgpp2d); + handle->vectorOfPoints = handle->implPointer->getVectorOfPoints(); + return result; +} + +// Removes a RGPPoint2D at specified index +bool Point2DForProgrammer::remove(Point2DForProgrammer::iterator it) +{ + Point2DImpl::iterator newIt = handle->implPointer->begin(); + for(Point2DImpl::iterator implit = handle->implPointer->begin(); implit!= handle->implPointer->end();++implit) + { + if(*it == *implit) + { + newIt = implit; + break; + } + } + bool result = handle->implPointer->remove(newIt); + handle->vectorOfPoints = handle->implPointer->getVectorOfPoints(); + return result; +} diff --git a/src/Point2DImpl.cpp b/src/Point2DImpl.cpp index 29771b4..b85ca38 100644 --- a/src/Point2DImpl.cpp +++ b/src/Point2DImpl.cpp @@ -1,16 +1,455 @@ #include "Point2DImpl.h" +#include "RGPPoint2D.h" +#include "RGP.h" +#include "RGPSegment2D.h" +#include "RGPHalfSegment2D.h" +#include "Line2DImpl.h" +#include +#include +#include +#include +#include +#include +//creates vectors to store points and bounding +struct Point2DImpl::Point2DImplStore +{ + std::vector vectorOfPoints; + std::vector boundingBox; +}; + +//iterator to iterate through our data structure and return elements accordingly. +//constructor to the iterator, points iterator to a particular element of our data type. +Point2DImpl::iterator::iterator(RGPPoint2D *ptr1) +{ + ptr = ptr1; +} + +//overloading * operator to return the pointing element +RGPPoint2D Point2DImpl::iterator::operator*() +{ + return *ptr; +} + +//overloading ++ operator to move the iterator through our set of points +//this method is for postincrement +RGPPoint2D Point2DImpl::iterator::operator++(int junk) +{ + RGPPoint2D *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; +} + +//overloading ++ operator to move the iterator through our set of points +//this method is for preincrement +RGPPoint2D Point2DImpl::iterator::operator++() +{ + ptr++; + return *ptr; +} + +//checks if both the iterators are not equal. +bool Point2DImpl::iterator::operator!=(const iterator &it) +{ + if(it.ptr==ptr) + return false; + return true; +} + +//checks if both the iterators are equal. +bool Point2DImpl::iterator::operator==(const iterator &it) +{ + if(it.ptr!=ptr) + return false; + return true; +} + +//method for pointImpl, used mainly with iterators. returns iterator to the first point in the list of Points. +Point2DImpl::iterator Point2DImpl::begin() +{ + RGPPoint2D *ptr = &(handle->vectorOfPoints[0]); + return iterator(ptr); +} + +//method for pointImpl, used mainly with iterators. returns iterator to the last point in the list of Points. +Point2DImpl::iterator Point2DImpl::end() +{ + int t = handle->vectorOfPoints.size(); + return (iterator(&(handle->vectorOfPoints[t-1]))); +} + +//Constructors +//constructor to initialise point with a vector of RGPPoints. +Point2DImpl::Point2DImpl(std::vector listOfPoints) +{ + handle = new Point2DImplStore; + handle->vectorOfPoints = listOfPoints; +} + +//this constructor does not have any args. This just re initializes the handle. Point2DImpl::Point2DImpl() { + handle = new Point2DImplStore; +} + +//constructor to read points from a file +Point2DImpl::Point2DImpl(std::ifstream& file) +{ + std::string inputString; + if(file.is_open()) + { + std::stringstream strBuffer; + strBuffer << file.rdbuf(); + inputString = strBuffer.str(); + } + else + { + throw std::runtime_error("Error while reading the file"); + } + + if(parseStringToVectorOfPoints(inputString)) + std::cout << "success" << std::endl; + else{ + std::cout << "failed" << std::endl; + handle->vectorOfPoints.clear(); + } +} + + +//This constructor creates a Point2DImpl object based on a passed in string of points. We follow a specific convention here. +//((a,b),(c,d)) +Point2DImpl::Point2DImpl(std::string listOfPoint2DString) +{ + handle = new Point2DImplStore; + if(parseStringToVectorOfPoints(listOfPoint2DString)) + { + std::cout<<"All points are added successfully"<vectorOfPoints.clear(); + } } Point2DImpl::~Point2DImpl() { + delete handle; +} +//this method checks if the structure is empty +bool Point2DImpl::isEmptyPoint() +{ + return handle->vectorOfPoints.empty(); } -std::vector Point2DImpl::getSequence() +//method to print all points in the Point2D object +void Point2DImpl::printAllPoints() { + std::cout<<"("; + std::vector x = handle->vectorOfPoints; + for(auto i = x.begin(); i!=x.end(); i++) + std::cout<<*i; + std::cout<<")"; +} + +//this method return total number of points in the Point2D object. +int Point2DImpl::getNumberOfPoints() +{ + return handle->vectorOfPoints.size(); +} + +//returns bounding box for the object +RGPSegment2D Point2DImpl::getBoundingBox() +{ + std::vector points; + std::vector boundPoints; + //get all the points in the object + points = handle->vectorOfPoints; + + //get the least point to get the first point for diagonal + boundPoints.push_back(points[0]); -} \ No newline at end of file + //get the maxy for the secound point + auto maxy = points[0].y; + for(auto it = points.begin(); it!=points.end() ;it++) + { + if((*it).y > maxy) + maxy=(*it).y; + } + //make the secound point from the set of points + RGPPoint2D pt(points[points.size() - 1].x,maxy); + //push back the secound point + boundPoints.push_back(pt); + + //create the diagonal + RGPSegment2D seg(boundPoints[0],boundPoints[1]); + std::vector segs; + + segs.push_back(seg); + Line2DImpl ln(segs); + return seg; +} + +//method checks if the both Point2D objects are equal +bool Point2DImpl::operator==(const Point2DImpl &p2d) +{ + int i=0; + while(i< p2d.handle->vectorOfPoints.size()) + { + if(handle->vectorOfPoints[i] != p2d.handle->vectorOfPoints[i]) + return false; + else + i++; + } + if(handle->vectorOfPoints.size() == p2d.handle->vectorOfPoints.size()) + return true; + else + return false; +} + +//method checks if the both Point2D objects are not equal +bool Point2DImpl::operator!=(const Point2DImpl &p2d) +{ + int i=0; + if(handle->vectorOfPoints.size() != p2d.handle->vectorOfPoints.size()) + return true; + while(i< p2d.handle->vectorOfPoints.size()) + { + if(handle->vectorOfPoints[i] != p2d.handle->vectorOfPoints[i]) + return true; + else + i++; + } + return false; +} + +//returns the point at that particular index of the Point2D object +Point2DImpl Point2DImpl::operator[](int index) +{ + std::vector t; + t.push_back(handle->vectorOfPoints[index]); + Point2DImpl temp(t); + return temp; +} + +//assigns the object to the right to the object in the left. +Point2DImpl Point2DImpl::operator=(const Point2DImpl &p2d) +{ + handle->vectorOfPoints.clear(); + handle->vectorOfPoints = p2d.handle->vectorOfPoints; +} + +std::vector Point2DImpl::getVectorOfPoints() +{ + return handle->vectorOfPoints; +} + +//this method is used to add a new point to Point2D object +bool Point2DImpl::add(RGPPoint2D rgpp2d) +{ + try + { + //check if the vector is empty + if(handle->vectorOfPoints.empty()) + { + handle->vectorOfPoints.push_back(rgpp2d); + return true; + } + + int i=0; + while(rgpp2d > handle->vectorOfPoints[i] && i < handle->vectorOfPoints.size()) + i++; + if(i==handle->vectorOfPoints.size()) + handle->vectorOfPoints.push_back(rgpp2d); + else + handle->vectorOfPoints.insert(handle->vectorOfPoints.begin()+i, rgpp2d); + } + catch(int e) + { + return false; + } + return true; +} + +//this method is used to update a point at a particular index +bool Point2DImpl::update(Point2DImpl::iterator it, RGPPoint2D rgpp2d) +{ + try + { + if(isEmptyPoint()) + { + return false; + } + else + { + int index = it.ptr - &(handle->vectorOfPoints[0]); + handle->vectorOfPoints.erase(handle->vectorOfPoints.begin()+index); + add(rgpp2d); + pointSort(handle->vectorOfPoints); + } + } + catch(int e) + { + return false; + } + return true; +} + +//removes a particular point in the vector of points +bool Point2DImpl::remove(Point2DImpl::iterator it) +{ + try + { + if(isEmptyPoint()) + { + return false; + } + else + { + int index = it.ptr - &(handle->vectorOfPoints[0]); + handle->vectorOfPoints.erase(handle->vectorOfPoints.begin()+index); + } + } + catch(int e) + { + return false; + } + return true; +} + +//merge sort imlementation to sort all points +void Point2DImpl::pointSort(std::vector &bar) +{ + if (bar.size() <= 1) + return; + + int mid = bar.size() / 2; + std::vector l; + std::vector r; + + for (size_t j = 0; j < mid;j++) + l.push_back(bar[j]); + for (size_t j = 0; j < (bar.size()) - mid; j++) + r.push_back(bar[mid + j]); + + pointSort(l); + pointSort(r); + mergeSort(l, r, bar); +} + + +void Point2DImpl::mergeSort(std::vector &left, std::vector &right, std::vector &bars) +{ + int nL = left.size(); + int nR = right.size(); + int i = 0, j = 0, k = 0; + + while (j < nL && k < nR) + { + if (left[j] <= + right[k]) { + bars[i] = left[j]; + j++; + } + else { + bars[i] = right[k]; + k++; + } + i++; + } + while (j < nL) { + bars[i] = left[j]; + j++; i++; + } + while (k < nR) { + bars[i] = right[k]; + k++; i++; + } +} + +//parse method to parse all points from the string and make the vector of points +bool Point2DImpl::parseStringToVectorOfPoints(std::string st) +{ + std::vector points; + int pos,fl=0; + std::string num1,num2; + std::string s =st; + std::vector nums; + + //initialize the delimiter + std::string delimeter = ","; + + //erase first and last (..*) + s.erase(0,1); + s.erase(s.length()-1,1); + s.append(","); + + //keep finding the substrings + pos = s.find(delimeter); + try{ + while(pos!= std::string::npos) + { + std::string a = s.substr(0, pos); + if(a.length()>=2) + { + try + { + if(a[0]=='(') + { + //get the complete number and store it. + std::string temp = ""; + int i =1; + while(((a[i]<='9'&&a[i]>='0')||a[i]=='.'||a[i]=='-')&&i='0')||a[i]=='.'||a[i]=='-')&&ivectorOfPoints = points; +} diff --git a/src/RGPHalfSegment2D.cpp b/src/RGPHalfSegment2D.cpp index 0c0e09e..4525995 100644 --- a/src/RGPHalfSegment2D.cpp +++ b/src/RGPHalfSegment2D.cpp @@ -3,55 +3,69 @@ // RGPHalfSegment2D // Constructors -RGPHalfSegment2D::RGPHalfSegment2D(RGPSegment2D s, RGPPoint2D dp) : segment(s), dominantPoint(dp) {} +RGPHalfSegment2D::RGPHalfSegment2D(RGPSegment2D s, RGPPoint2D dp) + : segment(s), dominantPoint(dp) { + if (dp == s.point1) + isLeftFlag = true; + else + isLeftFlag = false; + if(s.point2.x - s.point2.x != Number("0")) { + m = (s.point2.y - s.point1.y) / (s.point2.x - s.point2.x); + } else { + m = s.point2.x - s.point2.x; + } +} RGPHalfSegment2D::~RGPHalfSegment2D() {} -bool RGPHalfSegment2D::operator==(const RGPHalfSegment2D &rhs) const -{ - +bool RGPHalfSegment2D::operator==(const RGPHalfSegment2D &rhs) { + if (segment == rhs.segment && dominantPoint == rhs.dominantPoint && + isLeftFlag == rhs.isLeftFlag) + return true; + else + return false; } - -bool RGPHalfSegment2D::operator!=(const RGPHalfSegment2D &rhs) const -{ - +bool RGPHalfSegment2D::operator!=(const RGPHalfSegment2D &rhs) { + return !((*this) == rhs); } - -bool RGPHalfSegment2D::operator<(const RGPHalfSegment2D &rhs) const -{ - +bool RGPHalfSegment2D::operator<(const RGPHalfSegment2D &rhs) { + if (dominantPoint < rhs.dominantPoint || + (dominantPoint == rhs.dominantPoint && isLeftFlag == false && + rhs.isLeftFlag == true) || + (dominantPoint == rhs.dominantPoint && isLeftFlag == rhs.isLeftFlag && + m < rhs.m) || + (dominantPoint == rhs.dominantPoint && isLeftFlag == rhs.isLeftFlag && + m == rhs.m && sqLen() < rhs.sqLen())) { + return true; + } else + return false; } - -bool RGPHalfSegment2D::operator<=(const RGPHalfSegment2D &rhs) const -{ - +bool RGPHalfSegment2D::operator<=(const RGPHalfSegment2D &rhs) { + return (*this) == rhs || (*this) < rhs; } - -bool RGPHalfSegment2D::operator>(const RGPHalfSegment2D &rhs) const -{ - +bool RGPHalfSegment2D::operator>(const RGPHalfSegment2D &rhs) { + return !((*this) <= rhs); } - -bool RGPHalfSegment2D::operator>=(const RGPHalfSegment2D &rhs) const -{ - +bool RGPHalfSegment2D::operator>=(const RGPHalfSegment2D &rhs) { + return !((*this) < rhs); } -bool RGPHalfSegment2D::operator>(const RGPPoint2D &rhs) const -{ - return true; -} +bool RGPHalfSegment2D::isLeft() { return isLeftFlag; } -bool RGPHalfSegment2D::operator<(const RGPPoint2D &rhs) const -{ - return true; +Number RGPHalfSegment2D::sqLen() const { + return (segment.point1.x - segment.point2.x) * + (segment.point1.x - segment.point2.x) + + (segment.point1.y - segment.point2.y) * + (segment.point1.y - segment.point2.y); } // RGPAnnotatedHalfSegment2D // Constructors RGPAnnotatedHalfSegment2D::RGPAnnotatedHalfSegment2D(RGPSegment2D s, - RGPPoint2D dp, bool regAbove) : RGPHalfSegment2D::RGPHalfSegment2D(s, dp) { - this->interiorIsAbove = regAbove; + RGPPoint2D dp, + bool regAbove) + : RGPHalfSegment2D::RGPHalfSegment2D(s, dp) { + this->insideIsAbove = regAbove; } RGPAnnotatedHalfSegment2D::~RGPAnnotatedHalfSegment2D() {} diff --git a/src/RGPOperations.cpp b/src/RGPOperations.cpp index 5716224..31e64ea 100644 --- a/src/RGPOperations.cpp +++ b/src/RGPOperations.cpp @@ -1,4 +1,45 @@ #include "../include/RGPOperations2D.h" +int RGPOperations2D::orientation(RGPPoint2D point1, RGPPoint2D point2, + RGPPoint2D point3) { + Number x = (point2.y - point1.y) * (point3.x - point2.x) - + (point3.y - point2.y) * (point2.x - point1.x); + Number zero("0"); + if (x == zero) + return COLLINEAR; + else if (x > zero) + return CLOCKWISE; + else + return COUNTERCLOCKWISE; +} + +RGPPoint2D RGPOperations2D::intersection(RGPSegment2D s1, RGPSegment2D s2) { + Number x1 = s1.point1.x, y1 = s1.point1.y, x2 = s1.point2.x, y2 = s1.point2.y, + x3 = s2.point1.x, y3 = s2.point1.y, x4 = s2.point2.x, y4 = s2.point2.y, + resX, resY, denom; + denom = (x2 - x1) * (y4 - y3) - (x4 - x3) * (y2 - y1); + resX = ((x2 * y1 - x1 * y2) * (x4 - x3) - (x4 * y3 - x3 * y4) * (x2 - x1)) / + denom; + resY = ((x2 * y1 - x1 * y2) * (y4 - y3) - (x4 * y3 - x3 * y4) * (y2 - y1)) / + denom; + RGPPoint2D intersectPoint(resX, resY); + return intersectPoint; +} + optional RGPOperations2D::intersectionOf(RGPSegment2D s1, - RGPSegment2D s2) {} + RGPSegment2D s2) { + int orientation1 = orientation(s1.point1, s1.point2, s2.point1); + int orientation2 = orientation(s1.point1, s1.point2, s2.point2); + int orientation3 = orientation(s2.point1, s2.point2, s1.point1); + int orientation4 = orientation(s2.point1, s2.point2, s1.point2); + + if ((orientation1 != orientation2 && orientation3 != orientation4) || + (orientation1 == COLLINEAR && s1.contains(s2.point1)) || + (orientation2 == COLLINEAR && s1.contains(s2.point2)) || + (orientation3 == COLLINEAR && s2.contains(s1.point1)) || + (orientation4 == COLLINEAR && s2.contains(s1.point2))) { + return {intersection(s1, s2)}; + } + + return std::nullopt; +} diff --git a/src/RGPPoint2D.cpp b/src/RGPPoint2D.cpp index 7a70aa9..2d94b6a 100644 --- a/src/RGPPoint2D.cpp +++ b/src/RGPPoint2D.cpp @@ -2,28 +2,42 @@ // Constructors -RGPPoint2D::RGPPoint2D(Number x, Number y) : y(x), x(y) {} +RGPPoint2D::RGPPoint2D(Number x, Number y) : x(x), y(y) {} RGPPoint2D::~RGPPoint2D() {} // Methods -bool RGPPoint2D::operator==(const RGPPoint2D &rhs) const {} -bool RGPPoint2D::operator!=(const RGPPoint2D &rhs) const {} -bool RGPPoint2D::operator<(const RGPPoint2D &rhs) const {} -bool RGPPoint2D::operator<=(const RGPPoint2D &rhs) const {} -bool RGPPoint2D::operator>(const RGPPoint2D &rhs) const {} -bool RGPPoint2D::operator>=(const RGPPoint2D &rhs) const {} +bool RGPPoint2D::operator==(const RGPPoint2D &rhs) { + if (x == rhs.x && y == rhs.y) + return true; + else + return false; +} +bool RGPPoint2D::operator!=(const RGPPoint2D &rhs) { return !((*this) == rhs); } +bool RGPPoint2D::operator<(const RGPPoint2D &rhs) { + if (x < rhs.x || (x == rhs.x && y < rhs.y)) + return true; + else + return false; +} +bool RGPPoint2D::operator<=(const RGPPoint2D &rhs) { + return (*this) < rhs || (*this) == rhs; +} +bool RGPPoint2D::operator>(const RGPPoint2D &rhs) { return !((*this) <= rhs); } +bool RGPPoint2D::operator>=(const RGPPoint2D &rhs) { return !((*this) < rhs); } -// bool RGPPoint2D::operator<(const RGPHalfSegment2D &rhs) const { -// return true; -// } -// bool RGPPoint2D::operator>(const RGPHalfSegment2D &rhs) const { -// return true; -// } +std::ostream &operator<<(std::ostream &os, const RGPPoint2D p) { + os << "(" << p.x << "," << p.y << ")"; + return os; +} -// bool RGPPoint2D::operator<(const RGPAnnotatedHalfSegment2D &rhs) const { -// return true; -// } -// bool RGPPoint2D::operator>(const RGPAnnotatedHalfSegment2D &rhs) const { -// return true; -// } +std::istream &operator>>(std::istream &is, RGPPoint2D p) { + // TODO: Check for invalid conditions + char c; + is >> c; + is >> p.x; + is >> c; + is >> p.y; + is >> c; + return is; +} \ No newline at end of file diff --git a/src/RGPSegment2D.cpp b/src/RGPSegment2D.cpp index abd38c4..7eb16ee 100644 --- a/src/RGPSegment2D.cpp +++ b/src/RGPSegment2D.cpp @@ -2,21 +2,59 @@ // Constructors -RGPSegment2D::RGPSegment2D(RGPPoint2D p1, RGPPoint2D p2) : point1(p1), point2(p2) {} +RGPSegment2D::RGPSegment2D(RGPPoint2D p1, RGPPoint2D p2) + : point1(p1 < p2 ? p1 : p2), point2(p1 < p2 ? p2 : p1) {} RGPSegment2D::~RGPSegment2D() {} // Methods -bool RGPSegment2D::operator==(const RGPSegment2D &rhs) const {} -bool RGPSegment2D::operator!=(const RGPSegment2D &rhs) const {} -bool RGPSegment2D::operator<(const RGPSegment2D &rhs) const {} -bool RGPSegment2D::operator<=(const RGPSegment2D &rhs) const {} -bool RGPSegment2D::operator>(const RGPSegment2D &rhs) const {} -bool RGPSegment2D::operator>=(const RGPSegment2D &rhs) const {} +bool RGPSegment2D::operator==(const RGPSegment2D &rhs) { + if (point1 == rhs.point1 && point2 == rhs.point2) + return true; + else + return false; +} +bool RGPSegment2D::operator!=(const RGPSegment2D &rhs) { + if (point1 == rhs.point1 && point2 == rhs.point2) + return false; + else + return true; +} +bool RGPSegment2D::operator<(const RGPSegment2D &rhs) { + if (point1 < rhs.point1 && point2 < rhs.point1) + return true; + return false; +} +bool RGPSegment2D::operator<=(const RGPSegment2D &rhs) { + if ((*this) < rhs || (*this) == rhs) + return true; + return false; +} +bool RGPSegment2D::operator>(const RGPSegment2D &rhs) { + return !((*this) <= rhs); +} +bool RGPSegment2D::operator>=(const RGPSegment2D &rhs) { + return !((*this) < rhs); +} + +bool RGPSegment2D::contains(const RGPPoint2D p) { + if (p.x <= std::max(point1.x, point2.x) && + p.x >= std::min(point1.x, point2.x) && + p.y <= std::max(point1.y, point2.y) && + p.y >= std::min(point1.y, point2.y)) { + return true; + } + return false; +} -bool RGPSegment2D::operator<(const RGPPoint2D &rhs) const { - return true; +std::ostream &operator<<(std::ostream &os, const RGPSegment2D p) { + os << p.point1 << "," << p.point2; + return os; } -bool RGPSegment2D::operator>(const RGPPoint2D &rhs) const { - return true; + +std::istream &operator>>(std::istream &is, const RGPSegment2D p) { + // TODO: Check for invalid conditions + char c; + is >> p.point1 >> c >> p.point2; + return is; } diff --git a/src/Region2D.cpp b/src/Region2D.cpp index 2eb2e50..e0b7187 100644 --- a/src/Region2D.cpp +++ b/src/Region2D.cpp @@ -1,95 +1,95 @@ -#include "Region2D.h" - -class Region2D::Region2DImpl {}; - -Region2D::Region2D() -{ - // Emtpy -} - -Region2D::Region2D(std::vector> listOfRegions) -{ - // Emtpy -} - -Region2D::Region2D(std::string listOfRegion2DString) -{ - // Emtpy -} - -Region2D::Region2D(std::ifstream& file) -{ - // Emtpy -} - -Region2D::~Region2D() -{ - // Emtpy -} - -std::string Region2D::getRegionString() // Get the region as human readable ASCII string -{ - // Emtpy -} - -Number Region2D::area() -{ - // Emtpy -} - -// static -bool Region2D::isEmptyRegion(Region2D region) -{ - // Emtpy -} - -int Region2D::getNumberOfFaces() -{ - // Emtpy -} - -std::vector Region2D::getBoundingBox() -{ - // Emtpy -} - -bool Region2D::addFace(std::vector) -{ - // Emtpy -} - -bool Region2D::update(int index, std::vector) -{ - // Emtpy -} - -bool Region2D::remove(int index) -{ - // Emtpy -} - -bool Region2D::operator==(const Region2D &p2d) -{ - // Emtpy -} - -bool Region2D::operator!=(const Region2D &p2d) -{ - // Emtpy -} - -std::vector Region2D::operator[](int index) -{ - // Empty -} - -template std::vector getCycle(T it) -{ - // Emtpy -} - -template std::vector getFace(T it) -{ - // Emtpy -} - +#include "Region2D.h" + +class Region2D::Region2DImpl {}; + +Region2D::Region2D() +{ + // Emtpy +} + +Region2D::Region2D(std::vector> listOfRegions) +{ + // Emtpy +} + +Region2D::Region2D(std::string listOfRegion2DString) +{ + // Emtpy +} + +Region2D::Region2D(std::ifstream& file) +{ + // Emtpy +} + +Region2D::~Region2D() +{ + // Emtpy +} + +std::string Region2D::getRegionString() // Get the region as human readable ASCII string +{ + // Emtpy +} + +Number Region2D::area() +{ + // Emtpy +} + +// static +bool Region2D::isEmptyRegion(Region2D region) +{ + // Emtpy +} + +int Region2D::getNumberOfFaces() +{ + // Emtpy +} + +std::vector Region2D::getBoundingBox() +{ + // Emtpy +} + +bool Region2D::addFace(std::vector) +{ + // Emtpy +} + +bool Region2D::update(int index, std::vector) +{ + // Emtpy +} + +bool Region2D::remove(int index) +{ + // Emtpy +} + +bool Region2D::operator==(const Region2D &p2d) +{ + // Emtpy +} + +bool Region2D::operator!=(const Region2D &p2d) +{ + // Emtpy +} + +std::vector Region2D::operator[](int index) +{ + // Empty +} + +template std::vector getCycle(T it) +{ + // Emtpy +} + +template std::vector getFace(T it) +{ + // Emtpy +} + diff --git a/src/Region2DImpl.cpp b/src/Region2DImpl.cpp index 8a434d5..e6bdf8d 100644 --- a/src/Region2DImpl.cpp +++ b/src/Region2DImpl.cpp @@ -1,16 +1,649 @@ -#include "Region2DImpl.h" +#include "Region2DImpl.h" +#include + +struct Region2DImpl::Region2DImplStore +{ + std::vector vectorOfAnnHalfSegments; + std::vector> vectorOfFaces; + std::vector> vectorOfHoles; + std::map faceToHoleRelationMap; + std::vector boundingBox; + Number areaOfRegion; +}; + +//Constructors +Region2DImpl::Region2DImpl(std::string listOfRegion2DString) +{ + handle = new Region2DImplStore; + bool result = parseWDR(listOfRegion2DString); + if(result == true) + { + bool isValid = validateRegion(); + if(isValid == false) + { + throw std::invalid_argument("Invalid Constructed Region"); + } + sortAnnotatedHS(handle->vectorOfAnnHalfSegments); + } + else + { + throw std::invalid_argument("Invalid Constructed Region"); + } +} + +// Sorts all the annotated half segments using mergeSort technique +void Region2DImpl::sortAnnotatedHS(std::vector vec) +{ + if(vec.size() < 1) + { + int mid = vec.size() / 2; + // Partition through midway for merge sort + std::vector l; + std::vector r; -Region2DImpl::Region2DImpl() -{ + for (size_t j = 0; j < mid; j++) + l.push_back(vec[j]); + for (size_t j = 0; j < (vec.size()) - mid; j++) + r.push_back(vec[mid + j]); -} + sortAnnotatedHS(l); + sortAnnotatedHS(r); + mergeSort(l, r, vec); + } +} + +// merge sort internal function used for sorting the annotated half segments +void Region2DImpl::mergeSort(std::vector &left, std::vector &right, std::vector &bars) +{ + int nL = left.size(); + int nR = right.size(); + int i = 0, j = 0, k = 0; -Region2DImpl::~Region2DImpl() + while (j < nL && k < nR) + { + if (left[j] <= + right[k]) { + bars[i] = left[j]; + j++; + } + else { + bars[i] = right[k]; + k++; + } + i++; + } + while (j < nL) { + bars[i] = left[j]; + j++; i++; + } + while (k < nR) { + bars[i] = right[k]; + k++; i++; + } +} + +// Computes the area of a region input +// This has been used to compute areas of individual cycles of a region +Number Region2DImpl::computeArea() +{ + // compute area of all the faces + Number tfaceArea("0"); + for(int i=0; ivectorOfFaces.size(); i++) + { + Number area = getAreaOfCycle(handle->vectorOfFaces[i]); + if(area <= Number("0")) + { + return Number("0"); + } + tfaceArea = tfaceArea + area; + } + // compute area of all the holes + Number tholeArea("0"); + for(int i=0; ivectorOfHoles.size(); i++) + { + Number area = getAreaOfCycle(handle->vectorOfHoles[i]); + if(area <= Number("0")) + { + return Number("0"); + } + tholeArea = tholeArea + area; + } + handle->areaOfRegion = tfaceArea - tholeArea; + return handle->areaOfRegion; +} + +// Validates a region input according to the face and cycle information +bool Region2DImpl::validateRegion() +{ + // check areas if adding upto positive Number + std::vector faceAreas; + std::vector holeAreas; + + Number tfaceArea("0"); + for(int i=0; ivectorOfFaces.size(); i++) + { + Number area = getAreaOfCycle(handle->vectorOfFaces[i]); + if(area <= Number("0")) + { + return false; + } + faceAreas.push_back(area); + tfaceArea = tfaceArea + area; + } + Number tholeArea("0"); + for(int i=0; ivectorOfHoles.size(); i++) + { + Number area = getAreaOfCycle(handle->vectorOfHoles[i]); + if(area <= Number("0")) + { + return false; + } + holeAreas.push_back(area); + tholeArea = tholeArea + area; + } + + // The total area of faces when subtracted by that of holes has to be a positive number + handle->areaOfRegion = tfaceArea - tholeArea; + if(handle->areaOfRegion <= Number("0")) + { + return false; + } + + // Check if all holes are contained in their respective faces + std::map::iterator itr; + int faceIndex = 0; + int holeIndex = 0; + for (itr = handle->faceToHoleRelationMap.begin(); itr != handle->faceToHoleRelationMap.end(); ++itr) { + Number fArea = faceAreas[faceIndex]; + Number hArea("0"); + for(int i=holeIndex; isecond; i++) + { + hArea = hArea + holeAreas[i]; + } + + // Check if the face area is more than that of all the holes inside it + if(fArea - hArea <= Number("0")) + { + return false; + } + + faceIndex++; + holeIndex = holeIndex + itr->second; + } + + std::vector allCyclesVec; + //Check if any 2 cycles are intersecting + for(int i=0; ivectorOfFaces.size(); i++) + { + for(int j=0; jvectorOfFaces[i].size(); j++) + { + allCyclesVec.push_back(handle->vectorOfFaces[i][j]); + } + } + for(int i=0; ivectorOfHoles.size(); i++) + { + for(int j=0; jvectorOfHoles[i].size(); j++) + { + allCyclesVec.push_back(handle->vectorOfHoles[i][j]); + } + } + handle->vectorOfAnnHalfSegments = allCyclesVec; + + // Check for intersection between any two segments of the region including all the faces and cycles + for(int i=0; i zero && d2 < zero) || (d1 < zero && d2 > zero)) && + ((d3 > zero && d4 < zero) || (d3 < zero && d4 > zero))) + { + return true; + } + else + { + return false; + } +} + +Number Region2DImpl::computeDirection(RGPPoint2D pi, RGPPoint2D pj, RGPPoint2D pk) +{ + Number g = (pk.x - pi.x)*(pj.y - pi.y) - (pj.x - pi.x)*(pk.y - pi.y); + return g; +} + +// Used for computing the area of a cycle given all the points +Number Region2DImpl::getAreaOfCycle(std::vector vectorOfSegments) +{ + Number area("0"); + Number xCoord[vectorOfSegments.size()/2]; + Number yCoord[vectorOfSegments.size()/2]; + int j =0; + for(int i=0; i faceToHoleMap; + if(inputString.length() < 2) + { + return false; + } + + std::string firstChar = inputString.substr(0,1); + std::string lastChar = inputString.substr(inputString.length()-1, inputString.length()); + if(firstChar != "[" || lastChar != "]") + { + return false; + } + + std::string notation = inputString.substr(1,3); + if(notation != "WCR") + { + return false; + } + + // formattedString = ((1 1,2 2),(1 1,2 2))& + std::string formattedString = inputString.substr(4); + formattedString.erase(formattedString.length()-1,1); + + std::string delimiter = "&"; + + int numOfFaces = 1; + int numOfHoles = 0; + + while(formattedString.length() > 0) + { + // ((1 1,2 2),(1 1,3 3)) = faceHoleSetString + int pos = formattedString.find(delimiter); + std::string faceHoleSetString = formattedString; + if(pos != -1) + { + faceHoleSetString = formattedString.substr(0,pos); + } + + // (1 1,2 2),(1 1,3 3) = partString + std::string partString = faceHoleSetString.substr(0,pos); + partString.erase(0,1); + partString.erase(partString.length()-1,1); + + // 1 1,2 2 = faceSegmentString + std::vector facePoints; + int faceClosingPoint = partString.find(")"); + std::string faceSegmentString = partString.substr(1,faceClosingPoint-1); + int faceSegmentStringLength = faceSegmentString.length(); + while(faceSegmentString.length() > 0) + { + int l = faceSegmentString.find(" "); + std::string coord1 = faceSegmentString.substr(0,l); + faceSegmentString.erase(0,l+1); + int r = faceSegmentString.find(","); + std::string coord2 = faceSegmentString.substr(0,r); + if(r == -1) + { + faceSegmentString.erase(0,faceSegmentString.length()); + } + else + { + faceSegmentString.erase(0,r+1); + } + facePoints.push_back(RGPPoint2D(Number(coord1), Number(coord2))); + } + // If start and end point of a cycle are not same, return false + if(facePoints[0] != facePoints[facePoints.size()-1]) + { + return false; + } + + std::vector emptyFaceVec; + handle->vectorOfFaces.push_back(emptyFaceVec); + + // Fill the currently parsed vector into the face vector of region + for(int i=0; ivectorOfFaces[numOfFaces-1].push_back(annHS); + handle->vectorOfFaces[numOfFaces-1].push_back(annHS2); + } + + std::vector> holePointVector; + std::string holesString = partString.substr(faceSegmentStringLength+3, partString.length()); + + while(holesString.find(")") != std::string::npos) + { + int holeClosingPoint = holesString.find(")"); + std::string holeSegmentString = holesString.substr(1,holeClosingPoint-1); + int holeSegmentStringLength = holeSegmentString.length(); + std::vector emptyVec; + std::vector emptyHoleVec; + holePointVector.push_back(emptyVec); + handle->vectorOfHoles.push_back(emptyHoleVec); + while(holeSegmentString.length() > 0) + { + int l = holeSegmentString.find(" "); + std::string coord1 = holeSegmentString.substr(0,l); + holeSegmentString.erase(0,l+1); + int r = holeSegmentString.find(","); + std::string coord2 = holeSegmentString.substr(0,r); + if(r == -1) + { + holeSegmentString.erase(0,holeSegmentString.length()); + } + else + { + holeSegmentString.erase(0,r+1); + } + + holePointVector[numOfHoles].push_back(RGPPoint2D(Number(coord1), Number(coord2))); + } + + std::vector hole = holePointVector[numOfHoles]; + // Check if the first and last point for a hole cycle is the same + if(hole[0] != hole[hole.size()-1]) + { + return false; + } + + // Add the parsed hole cycle into the vector of holes of the region + for(int i=0; ivectorOfHoles[numOfHoles].push_back(annHS); + handle->vectorOfHoles[numOfHoles].push_back(annHS2); + } + + holesString = holesString.substr(holeSegmentStringLength+2, holesString.length()); + if(holesString.length() != 0 && holesString.substr(0,1) == ",") + { + holesString.erase(0,1); + } + // Keep track of number of holes being added + numOfHoles++; + } + + // Maintain the relation of face to corresponding hole + faceToHoleMap.insert(std::pair(numOfFaces,numOfHoles)); + numOfFaces++; + + int faceHoleSetStringLength = faceHoleSetString.length(); + if(pos != -1) + { + faceHoleSetStringLength++; + } + formattedString = formattedString.substr(faceHoleSetStringLength,formattedString.length()); + } + + std::map::iterator itr; + handle->faceToHoleRelationMap = faceToHoleMap; + return true; +} + +Region2DImpl::~Region2DImpl() +{ + delete handle; +} + +Number Region2DImpl::area() +{ + return handle->areaOfRegion; +} + +bool Region2DImpl::isEmptyRegion() +{ + return handle->vectorOfFaces.empty(); +} + +int Region2DImpl::getNumberOfFaces() +{ + return handle->vectorOfFaces.size(); +} + +int Region2DImpl::getNumberOfHoles() +{ + return handle->vectorOfHoles.size(); +} + +RGPSegment2D Region2DImpl::getBoundingBox() { + std::vector halfSegments; + halfSegments = handle->vectorOfAnnHalfSegments; -} + //p1 is the first point of the bounding box segment + RGPPoint2D p1(halfSegments[0].segment.point1.x,halfSegments[0].segment.point1.y); + RGPPoint2D p2(halfSegments[halfSegments.size()-1].segment.point2.x,halfSegments[halfSegments.size()-1].segment.point2.y); + auto maxy = halfSegments[0].segment.point2.y; -std::vector Region2DImpl::getSequence() -{ + //iterate through the loop to find max y coordinate in the given lis of points + for(auto it = halfSegments.begin();it!= halfSegments.end();it++) + { + if(maxy<(*it).segment.point1.y) + maxy = (*it).segment.point1.y; + if(maxy<(*it).segment.point2.y) + maxy = (*it).segment.point2.y; + } + //we make the next point taking the x of p2 and maxy found in the above loop + RGPSegment2D seg(p1,RGPPoint2D(p2.x,maxy)); + handle->boundingBox.push_back(seg); + //returing the diagonal that tells us the bounding box + return handle->boundingBox[0]; +} + +bool Region2DImpl::addFace(std::vector faceVec) +{ + std::vector vecToAdd; + // Iterate and create annotated half segments + for(int i=0; ivectorOfAnnHalfSegments.push_back(a); + handle->vectorOfAnnHalfSegments.push_back(b); + } + handle->vectorOfFaces.push_back(vecToAdd); + handle->faceToHoleRelationMap.insert(std::pair(handle->vectorOfFaces.size()+1,0)); + + // Might throw exception as and when the validation fails + validateRegion(); + // Sort the newly added half segments as well + sortAnnotatedHS(handle->vectorOfAnnHalfSegments); +} + +bool Region2DImpl::operator==(const Region2DImpl &p2d) +{ + int i = 0; + //Check if size equal + if(handle->vectorOfAnnHalfSegments.size() != p2d.handle->vectorOfAnnHalfSegments.size()) + { + return false; + } + + // Check iteratively if each segment is equal to other + while(i < p2d.handle->vectorOfAnnHalfSegments.size()) + { + if(handle->vectorOfAnnHalfSegments[i] != p2d.handle->vectorOfAnnHalfSegments[i]) + { + return false; + } + else + i++; + } + return true; +} + +bool Region2DImpl::operator!=(const Region2DImpl &p2d) +{ + int i = 0; + //Check if size equal + if(handle->vectorOfAnnHalfSegments.size() != p2d.handle->vectorOfAnnHalfSegments.size()) + { + return true; + } + + // Check iteratively if each segment is equal to other + while(i < p2d.handle->vectorOfAnnHalfSegments.size()) + { + if(handle->vectorOfAnnHalfSegments[i] != p2d.handle->vectorOfAnnHalfSegments[i]) + { + return true; + } + else + i++; + } + return false; +} + +// Iterators for faces and hole cycles +Region2DImpl::iteratorforFaces::iteratorforFaces(std::vector *ptr1) +{ + ptr = ptr1; +} + +std::vector Region2DImpl::iteratorforFaces::operator*() +{ + return *ptr; +} + +std::vector Region2DImpl::iteratorforFaces::operator++(int junk) +{ + std::vector *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; +} + +std::vector Region2DImpl::iteratorforFaces::operator++() +{ + ptr++; + return *ptr; +} + +bool Region2DImpl::iteratorforFaces::operator!=(const iteratorforFaces &it) +{ + if(it.ptr==ptr) + return false; + return true; +} + +bool Region2DImpl::iteratorforFaces::operator==(const iteratorforFaces &it) +{ + if(it.ptr!=ptr) + return false; + return true; +} + +Region2DImpl::iteratorforFaces Region2DImpl::beginFaces() +{ + std::vector *ptr = &(handle->vectorOfFaces[0]); + return iteratorforFaces(ptr); +} + +Region2DImpl::iteratorforFaces Region2DImpl::endFaces() +{ + int t = handle->vectorOfFaces.size(); + return (iteratorforFaces(&(handle->vectorOfFaces[t-1]))); +} + +Region2DImpl::iteratorforHoles::iteratorforHoles(std::vector *ptr1) +{ + ptr = ptr1; +} + +std::vector Region2DImpl::iteratorforHoles::operator*() +{ + return *ptr; +} + +std::vector Region2DImpl::iteratorforHoles::operator++(int junk) +{ + std::vector *ptr1; + ptr1 = ptr; + ptr++; + return *ptr1; +} + +std::vector Region2DImpl::iteratorforHoles::operator++() +{ + ptr++; + return *ptr; +} + +bool Region2DImpl::iteratorforHoles::operator!=(const iteratorforHoles &it) +{ + if(it.ptr==ptr) + return false; + return true; +} + +bool Region2DImpl::iteratorforHoles::operator==(const iteratorforHoles &it) +{ + if(it.ptr!=ptr) + return false; + return true; +} + +Region2DImpl::iteratorforHoles Region2DImpl::beginHoles() +{ + std::vector *ptr = &(handle->vectorOfHoles[0]); + return iteratorforHoles(ptr); +} + +Region2DImpl::iteratorforHoles Region2DImpl::endHoles() +{ + int t = handle->vectorOfHoles.size(); + return (iteratorforHoles(&(handle->vectorOfHoles[t-1]))); } \ No newline at end of file diff --git a/src/Relationship2D.cpp b/src/Relationship2D.cpp deleted file mode 100644 index df59083..0000000 --- a/src/Relationship2D.cpp +++ /dev/null @@ -1,678 +0,0 @@ -#include "PredicateEnum.h" -#include "Relationship2D.h" -#include "PlaneSweep.h" -#include "Explore.h" -#include "Evaluate.h" - -#include - -// ============================================================================= -// --------------------------- Determination ----------------------------------- -// ============================================================================= - -Predicate Relationship2D::determine(Point2D &leftOperand, Point2D &rightOperand) -{ - // Explore - explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::determine(leftOperand, rightOperand, leftFeature, rightFeature); -} - -Predicate Relationship2D::determine(Point2D &leftOperand, Line2D &rightOperand) -{ - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::determine(leftOperand, rightOperand, leftFeature, rightFeature); -} - -Predicate Relationship2D::determine(Point2D &leftOperand, Region2D &rightOperand) -{ - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::determine(leftOperand, rightOperand, leftFeature, rightFeature); -} - -Predicate Relationship2D::determine(Line2D &leftOperand, Line2D &rightOperand) -{ - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::determine(leftOperand, rightOperand, leftFeature, rightFeature); -} - -Predicate Relationship2D::determine(Line2D &leftOperand, Region2D &rightOperand) -{ - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::determine(leftOperand, rightOperand, leftFeature, rightFeature); -} - -Predicate Relationship2D::determine(Region2D &leftOperand, Region2D &rightOperand) -{ - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::determine(leftOperand, rightOperand, leftFeature, rightFeature); -} - -// ============================================================================= -// --------------------------- Verification ------------------------------------ -// ============================================================================= - -// Disjoint -bool Relationship2D::disjoint(Point2D &leftOperand, Point2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_shared, poi_disjoint}; - - std::vector leftFeature(2, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::disjoint); - - // return !leftFeature[poi_shared] && leftFeature[poi_disjoint]; -} - -bool Relationship2D::disjoint(Point2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_disjoint, poi_on_interior, poi_on_bound, bound_poi_disjoint}; - - std::vector leftFeature(3, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::disjoint); - - // return !leftFeature[poi_on_interior] && !leftFeature[poi_on_bound]; -} - -bool Relationship2D::disjoint(Point2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_inside, poi_on_bound, poi_outside}; - - std::vector leftFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::disjoint); - - // return !leftFeature[poi_inside] && !leftFeature[poi_on_bound]; -} - -bool Relationship2D::disjoint(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::disjoint); - - // return !(leftFeature[seg_shared] || leftFeature[interior_poi_shared]) && - // !rightFeature[bound_on_interior] && - // leftFeature[seg_unshared] && - // !leftFeature[bound_on_interior] && - // !leftFeature[bound_shared]; -} - -bool Relationship2D::disjoint(Line2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, seg_inside, seg_shared, seg_outside, poi_shared, bound_inside, bound_shared, bound_disjoint}; - - std::vector leftFeature(7, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::disjoint); - - // return !leftFeature[seg_inside] && - // !(leftFeature[seg_shared] || leftFeature[poi_shared]) && - // leftFeature[seg_outside] && - // !leftFeature[bound_inside] && - // !leftFeature[bound_shared]; -} - -bool Relationship2D::disjoint(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::disjoint); - - // return !(leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_two] || leftFeature[two_one] || rightFeature[one_two] || rightFeature[two_one]) && - // !(rightFeature[one_two] || rightFeature[two_one]) && - // !(leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_one] || leftFeature[bound_poi_shared]) && - // (leftFeature[zero_one] || leftFeature[one_zero]) && - // (rightFeature[zero_one] || rightFeature[one_zero]); -} - -// Meet -bool Relationship2D::meet(Point2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_disjoint, poi_on_interior, poi_on_bound, bound_poi_disjoint}; - - std::vector leftFeature(3, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::meet); - - // return !leftFeature[poi_on_interior] && leftFeature[poi_on_bound]; -} - -bool Relationship2D::meet(Point2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_inside, poi_on_bound, poi_outside}; - - std::vector leftFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::meet); - - // return !leftFeature[poi_inside] && leftFeature[poi_on_bound]; -} - -bool Relationship2D::meet(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::meet); - - // return !(leftFeature[seg_shared] || leftFeature[interior_poi_shared]) && leftFeature[seg_unshared]; -} - -bool Relationship2D::meet(Line2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, seg_inside, seg_shared, seg_outside, poi_shared, bound_inside, bound_shared, bound_disjoint}; - - std::vector leftFeature(7, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::meet); - - // return !leftFeature[seg_inside] && - // !leftFeature[seg_outside] && - // !leftFeature[bound_inside]; -} - -bool Relationship2D::meet(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::meet); - - // return !(leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_two] || leftFeature[two_one] || rightFeature[one_two] || rightFeature[two_one]) && - // !(rightFeature[one_two] || rightFeature[two_one]) && - // (leftFeature[zero_one] || leftFeature[one_zero] || leftFeature[one_one] || rightFeature[one_two] || rightFeature[two_one]) && - // !(leftFeature[one_two] || leftFeature[two_one]) && - // (leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_one] || leftFeature[bound_poi_shared]); -} - -// Overlap -bool Relationship2D::overlap(Point2D &leftOperand, Point2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_shared, poi_disjoint}; - - std::vector leftFeature(2, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::overlap); - - // return leftFeature[poi_shared] && leftFeature[poi_disjoint] && rightFeature[poi_disjoint]; -} - -bool Relationship2D::overlap(Point2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_disjoint, poi_on_interior, poi_on_bound, bound_poi_disjoint}; - - std::vector leftFeature(3, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::overlap); - - // return leftFeature[poi_on_interior] && leftFeature[poi_disjoint]; -} - -bool Relationship2D::overlap(Point2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_inside, poi_on_bound, poi_outside}; - - std::vector leftFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::overlap); - - // return leftFeature[poi_inside] && leftFeature[poi_outside]; -} - -bool Relationship2D::overlap(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::overlap); - - // return (leftFeature[seg_shared] || leftFeature[interior_poi_shared]) && rightFeature[seg_unshared]; -} - -bool Relationship2D::overlap(Line2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, seg_inside, seg_shared, seg_outside, poi_shared, bound_inside, bound_shared, bound_disjoint}; - - std::vector leftFeature(7, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::overlap); - - // return leftFeature[seg_inside] && - // leftFeature[seg_outside]; -} - -bool Relationship2D::overlap(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::overlap); - - // return (leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_two] || leftFeature[two_one] || rightFeature[one_two] || rightFeature[two_one]) && - // (leftFeature[zero_one] || leftFeature[one_zero] || leftFeature[one_one] || rightFeature[one_two] || rightFeature[two_one]) && - // (leftFeature[one_two] || leftFeature[two_one] || leftFeature[one_one] || rightFeature[zero_one] || rightFeature[one_zero]); -} - -// Equal -bool Relationship2D::equal(Point2D &leftOperand, Point2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_shared, poi_disjoint}; - - std::vector leftFeature(2, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::equal); - - // return !leftFeature[poi_disjoint] && !rightFeature[poi_disjoint]; -} - -bool Relationship2D::equal(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::equal); - - // return !rightFeature[bound_on_interior] && - // !leftFeature[seg_unshared] && - // !leftFeature[bound_on_interior] && - // !leftFeature[bound_disjoint] && - // !rightFeature[seg_unshared]; -} - -bool Relationship2D::equal(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::equal); - - // return !(rightFeature[one_two] || rightFeature[two_one]) && - // !(leftFeature[zero_one] || leftFeature[one_zero] || leftFeature[one_one] || rightFeature[one_two] || rightFeature[two_one]) && - // !(leftFeature[one_two] || leftFeature[two_one]) && - // !(leftFeature[zero_one] || leftFeature[one_zero]) && - // !(leftFeature[one_two] || leftFeature[two_one] || leftFeature[one_one] || rightFeature[zero_one] || rightFeature[one_zero]); -} - -// Inside -bool Relationship2D::inside(Point2D &leftOperand, Point2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_shared, poi_disjoint}; - - std::vector leftFeature(2, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::inside); - - // return !leftFeature[poi_disjoint] && rightFeature[poi_disjoint]; -} - -bool Relationship2D::inside(Point2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_disjoint, poi_on_interior, poi_on_bound, bound_poi_disjoint}; - - std::vector leftFeature(3, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::inside); - - // return leftFeature[poi_on_interior] && !leftFeature[poi_disjoint]; -} - -bool Relationship2D::inside(Point2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_inside, poi_on_bound, poi_outside}; - - std::vector leftFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::inside); - - // return leftFeature[poi_inside] && !leftFeature[poi_outside]; -} - -bool Relationship2D::inside(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::inside); - - // return (leftFeature[seg_shared] || leftFeature[interior_poi_shared]) && - // !rightFeature[bound_on_interior] && - // !leftFeature[seg_unshared] && - // !leftFeature[bound_shared] && - // !leftFeature[bound_disjoint] && - // rightFeature[seg_unshared]; -} - -bool Relationship2D::inside(Line2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, seg_inside, seg_shared, seg_outside, poi_shared, bound_inside, bound_shared, bound_disjoint}; - - std::vector leftFeature(7, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::inside); - - // return leftFeature[seg_inside] && - // !leftFeature[seg_outside] && - // !leftFeature[bound_shared]; -} - -bool Relationship2D::inside(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::inside); - - // return !(rightFeature[one_two] || rightFeature[two_one]) && - // !(leftFeature[zero_one] || leftFeature[one_zero] || leftFeature[one_one] || rightFeature[one_two] || rightFeature[two_one]) && - // (leftFeature[one_two] || leftFeature[two_one]) && - // !(leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_one] || leftFeature[bound_poi_shared]) && - // !(leftFeature[zero_one] || leftFeature[one_zero]); -} - -// Contains -bool Relationship2D::contains(Point2D &leftOperand, Point2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {poi_shared, poi_disjoint}; - - std::vector leftFeature(2, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::contains); - - // return leftFeature[poi_shared] && leftFeature[poi_disjoint] && !rightFeature[poi_disjoint]; -} - -bool Relationship2D::contains(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::contains); - - // return (leftFeature[seg_shared] || leftFeature[interior_poi_shared]) && - // leftFeature[seg_unshared] && - // !leftFeature[bound_on_interior] && - // !leftFeature[bound_shared] && - // !rightFeature[seg_unshared]; -} - -bool Relationship2D::contains(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::contains); - - // return (rightFeature[one_two] || rightFeature[two_one]) && - // !(leftFeature[one_two] || leftFeature[two_one]) && - // !(leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_one] || leftFeature[bound_poi_shared]) && - // (leftFeature[zero_one] || leftFeature[one_zero]) && - // !(leftFeature[one_two] || leftFeature[two_one] || leftFeature[one_one] || rightFeature[zero_one] || rightFeature[one_zero]); -} - -// Covers -bool Relationship2D::covers(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::covers); - - // return (leftFeature[seg_shared] || leftFeature[interior_poi_shared]) && - // leftFeature[seg_unshared] && - // !leftFeature[bound_on_interior] && - // leftFeature[bound_shared] && - // !rightFeature[seg_unshared]; -} - -bool Relationship2D::covers(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::covers); - - // return (leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_two] || leftFeature[two_one] || rightFeature[one_two] || rightFeature[two_one]) && - // !(leftFeature[one_two] || leftFeature[two_one]) && - // (leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_one] || leftFeature[bound_poi_shared]) && - // !(leftFeature[one_two] || leftFeature[two_one] || leftFeature[one_one] || rightFeature[zero_one] || rightFeature[one_zero]) && - // !(rightFeature[zero_one] || rightFeature[one_zero]); -} - -// CoveredBy -bool Relationship2D::coveredBy(Line2D &leftOperand, Line2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, bound_on_interior, bound_disjoint, seg_shared, interior_poi_shared, bound_shared}; - - std::vector leftFeature(6, false); - std::vector rightFeature(3, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::coveredBy); - - // return (leftFeature[seg_shared] || leftFeature[interior_poi_shared]) && - // !rightFeature[bound_on_interior] && - // !leftFeature[seg_unshared] && - // leftFeature[bound_shared] && - // !leftFeature[bound_disjoint] && - // rightFeature[seg_unshared]; -} - -bool Relationship2D::coveredBy(Line2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {seg_unshared, seg_inside, seg_shared, seg_outside, poi_shared, bound_inside, bound_shared, bound_disjoint}; - - std::vector leftFeature(7, false); - std::vector rightFeature(1, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::coveredBy); - - /* return leftFeature[seg_inside] && - !leftFeature[seg_outside] && - leftFeature[bound_shared]; */ -} - -bool Relationship2D::coveredBy(Region2D &leftOperand, Region2D &rightOperand) -{ - // Indicates what index in the bool vector represents what flag - enum VectorFlag {zero_one, one_zero, one_two, two_one, zero_two, two_zero, one_one, bound_poi_shared}; - - std::vector leftFeature(8, false); - std::vector rightFeature(4, false); - - // Explore - Explore::explore(leftOperand, rightOperand, leftFeature, rightFeature); - // Evaluate - return Evaluate::validate(leftOperand, rightOperand, leftFeature, rightFeature, Predicate::coveredBy); - - /* return !(rightFeature[one_two] || rightFeature[two_one]) && - !(leftFeature[zero_one] || leftFeature[one_zero] || leftFeature[one_one] || rightFeature[one_two] || rightFeature[two_one]) && - (leftFeature[zero_two] || leftFeature[two_zero] || leftFeature[one_one] || leftFeature[bound_poi_shared]) && - !(leftFeature[zero_one] || leftFeature[one_zero]) && - (leftFeature[one_two] || leftFeature[two_one] || leftFeature[one_one] || rightFeature[zero_one] || rightFeature[one_zero]); */ -} diff --git a/src/SpatialOperations.cpp b/src/SpatialOperations.cpp deleted file mode 100644 index d915148..0000000 --- a/src/SpatialOperations.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "SpatialOperations.h" - -SpatialOperations::SpatialOperations() -{ - // Emtpy -} - -SpatialOperations::~SpatialOperations() -{ - // Emtpy -} - -Point2D SpatialOperations::union(Point2D F, Point2D G) { - Point2D poi = new Point2D(); - // Point2D won't accept duplicate points being added - // Loop through both sets of points and add them to a new point object - for (int i = 0; i < F.getNumberOfPoints(); i++ ) { - poi.add( F[i] ); - } - - for (int i = 0; i < G.getNumberOfPoints(); i++ ) { - poi.add( G[i] ); - } - - return poi; -} - -Line2D SpatialOperations::union(Line2D F, Line2D G){ - Line2D line = new Line2D(); - // Add lines from F and G to new line object - for (int i = 0; i < F.getNumberOfSegments(); i++){ - line.add( F[i] ); - } - for (int i = 0; i < G.getNumberOfSegments(); i++){ - line.add( G[i] ); - } - return line; -} - -Region2D SpatialOperations::union(Region2D F, Region2D G){ - Region2D region = new Region2D(); - // Add regions from F and G to new region object - for (int i = 0; i < F.getNumberOfFaces(); i++){ - region.add( F[i] ); - } - for (int i = 0; i < G.getNumberOfFaces(); i++){ - region.add( G[i] ); - } - return region; -} - -Point2D SpatialOperations::intersection(Point2D F, Point2D G){ - Point2D poi = new Point2D(); - // Compare all points in F with all points in G - // Add to new point object if points are the same - for (int i = 0; i < F.getNumberOfPoints(); i++){ - for (int j = 0; j < G.getNumberOfPoints(); j++){ - if(F[i] == G[j]){ - poi.add( F[i] ); - } - } - } - return poi; -} - -Point2D SpatialOperations::difference(Point2D F, Point2D G){ - Point2D poi = new Point2D(); - // Add all points from F into new point object - // Remove all points from G from new point object - for (int i = 0; i < F.getNumberOfPoints(); i++){ - poi.add( F[i] ); - } - for (int i = 0; i < G.getNumberOfPoints(); i++){ - poi.remove( G[i] ); - } - return poi; -} - -Point2D union(Point2D F, Point2D G) { - //implemented - return new Point2D(); -} - -Line2D union(Line2D F, Line2D G) { - //implemented - return new Line2D(); -} - -Region2D union(Region2D F, Region2D G) { - //implemented - return new Region2D(); -} - -Point2D intersection(Point2D F, Point2D G) { - //implemented - return new Point2D(); -} - -Line2D intersection(Line2D F, Line2D G) { - return new Point2D(); -} - -Region2D intersection(Region2D F, Region2D G) { - return new Region2D(); -} - -Line2D intersection(Region2D F, Line2D G) { - return new Line2D(); -} - -Point2D difference(Point2D F, Point2D G) { - //implemented - return new Point2D(); -} - -Line2D difference(Line2D F, Line2D G) { - return new Line2D(); -} - -Region2D difference(Region2D F, Region2D G) { - return new Region2D(); -} diff --git a/test/NumberTest.cpp b/test/NumberTest.cpp new file mode 100644 index 0000000..a7e9552 --- /dev/null +++ b/test/NumberTest.cpp @@ -0,0 +1,262 @@ +#include "Number.h" +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE NumberTest +#include +#include +#include + +BOOST_AUTO_TEST_CASE(init_out) +{ + boost::test_tools::output_test_stream out; + Number a; + out << a; + BOOST_REQUIRE(out.is_equal("0")); +} + +BOOST_AUTO_TEST_CASE(init_string) +{ + boost::test_tools::output_test_stream out; + Number a("500"); + out << a; + BOOST_REQUIRE(out.is_equal("500")); +} + +BOOST_AUTO_TEST_CASE(init_negative) +{ + boost::test_tools::output_test_stream out; + Number a("-400"); + out << a; + BOOST_REQUIRE(out.is_equal("-400")); +} + +BOOST_AUTO_TEST_CASE(init_to_string) +{ + Number a("500.7293203823820"); + BOOST_REQUIRE(a.to_string(13) == "500.7293203823820"); +} + +BOOST_AUTO_TEST_CASE(to_string_truncate) +{ + Number a("500.7293203823820"); + BOOST_CHECK_EQUAL(a.to_string(10), "500.7293203823"); +} + +BOOST_AUTO_TEST_CASE(to_string_expand) +{ + Number a("500.7293203823820"); + BOOST_CHECK_EQUAL(a.to_string(15), "500.729320382382000"); +} + +BOOST_AUTO_TEST_CASE(init_negative_decimal) +{ + Number a("-4.87654"); + BOOST_CHECK_EQUAL(a.to_string(5), "-4.87654"); +} + +BOOST_AUTO_TEST_CASE(malformed_number) +{ + BOOST_CHECK_THROW(Number a("7 - 99"), std::invalid_argument); + BOOST_CHECK_THROW(Number a("5/3"), std::invalid_argument); + BOOST_CHECK_THROW(Number a("1.45e+14"), std::invalid_argument); + BOOST_CHECK_THROW(Number a("500.729.789"), std::invalid_argument); + BOOST_CHECK_THROW(Number a("500.729abc"), std::invalid_argument); +} + +BOOST_AUTO_TEST_CASE(assignment) +{ + Number a("65.378"); + Number b; + b = a; + BOOST_CHECK_EQUAL(b.to_string(3), "65.378"); +} + +BOOST_AUTO_TEST_CASE(addition) +{ + Number a("678.56"); + Number b("0.678965"); + Number c; + c = a + b; + BOOST_CHECK_EQUAL(c.to_string(6), "679.238965"); +} + +BOOST_AUTO_TEST_CASE(add_assign) +{ + Number a("678.56"); + Number b("0.678965"); + a += b; + BOOST_CHECK_EQUAL(a.to_string(6), "679.238965"); +} + +BOOST_AUTO_TEST_CASE(subtraction) +{ + Number a("678.56"); + Number b("0.678965"); + Number c; + c = a - b; + BOOST_CHECK_EQUAL(c.to_string(6), "677.881035"); +} + +BOOST_AUTO_TEST_CASE(sub_assign) +{ + Number a("678.56"); + Number b("0.678965"); + a -= b; + BOOST_CHECK_EQUAL(a.to_string(6), "677.881035"); +} + +BOOST_AUTO_TEST_CASE(multiplication) +{ + Number a("78.563"); + Number b("25.87601"); + Number c; + c = a * b; + BOOST_CHECK_EQUAL(c.to_string(8), "2032.89697363"); +} + +BOOST_AUTO_TEST_CASE(mult_assign) +{ + Number a("78.563"); + Number b("25.87601"); + a *= b; + BOOST_CHECK_EQUAL(a.to_string(8), "2032.89697363"); +} + +BOOST_AUTO_TEST_CASE(division) +{ + Number a("78.563"); + Number b("25.87601"); + Number c; + c = a / b; + BOOST_CHECK_EQUAL(c.to_string(20), "3.03613269588317518813"); +} + +BOOST_AUTO_TEST_CASE(div_assign) +{ + Number a("78.563"); + Number b("25.87601"); + a /= b; + BOOST_CHECK_EQUAL(a.to_string(20), "3.03613269588317518813"); +} + +BOOST_AUTO_TEST_CASE(exponentiation) +{ + Number a("78.563"); + int b = 3; + Number c; + c = a ^ b; + BOOST_CHECK_EQUAL(c.to_string(4), "484902.2251"); +} + +BOOST_AUTO_TEST_CASE(less_than) +{ + Number a("56.78"); + Number b("67.78"); + Number c("45.78"); + Number d("56.78"); + BOOST_CHECK_EQUAL(a < b, true); + BOOST_CHECK_EQUAL(a < c, false); + BOOST_CHECK_EQUAL(a < d, false); +} + +BOOST_AUTO_TEST_CASE(less_than_equal) +{ + Number a("56.78"); + Number b("67.78"); + Number c("45.78"); + Number d("56.78"); + BOOST_CHECK_EQUAL(a <= b, true); + BOOST_CHECK_EQUAL(a <= c, false); + BOOST_CHECK_EQUAL(a <= d, true); +} + +BOOST_AUTO_TEST_CASE(greater_than) +{ + Number a("56.78"); + Number b("67.78"); + Number c("45.78"); + Number d("56.78"); + BOOST_CHECK_EQUAL(a > b, false); + BOOST_CHECK_EQUAL(a > c, true); + BOOST_CHECK_EQUAL(a > d, false); +} + +BOOST_AUTO_TEST_CASE(greater_than_equal) +{ + Number a("56.78"); + Number b("67.78"); + Number c("45.78"); + Number d("56.78"); + BOOST_CHECK_EQUAL(a >= b, false); + BOOST_CHECK_EQUAL(a >= c, true); + BOOST_CHECK_EQUAL(a >= d, true); +} + +BOOST_AUTO_TEST_CASE(equal) +{ + Number a("56.78"); + Number b("67.78"); + Number c("56.78"); + BOOST_CHECK_EQUAL(a == a, true); + BOOST_CHECK_EQUAL(a == b, false); + BOOST_CHECK_EQUAL(a == c, true); +} + +BOOST_AUTO_TEST_CASE(not_equal) +{ + Number a("56.78"); + Number b("67.78"); + Number c("56.78"); + BOOST_CHECK_EQUAL(a != a, false); + BOOST_CHECK_EQUAL(a != b, true); + BOOST_CHECK_EQUAL(a != c, false); +} + +BOOST_AUTO_TEST_CASE(sqrt_approx) +{ + Number a("5"); + a = a.sqrt(); + double sqrt5 = 2.236068; + double result = std::stod(a.to_string(6)); + BOOST_CHECK_CLOSE(result, sqrt5, 0.0001); +} + +BOOST_AUTO_TEST_CASE(sqrt_digits) +{ + Number a("5"); + a = a.sqrt(98); + std::string oeis_a002163 = "2.23606797749978969640917366873127623544" + "0618359611525724270897245410520925637804" + "89941441440837878227"; + BOOST_CHECK_EQUAL(a.to_string(98), oeis_a002163); +} + +BOOST_AUTO_TEST_CASE(sqrt_digits_neg) +{ + Number a("-5"); + BOOST_CHECK_THROW(a.sqrt(2), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(input_stream) +{ + Number a; + std::stringstream ss; + ss << "5.6789"; + ss >> a; + BOOST_CHECK_EQUAL(a.to_string(4), "5.6789"); +} + +BOOST_AUTO_TEST_CASE(malformed_input) +{ + Number a; + std::stringstream ss; + ss << "7 - 99\n"; + BOOST_CHECK_THROW(ss >> a, std::invalid_argument); + ss << "5/3\n"; + BOOST_CHECK_THROW(ss >> a, std::invalid_argument); + ss << "1.45e+14\n "; + BOOST_CHECK_THROW(ss >> a, std::invalid_argument); + ss << "500.729.789\n"; + BOOST_CHECK_THROW(ss >> a, std::invalid_argument); + ss << "500.729abc\n"; + BOOST_CHECK_THROW(ss >> a, std::invalid_argument); +} \ No newline at end of file