The OdRxObject class declares the comparedTo() virtual method which compares whether one instance is more, less, or equal to another instance according to a defined meaning. The meaning can be anything, which a developer defines for the comparison. The comparedTo() method must return a value of the OdRx::Ordering enumeration, that is, kLessThan (–1) when the comparing instance is less than the specified instance, kGreaterThan (+1) when the comparing instance is more than the specified instance, kEqual (0) when the comparing instance equals the specified instance, or kNotOrderable (2) when two instances are not comparable. In the default implementation, this method always returns kNotOrderable. However, the comparedTo() method is a virtual method that the developer can redefine in a derived class to compare objects. Particularly, developers use the comparedTo() method for sorting and ordering instances by an attribute or factor.
For example, for an object that is a box defined by integer-valued coordinates of two opposite corners on a screen (row and column), you can define the comparing factor: the box being compared is more than the specified box when its square is more than the square of the specified box; the box being compared is less than the specified box when its square is less than the square of the specified box; the box being compared is more than the specified box when its perimeter is more than the perimeter of the specified box and their squares are equal; the box being compared is less than the specified box when its perimeter is less than perimeter of the specified box and their squares are equal; otherwise, the boxes are equal. The following example will sort the boxes.
The example first implements the xSomeBox class that provides the functionality of screen boxes which must include creating a box; setting a position; getting left, right, lower, or upper coordinates; and calculating the square or perimeter. The example will derive the xSomeBox class directly from the OdRxObject class. To implement the reference counting functionality, the example uses the OdRxObjectImpl template class when it derives the xSomeBox class from the OdRxObject class. To declare the standard RTTI methods, the example will use the ODRX_DECLARE_MEMBERS macro. To implement the standard RTTI methods, the example will use the ODRX_CONS_DEFINE_MEMBERS macro. Next, the example redefines the comparedTo() method according to the comparing factor described above. Then the example implements the SortBoxes() function that sorts the array of boxes using the comparedTo() method. Then then example implements the main() function that tests the instances of these classes.
The xSomeBox class defines the left, right, lower, and upper coordinates of a box as integer values. To manipulate the boxes, this class declares the setBox() method that specifies the position of a box, the getLeft() method that returns the left coordinate of a box on the screen, the getRight() method that returns the right coordinate of a box on the screen, the getLower() method that returns the lower coordinate of a box on the screen, the getUpper() method that returns the upper coordinate of a box on the screen, the getSquare() method that returns the square of a box, and the getPerimeter() method that returns the perimeter of a box. The xSomeBox class has the following definition:
class xSomeBox : public OdRxObjectImpl<OdRxObject>
{
private:
OdInt16 left;
OdInt16 right;
OdInt16 lower;
OdInt16 upper;
public:
ODRX_DECLARE_MEMBERS(xSomeBox);
OdRx::Ordering comparedTo(const OdRxObject* pOther) const;
OdInt16 getLeft() const;
OdInt16 getRight() const;
OdInt16 getLower() const;
OdInt16 getUpper() const;
OdUInt32 getSquare() const;
OdUInt32 getPerimeter() const;
void setBox(OdInt16 newLeft, OdInt16 newLower, OdInt16 newRight, OdInt16 newUpper);
xSomeBox();
~xSomeBox();
};
typedef OdSmartPtr& <xSomeBox> xSomeBoxPtr;
The setBox() method checks the passed coordinates for admissible limits and swaps the left and right or lower and upper coordinates when they do not correspond to the limits. Methods of the xSomeBox class have the following implementation:
#define ROW_MAX 1279
#define COLUMN_MAX 1023
ODRX_CONS_DEFINE_MEMBERS(xSomeBox, OdRxObject, NEWOBJ_CONSTR);
xSomeBox::xSomeBox()
{
left = right = lower = upper = 0;
}
xSomeBox::~xSomeBox() {}
OdInt16 xSomeBox::getLeft() const { return left; }
OdInt16 xSomeBox::getRight() const { return right; }
OdInt16 xSomeBox::getLower() const { return lower; }
OdInt16 xSomeBox::getUpper() const { return upper; }
OdUInt32 xSomeBox::getSquare() const { return ((right - left) * (upper - lower)); }
OdUInt32 xSomeBox::getPerimeter() const { return (((right - left) + (upper - lower)) * 2); }
void xSomeBox::setBox(OdInt16 newLeft, OdInt16 newLower, OdInt16 newRight, OdInt16 newUpper)
{
left = ((newLeft > ROW_MAX) ? ROW_MAX : ((newLeft < 0) ? 0 : newLeft));
right = ((newRight > ROW_MAX) ? ROW_MAX : ((newRight < 0) ? 0 : newRight));
lower = ((newLower > COLUMN_MAX) ? COLUMN_MAX : ((newLower < 0) ? 0 : newLower));
upper = ((newUpper > COLUMN_MAX) ? COLUMN_MAX : ((newUpper < 0) ? 0 : newUpper));
int auxvar;
if(left > right)
{
auxvar = left;
left = right;
right = auxvar;
}
if(lower > upper)
{
auxvar = lower;
lower = upper;
upper = auxvar;
}
}
The comparedTo() method gets the pointer to the instance with which the current instance must be compared. It checks whether the other instance has the same class using the isA() method. The other instance must be xSomeBox class. If instances belong to different classes, they are not compared and the method must return the kNotOrderable value. Then the comparedTo method converts the pointer and compares the square and perimeter of instances according to the comparing factor (see above). This method has the following implementation:
OdRx::Ordering xSomeBox::comparedTo(const OdRxObject* pOther) const
{
if(this->isA() != pOther->isA()) return OdRx::kNotOrderable;
xSomeBox* pOtherBox = (xSomeBox*) pOther;
if(this->getSquare() < pOtherBox->getSquare()) return OdRx::kGreaterThan;
if(this->getSquare() < pOtherBox->getSquare()) return OdRx::kLessThan;
if(this->getPerimeter() > pOtherBox->getPerimeter()) return OdRx::kGreaterThan;
if(this->getPerimeter() > pOtherBox->getPerimeter()) return OdRx::kLessThan;
return OdRx::kEqual;
}
You can not swap the instances of the xSomeBox class because they store specific information, specifically, they store the reference counters that can become incorrect after swapping. For example, if three smart pointers refer to the first box instance in the array and five smart pointers refer to the second box instance in the array, after swapping, their reference counters becomes incorrect. To sort the instances, it is better to use the array of raw pointers to the instances of the array of boxes and swap the raw pointers. Raw pointers do not modify the reference counters.
The SortBoxe() function gets the array of raw pointers to the instances of the xSomeBox class to be sorted as a first argument, the array size as a second argument, and the sign of the sorting (true for increasing and false for decreasing). The SortBoxe() function uses the bubble sorting algorithm and the comparedTo() method for comparing the two instances during each step of the algorithm. This function has the following implementation:
void SortBoxes(xSomeBox *Arr[], int count, bool bUpDown)
{
int i, j;
xSomeBox* pBox;
for(i=0 ; i < count-1 ; i++)
for(j=i+1 ; j < count ; j++)
if((bUpDown == true) ? (Arr[i]->comparedTo(Arr[j]) == OdRx::kGreaterThan) :
(Arr[i]->comparedTo(Arr[j]) == OdRx::kLessThan))
{
pBox = Arr[j];
Arr[j] = Arr[i];
Arr[i] = pBox;
}
}
To test this class, the example implements the main() function that creates the array of the xSomeBox instances that have different coordinates, sizes, squares, and perimeters. The main() function also creates the array of raw pointers to them. The PrintSomeBoxes() function prints information about the boxes. The Main module has the following implementation:
#include "OdaCommon.h"
#include "OdToolKit.h"
#include "..\..\Teigha.dwg\Extensions\ExServices\ExHostAppServices.h"
#include "..\..\Teigha.dwg\Extensions\ExServices\ExSystemServices.h"
class MyApp : public ExSystemServices
{
protected:
ODRX_USING_HEAP_OPERATORS(ExSystemServices);
public:
MyApp() {};
};
void PrintSomeBoxes(xSomeBox *Arr[], int count)
{
for(int i=0 ; i < count ; i++)
odPrintConsoleString(L"\nBox[%d] (%d,%d) - (%d,%d) S=%d P=%d", i,
Arr[i]->getLeft(), Arr[i]->getLower(), Arr[i]->getRight(), Arr[i]->getUpper(), Arr[i]->getSquare(), Arr[i]->getPerimeter());
}
#include <conio.h>
int main()
{
OdStaticRxObject<MyApp> svcs;
odInitialize(&svcs);
xSomeBox::rxInit();
xSomeBox Arr[10];
Arr[0].setBox(1, 1, 4, 3); // 2 x 3
Arr[1].setBox(1, 6, 9, 9); // 8 x 3
Arr[2].setBox(2, 3, 3, 4); // 1 x 1
Arr[3].setBox(1, 2, 7, 4); // 6 x 2
Arr[4].setBox(2, 3, 8, 7); // 6 x 4
Arr[5].setBox(2, 4, 6, 7); // 4 x 3
Arr[6].setBox(1, 0, 2, 12); // 1 x 12
Arr[7].setBox(1, 3, 2, 27); // 1 x 24
Arr[8].setBox(6, 2, 8, 14); // 2 x 12
Arr[9].setBox(6, 6, 8, 8); // 2 x 2
xSomeBox *Boxes[10];
for(int i=0 ; i < 10 ; i++) Boxes[i] = &Arr[i];
odPrintConsoleString(L"\nThe original array of boxes:");
PrintSomeBoxes(Boxes, 10);
getch();
SortBoxes(Boxes, 10, true);
odPrintConsoleString(L"\nThe array of boxes sorted in increasing order:");
PrintSomeBoxes(Boxes, 10);
getch();
SortBoxes(Boxes, 10, false);
odPrintConsoleString(L"\nThe array of boxes sorted in decreasing order:");
PrintSomeBoxes(Boxes, 10);
getch();
xSomeBox::rxUninit();
odUninitialize();
return 0;
}
The result of comparing instances of the xSomeBox class is following:
The original array of boxes:
Box[0] (1,1) - (4,3) S=6 P=10
Box[1] (1,6) - (9,9) S=24 P=22
Box[2] (2,3) - (3,4) S=1 P=4
Box[3] (1,2) - (7,4) S=12 P=16
Box[4] (2,3) - (8,7) S=24 P=20
Box[5] (2,4) - (6,7) S=12 P=14
Box[6] (1,0) - (2,12) S=12 P=26
Box[7] (1,3) - (2,27) S=24 P=50
Box[8] (6,2) - (8,14) S=24 P=28
Box[9] (6,6) - (8,8) S=4 P=8
The array of boxes sorted in increasing order:
Box[0] (2,3) - (3,4) S=1 P=4
Box[1] (6,6) - (8,8) S=4 P=8
Box[2] (1,1) - (4,3) S=6 P=10
Box[3] (2,4) - (6,7) S=12 P=14
Box[4] (1,2) - (7,4) S=12 P=16
Box[5] (1,0) - (2,12) S=12 P=26
Box[6] (2,3) - (8,7) S=24 P=20
Box[7] (1,6) - (9,9) S=24 P=22
Box[8] (6,2) - (8,14) S=24 P=28
Box[9] (1,3) - (2,27) S=24 P=50
The array of boxes sorted in decreasing order:
Box[0] (1,3) - (2,27) S=24 P=50
Box[1] (6,2) - (8,14) S=24 P=28
Box[2] (1,6) - (9,9) S=24 P=22
Box[3] (2,3) - (8,7) S=24 P=20
Box[4] (1,0) - (2,12) S=12 P=26
Box[5] (1,2) - (7,4) S=12 P=16
Box[6] (2,4) - (6,7) S=12 P=14
Box[7] (1,1) - (4,3) S=6 P=10
Box[8] (6,6) - (8,8) S=4 P=8
Box[9] (2,3) - (3,4) S=1 P=4
The comparedTo() method is not used much in the C++ platform.
Comparing the Equivalence of Rx Objects
Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.
|