The OdRxObject class declares the copyFrom() virtual method that copies the content of the source instance into an instance for which it is called. This method does not return a value and requires the raw pointer to the instance from which it copies data. Developers can redefine it in their own derived classes. The redefined copyFrom() method can copy whole content from an instance of the same class or part of the content from an instance of another class. Developers can also use this method to initialize an instance using another instance of the same or another class.
For example, consider three classes: point, box, and circle. The point object is defined by two-dimensional coordinates of the position in a plane, the box object is defined by two-dimensional coordinates of two opposite corners in a plane, and the circle object is defined by two-dimensional coordinates of the center in a plane and radius. We can redefine the copyFrom() method for each class so that it can copy the content from an instance of one class to an instance of other class using the following assumptions:
The example first implements the xSomePoint class that provides the functionality of points which must include creating a point, setting a position, and getting the X-coordinate or Y-coordinate. Then the example implements the xSomeBox class that provides the functionality of boxes which must include creating a box, setting the position, and getting the left, right, lower, or upper coordinates. The example next implements the xSomeCircle class that provides the functionality of circles which must include creating a circle, setting the position and radius, and getting the X-coordinate, Y-coordinate, or radius. Last, the example implements the main() function that creates four instances of each class, initializes one instance of each class, and copies the content of each initialized instance into instances of each other class.
The example derives the xSomePoint, xSomeBox, and xSomeCircle classes directly from the OdRxObject class. To declare the standard RTTI methods, the example uses the ODRX_DECLARE_MEMBERS macro. To implement the standard RTTI methods, the example uses the ODRX_CONS_DEFINE_MEMBERS macro. The example redefines the copyFrom() virtual method for each class.
The xSomePoint class defines the X-coordinate and Y-coordinate as double values. To manipulate points, this class declares the setPoint() method that specifies the position, the getX() method that returns the current X-coordinate, and the getY() method that returns the current Y-coordinate. The xSomePoint class has the following definition:
class xSomePoint : public OdRxObjectImpl<OdRxObject>
{
private:
double posX;
double posY;
public:
ODRX_DECLARE_MEMBERS(xSomePoint);
void copyFrom(const OdRxObject* pSource);
double getX() const;
double getY() const;
void setPoint(double newPosX, double newPosY);
xSomePoint();
~xSomePoint();
};
typedef OdSmartPtr<xSomePoint> xSomePointPtr;
Its methods have the following implementation:
ODRX_CONS_DEFINE_MEMBERS(xSomePoint, OdRxObject, NEWOBJ_CONSTR);
xSomePoint::xSomePoint() { posX = posY = 0; }
xSomePoint::~xSomePoint() {}
double xSomePoint::getX() const { return posX; }
double xSomePoint::getY() const { return posY; }
void xSomePoint::setPoint(double newPosX, double newPosY)
{
PosX = newPosX;
PosY = newPosY;
}
The redefined copyFrom() method gets the raw pointer to the source instance whose content must be used as data for copying. The method checks the class name of the passed object and selects the action subject to the class of the source instance. The method converts the raw pointer to the corresponding class type and uses the setPoint() method to set new coordinates of the point object. When the class name is "xSomePoint", the method copies the coordinates of the passed point object using the getX() and getY() methods. When the class name is "xSomeBox", the method calculates the box center as half the width and half the height using the getLeft(), getRight(), getLower(), and getUpper() methods of the passed box object and sets the point coordinates to the box center. When the class name is "xSomeCircle", the method sets the point coordinates to the circle center using the getCenterX() and getCenterY() methods of the passed circle object. The redefined copyFrom() method has the following implementation:
void xSomePoint::copyFrom(const OdRxObject* pSource)
{
if(pSource->isA()->name().compare(L"xSomePoint") == 0)
{
xSomePoint* pPoint = (xSomePoint*) pSource;
this->setPoint(pPoint->getX(), pPoint->getY());
}
else if(pSource->isA()->name().compare(L"xSomeBox") == 0)
{
xSomeBox* pBox = (xSomeBox*) pSource;
this->setPoint((pBox->getLeft() + pBox->getRight()) / 2 , (pBox->getLower() + pBox->getUpper()) / 2);
}
else if(pSource->isA()->name().compare(L"xSomeCircle") == 0)
{
xSomeCircle* pCircle = (xSomeCircle*) pSource;
this->setPoint(pCircle->getCenterX() , pCircle->getCenterY());
}
}
The xSomeBox class defines the left, right, lower, and upper coordinates of a box as double values. To manipulate boxes, this class declares the setBox() method that specifies the position of a box, the getLeft() method that returns the X-coordinate of the left edge, the getRight() method that returns the X-coordinate of the right edge, the getLower() method that returns the Y-coordinate of the lower edge, and the getUpper() method that returns the Y-coordinate of the upper edge. The xSomeBox class has the following definition:
class xSomeBox : public OdRxObjectImpl<OdRxObject>
{
private:
double left;
double right;
double lower;
double upper;
public:
ODRX_DECLARE_MEMBERS(xSomeBox);
void copyFrom(const OdRxObject* pSource);
double getLeft() const;
double getRight() const;
double getLower() const;
double getUpper() const;
void setBox(double newLeft, double newLower, double newRight, double newUpper);
xSomeBox();
~xSomeBox();
};
typedef OdSmartPtr<xSomeBox> xSomeBoxPtr;
Its methods have the following implementation:
ODRX_CONS_DEFINE_MEMBERS(xSomeBox, OdRxObject, NEWOBJ_CONSTR);
xSomeBox::xSomeBox()
{
left = lower = 0; right = upper = 1;
}
xSomeBox::~xSomeBox() {}
double xSomeBox::getLeft() const { return left; }
double xSomeBox::getRight() const { return right; }
double xSomeBox::getLower() const { return lower; }
double xSomeBox::getUpper() const { return upper; }
void xSomeBox::setBox(double newLeft, double newLower, double newRight, double newUpper)
{
if(newLeft > newRight)
{
left = newRight;
right = newLeft;
}
else
{
left = newLeft;
right = newRight;
}
if(newLower > newUpper)
{
lower = newUpper;
upper = newLower;
}
else
{
lower = newLower;
upper = newUpper;
}
}
The redefined copyFrom() method gets the raw pointer to the source instance whose content must be used as data for copying. The method checks the class name of the passed object and selects the action subject to the source instance. The method converts the raw pointer to the corresponding class type and uses the setBox() method to set new coordinates of the box object. When the class name is "xSomePoint", the method sets the lower-left corner using the getX() and getY() methods of the passed point object and sets the upper-right corner to one more. When the class name is "xSomeBox", the method copies the coordinates of the lower-left corner and upper-right corner using the getLeft(), getRight(), getLower(), and getUpper() methods of the passed box object. When the class name is "xSomeCircle", the method calculates the lower-left corner and upper-right corner of the circumscribed quadrilateral using the getCenterX(), getCenterY(), and getRadius() methods of the passed circle object. The redefined copyFrom() method has the following implementation:
void xSomeBox::copyFrom(const OdRxObject* pSource)
{
if(pSource->isA()->name().compare(L"xSomePoint") == 0)
{
xSomePoint* pPoint = (xSomePoint*) pSource;
this->setBox(pPoint->getX(), pPoint->getY(), pPoint->getX() + 1, pPoint->getY() + 1);
}
else if(pSource->isA()->name().compare(L"xSomeBox") == 0)
{
xSomeBox* pBox = (xSomeBox*) pSource;
this->setBox(pBox->getLeft(), pBox->getLower(), pBox->getRight(), pBox->getUpper());
}
else if(pSource->isA()->name().compare(L"xSomeCircle") == 0)
{
xSomeCircle* pCircle = (xSomeCircle*) pSource;
this->setBox(pCircle->getCenterX() - pCircle->getRadius(), pCircle->getCenterY() - pCircle->getRadius(),
pCircle->getCenterX() + pCircle->getRadius(), pCircle->getCenterY() + pCircle->getRadius());
}
}
The xSomeCircle class defines the center coordinates and radius of a circle as double values. To manipulate circles, this class declares the setCircle() method that specifies the center position and radius of a circle, the getCenterX() method that returns the current X-coordinate of the center, the getCenterY() method that returns the current Y-coordinate of the center, and the getRadius() method that returns the radius. The xSomeCircle class has the following definition:
class xSomeCircle : public OdRxObjectImpl<OdRxObject>
{
private:
double centerX;
double centerY;
double radius;
public:
ODRX_DECLARE_MEMBERS(xSomeCircle);
void copyFrom(const OdRxObject* pSource);
double getCenterX() const;
double getCenterY() const;
double getRadius() const;
void setCircle(double newCenterX, double newCenterY, double newRadius);
xSomeCircle();
~xSomeCircle();
};
typedef OdSmartPtr<xSomeCircle> xSomeCirclePtr;
Its methods have the following implementation:
ODRX_CONS_DEFINE_MEMBERS(xSomeCircle, OdRxObject, NEWOBJ_CONSTR);
xSomeCircle::xSomeCircle()
{
centerX = centerY = 0; radius = 1;
}
xSomeCircle::~xSomeCircle() {}
double xSomeCircle::getCenterX() const { return centerX; }
double xSomeCircle::getCenterY() const { return centerY; }
double xSomeCircle::getRadius() const { return radius; }
void xSomeCircle::setCircle(double newCenterX, double newCenterY, double newRadius)
{
centerX = newCenterX;
centerY = newCenterY;
radius = ((newRadius < 0) ? -newRadius : newRadius);
}
The redefined copyFrom() method gets the raw pointer to the source instance whose content must be used as data for copying. The method checks the class name of the passed object and selects the action subject to the source instance. The method converts the raw pointer to the corresponding class type and uses the setCircle() method to set a new center position and radius of the circle object. When the class name is "xSomePoint", the method sets the center at this point using the getX() and getY() methods of the passed point object and sets the radius to one. When the class name is "xSomeBox", the method calculates the circle center as the box center (half width and half height) and calculates the radius as half of the minimal side (width or height) using the getLeft(), getRight(), getLower(), and getUpper() methods of the passed box object. When the class name is "xSomeCircle", the method copies the center coordinates and radius using the getCenterX(), getCenterY(), and getRadius() methods of the passed circle object. The redefined copyFrom() method has the following implementation:
void xSomeCircle::copyFrom(const OdRxObject* pSource)
{
if(pSource->isA()->name().compare(L"xSomePoint") == 0)
{
xSomePoint* pPoint = (xSomePoint*) pSource;
this->setCircle(pPoint->getX(), pPoint->getY(), 1);
}
else if(pSource->isA()->name().compare(L"xSomeBox") == 0)
{
xSomeBox* pBox = (xSomeBox*) pSource;
this->setCircle((pBox->getLeft() + pBox->getRight()) / 2, (pBox->getLower() + pBox->getUpper()) / 2,
(((pBox->getRight() - pBox->getLeft()) > (pBox->getUpper() - pBox->getLower())) ?
(pBox->getUpper() - pBox->getLower()) / 2 : (pBox->getRight() - pBox->getLeft()) / 2));
}
else if(pSource->isA()->name().compare(L"xSomeCircle") == 0)
{
xSomeCircle* pCircle = (xSomeCircle*) pSource;
this->setCircle(pCircle->getCenterX(), pCircle->getCenterY(), pCircle->getRadius());
}
}
For testing the copying of these classes, the main() function creates the source point instance, source box instance, source circle instance, and initializes them. Then the main() function creates three point instances with default coordinates (0,0), three box instances with default coordinates of corners (0,0) — (1,1), and three circle instances with default parameters (0,0) R=1. Next, the main() function copies the content of the source point instance in the first point, first box, and first circle instances; the content of the source box instance in the second point, second box, and second circle instances; the content of the source circle instance in the third point, third box, and third circle instances, and prints the result of the copying. 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() {};
};
#include <conio.h>
int main()
{
OdStaticRxObject<MyApp> svcs;
odInitialize(&svcs);
xSomePoint::rxInit();
xSomeBox::rxInit();
xSomeCircle::rxInit();
xSomePoint point, point1, point2, point3;
xSomeBox box, box1, box2, box3;
xSomeCircle circle, circle1, circle2, circle3;
point.setPoint(2, 4);
box.setBox(1, 1, 5, 5);
circle.setCircle(3, 6, 2);
odPrintConsoleString(L"\nThe original figures:");
odPrintConsoleString(L"\nPoint: (%g , %g)", point.getX(), point.getY());
odPrintConsoleString(L"\nCircle: (%g , %g) R=%g", circle.getCenterX(), circle.getCenterY(), circle.getRadius());
odPrintConsoleString(L"\nBox: (%g , %g) - (%g , %g)", box.getLeft(), box.getLower(), box.getRight(), box.getUpper());
getch();
point1.copyFrom(&point);
point2.copyFrom(&circle);
point3.copyFrom(&box);
odPrintConsoleString(L"\nThe points after copying of the content:");
odPrintConsoleString(L"\nPoint1: (%g , %g) from point", point1.getY(), point1.getY());
odPrintConsoleString(L"\nPoint2: (%g , %g) from circle", point2.getX(), point2.getY());
odPrintConsoleString(L"\nPoint3: (%g , %g) from box", point3.getX(), point3.getY());
getch();
box1.copyFrom(&point);
box2.copyFrom(&circle);
box3.copyFrom(&box);
odPrintConsoleString(L"\nThe boxes after copying of the content:");
odPrintConsoleString(L"\nBox1: (%g , %g) - (%g , %g) from point", box1.getLeft(), box1.getLower(), box1.getRight(), box1.getUpper());
odPrintConsoleString(L"\nBox2: (%g , %g) - (%g , %g) from circle", box2.getLeft(), box2.getLower(), box2.getRight(), box2.getUpper());
odPrintConsoleString(L"\nBox3: (%g , %g) - (%g , %g) from box", box3.getLeft(), box3.getLower(), box3.getRight(), box3.getUpper());
getch();
circle1.copyFrom(&point);
circle2.copyFrom(&circle);
circle3.copyFrom(&box);
odPrintConsoleString(L"\nThe circles after copying of the content:");
odPrintConsoleString(L"\nCircle1: (%g , %g) R=%g from point", circle1.getCenterX(), circle1.getCenterY(), circle1.getRadius());
odPrintConsoleString(L"\nCircle2: (%g , %g) R=%g from circle", circle2.getCenterX(), circle2.getCenterY(), circle2.getRadius());
odPrintConsoleString(L"\nCircle3: (%g , %g) R=%g from box", circle3.getCenterX(), circle3.getCenterY(), circle3.getRadius());
getch();
xSomePoint::rxUninit();
xSomeBox::rxUninit();
xSomeCircle::rxUninit();
odUninitialize();
return 0;
}
The result of coping for these instances is the following:
The original figures:
Point: (2 , 4)
Circle: (3 , 6) R=2
Box: (1 , 1) - (5 , 5)
The points after copying of the content:
Point1: (2 , 4) from point
Point2: (3 , 6) from circle
Point3: (3 , 3) from box
The boxes after copying of the content:
Box1: (2 , 4) - (3 , 5) from point
Box2: (1 , 4) - (5 , 8) from circle
Box3: (1 , 1) - (5 , 5) from box
The circles after copying of the content:
Circle1: (2 , 4) R=1 from point
Circle2: (3 , 6) R=2 from circle
Circle3: (3 , 3) R=2 from box
Note: The clone() method of the OdRxObject class uses the copyFrom() method to initialize a new instance. You should redefine the copyFrom() method in its own classes for correct cloning of objects.
Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.
|