Commit d95b0482 authored by Janik Zikovsky's avatar Janik Zikovsky
Browse files

Fixes #1969: Removed superfluous scaleFactor member in IObjComponent. Fixed...

Fixes #1969: Removed superfluous scaleFactor member in IObjComponent. Fixed solid angle calculations.
parent ddf2c948
......@@ -348,7 +348,7 @@ void SetScalingPSD::movePos(API::MatrixWorkspace_sptr& WS, std::map<int,Geometry
if(maxScale<scale) maxScale=scale;
aveScale+=fabs(1.0-scale);
scaleCount++;
pmap.addV3D(comp.get(),"sca",V3D(1.0,it->second,1.0));
pmap.addV3D(comp.get(),"sca",V3D(1.0,it->second,1.0));
}
//
prog+= double(1)/m_vectDet.size();
......
......@@ -4,6 +4,7 @@
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidGeometry/V3D.h"
#include "MantidKernel/System.h"
#include <string>
#include <vector>
......@@ -116,6 +117,11 @@ namespace Mantid
/// Get the bounding box for this component and store it in the given argument
virtual void getBoundingBox(BoundingBox& boundingBox) const = 0;
/** Gets the scaling factor of the object for the Object Component.
* @return a vector with 1 in all 3 directions.
*/
virtual V3D getScaleFactor()const{ return V3D(1.0, 1.0, 1.0);}
/** @name ParameterMap access */
//@{
/// Return the names of the parameters for this component
......
......@@ -114,11 +114,6 @@ public:
/// Returns the material of the Object
virtual const boost::shared_ptr<const Material> material()const = 0;
void setScaleFactor(double xFactor,double yFactor, double zFactor);
///Gets the scaling factor of the object for the Object Component.
V3D getScaleFactor()const{return m_ScaleFactor;}
/// Gets the GeometryHandler
GeometryHandler* Handle()const{return handle;}
......@@ -130,8 +125,6 @@ protected:
/// Reset the current geometry handler
void setGeometryHandler(GeometryHandler *h);
/// Object Scaling factor in 3 axis direction. given as a vector
V3D m_ScaleFactor;
private:
/// Geometry Handle for rendering
......
......@@ -188,7 +188,7 @@ namespace Mantid
const IComponent* base()const { return m_base;}
/// Returns the ScaleFactor
virtual V3D getScaleFactorP() const;
virtual V3D getScaleFactor() const;
protected:
/// The base component - this is the unmodifed component (without the parameters). Stored
......
......@@ -182,7 +182,6 @@ namespace Mantid
return boost::shared_ptr<const Material>();
}
void setScaleFactor(double,double, double);
};
/// Typedef for shared pointer
......
......@@ -89,7 +89,6 @@ public:
void draw() const;
void drawObject() const;
void initDraw() const;
V3D getScaleFactorP() const;
///Return the shape of the component
const boost::shared_ptr<const Object> shape()const;
......
......@@ -10,79 +10,64 @@
namespace Mantid
{
namespace Geometry
{
namespace Geometry
{
IObjComponent::IObjComponent()
:m_ScaleFactor(1.0,1.0,1.0)
{
handle = new CacheGeometryHandler(this);
}
IObjComponent::IObjComponent()
{
handle = new CacheGeometryHandler(this);
}
/** Constructor, specifying the GeometryHandler (renderer engine)
* for this IObjComponent.
*/
IObjComponent::IObjComponent(GeometryHandler* the_handler)
:m_ScaleFactor(1.0,1.0,1.0)
{
handle = the_handler;
}
/** Constructor, specifying the GeometryHandler (renderer engine)
* for this IObjComponent.
*/
IObjComponent::IObjComponent(GeometryHandler* the_handler)
{
handle = the_handler;
}
// Looking to get rid of the first of these constructors in due course (and probably add others)
IObjComponent::~IObjComponent()
{
if(handle!=NULL)
delete handle;
}
// Looking to get rid of the first of these constructors in due course (and probably add others)
IObjComponent::~IObjComponent()
{
if(handle!=NULL)
delete handle;
}
/**
* Sets the scaling factor of the object for the Object Component.
* @param xFactor: scaling factor in x-direction
* @param yFactor: scaling factor in y-direction
* @param zFactor: scaling factor in z-direction
*/
void IObjComponent::setScaleFactor(double xFactor,double yFactor, double zFactor)
{
m_ScaleFactor=V3D(xFactor,yFactor,zFactor);
}
/**
* Set the geometry handler for IObjComponent
* @param[in] h is pointer to the geometry handler. don't delete this pointer in the calling function.
*/
void IObjComponent::setGeometryHandler(GeometryHandler *h)
{
if(h==NULL)return;
this->handle=h;
}
/**
* Set the geometry handler for IObjComponent
* @param[in] h is pointer to the geometry handler. don't delete this pointer in the calling function.
*/
void IObjComponent::setGeometryHandler(GeometryHandler *h)
{
if(h==NULL)return;
this->handle=h;
}
/**
* Copy constructor
* @param origin :: The object to initialize this with
*/
IObjComponent::IObjComponent(const IObjComponent& origin)
{
// Handler contains a pointer to 'this' therefore needs regenerating
// with new object
handle = origin.handle->createInstance(this);
}
/**
* Copy constructor
* @param origin :: The object to initialize this with
*/
IObjComponent::IObjComponent(const IObjComponent& origin) :
m_ScaleFactor(origin.m_ScaleFactor)
/**
* Assignment operator
* @param rhs The rvalue to copy into this object
* @returns A reference to this object
*/
IObjComponent& IObjComponent::operator=(const IObjComponent& rhs)
{
if( &rhs != this )
{
// Handler contains a pointer to 'this' therefore needs regenerating
// with new object
handle = origin.handle->createInstance(this);
handle = rhs.handle->createInstance(this);
}
return *this;
}
/**
* Assignment operator
* @param rhs The rvalue to copy into this object
* @returns A reference to this object
*/
IObjComponent& IObjComponent::operator=(const IObjComponent& rhs)
{
if( &rhs != this )
{
m_ScaleFactor = rhs.m_ScaleFactor;
handle = rhs.handle->createInstance(this);
}
return *this;
}
} // namespace Geometry
} // namespace Geometry
} // namespace Mantid
......@@ -77,7 +77,7 @@ namespace Mantid
if (!shape()) return (this->getPos() == point);
// Otherwise pass through the shifted point to the Object::isValid method
V3D scaleFactor = V3D(1,1,1); //=this->getScaleFactorP();
V3D scaleFactor = this->getScaleFactor();
return shape()->isValid( factorOutComponentPosition(point) / scaleFactor )!=0;
}
......@@ -87,7 +87,7 @@ namespace Mantid
// If the form of this component is not defined, just treat as a point
if (!shape()) return (this->getPos() == point);
// Otherwise pass through the shifted point to the Object::isOnSide method
V3D scaleFactor = V3D(1,1,1); // = this->getScaleFactorP();
V3D scaleFactor = this->getScaleFactor();
return shape()->isOnSide( factorOutComponentPosition(point) / scaleFactor )!=0;
}
......@@ -114,12 +114,12 @@ namespace Mantid
V3D in = it->entryPoint;
this->getRotation().rotate(in);
//use the scale factor
in *= m_ScaleFactor;
in *= getScaleFactor();
in += this->getPos();
V3D out = it->exitPoint;
this->getRotation().rotate(out);
//use the scale factor
out *= m_ScaleFactor;
out *= getScaleFactor();
out += this->getPos();
track.addLink(in,out,out.distance(track.startPoint()),this->getComponentID());
}
......@@ -137,11 +137,16 @@ namespace Mantid
// If the form of this component is not defined, throw NullPointerException
if (!shape()) throw Kernel::Exception::NullPointerException("ObjComponent::solidAngle","shape");
// Otherwise pass through the shifted point to the Object::solidAngle method
V3D scaleFactor=this->getScaleFactorP();
V3D scaleFactor=this->getScaleFactor();
if((scaleFactor-V3D(1.0,1.0,1.0)).norm()<1e-12)
return shape()->solidAngle( factorOutComponentPosition(observer) );
else
return shape()->solidAngle( factorOutComponentPosition(observer)*scaleFactor, scaleFactor );
{
// This is the observer position in the shape's coordinate system.
V3D relativeObserver = factorOutComponentPosition(observer);
// This function will scale the object shape when calculating the solid angle.
return shape()->solidAngle( relativeObserver, scaleFactor );
}
}
/**
......@@ -167,8 +172,9 @@ namespace Mantid
min-=this->getPos();
max-=this->getPos();
// Scale
min/=m_ScaleFactor;
max/=m_ScaleFactor;
V3D scaleFactor = getScaleFactor();
min/=scaleFactor;
max/=scaleFactor;
//Rotation
Geometry::Quat inverse(this->getRotation());
......@@ -180,8 +186,8 @@ namespace Mantid
shape()->getBoundingBox(max[0],max[1],max[2],min[0],min[1],min[2]);
//Apply scale factor
min*=m_ScaleFactor;
max*=m_ScaleFactor;
min*=scaleFactor;
max*=scaleFactor;
// Re-rotate
(this->getRotation()).rotateBB(min[0],min[1],min[2],max[0],max[1],max[2]);
min+=this->getPos();
......@@ -204,13 +210,14 @@ namespace Mantid
absoluteBB = BoundingBox(shapeBox);
if ( shapeBox.isNull() ) return;
// modify in place for speed
V3D scaleFactor = getScaleFactor();
// Scale
absoluteBB.xMin() *= m_ScaleFactor.X();
absoluteBB.xMax() *= m_ScaleFactor.X();
absoluteBB.yMin() *= m_ScaleFactor.Y();
absoluteBB.yMax() *= m_ScaleFactor.Y();
absoluteBB.zMin() *= m_ScaleFactor.Z();
absoluteBB.zMax() *= m_ScaleFactor.Z();
absoluteBB.xMin() *= scaleFactor.X();
absoluteBB.xMax() *= scaleFactor.X();
absoluteBB.yMin() *= scaleFactor.Y();
absoluteBB.yMax() *= scaleFactor.Y();
absoluteBB.zMin() *= scaleFactor.Z();
absoluteBB.zMax() *= scaleFactor.Z();
// Rotate
(this->getRotation()).rotateBB(absoluteBB.xMin(),absoluteBB.yMin(),absoluteBB.zMin(),
absoluteBB.xMax(),absoluteBB.yMax(),absoluteBB.zMax());
......@@ -231,7 +238,7 @@ namespace Mantid
double ObjComponent::getHeight() const
{
const BoundingBox & bbox = shape()->getBoundingBox();
return (bbox.yMax() - bbox.yMin()) / m_ScaleFactor.Y();
return (bbox.yMax() - bbox.yMin()) / getScaleFactor().Y();
}
/**
......@@ -241,7 +248,7 @@ namespace Mantid
double ObjComponent::getWidth() const
{
const BoundingBox & bbox = shape()->getBoundingBox();
return ( bbox.xMax() - bbox.xMin() ) / m_ScaleFactor.X();
return ( bbox.xMax() - bbox.xMin() ) / getScaleFactor().X();
}
/**
......@@ -251,7 +258,7 @@ namespace Mantid
double ObjComponent::getDepth() const
{
const BoundingBox & bbox = shape()->getBoundingBox();
return ( bbox.zMax() - bbox.zMin() ) / m_ScaleFactor.Z();
return ( bbox.zMax() - bbox.zMin() ) / getScaleFactor().Z();
}
/**
......@@ -269,7 +276,7 @@ namespace Mantid
if(result)
{
//Scale up
V3D scaleFactor=this->getScaleFactorP();
V3D scaleFactor=this->getScaleFactor();
point*=scaleFactor;
Quat Rotate = this->getRotation();
Rotate.rotate(point);
......@@ -297,36 +304,12 @@ namespace Mantid
// Can not Consider scaling factor here as this transform used by solidAngle as well
// as IsValid etc. While this would work for latter, breaks former
//TODO: What is the answere here? ObjComponentTest needs these lines IN!
//Consider scaling factor
point/=m_ScaleFactor;
//point/=getScaleFactorP();
return point;
}
/** Get ScaleFactor of the object
* @returns A vector of the scale factors (1,1,1) if not set
*/
V3D ObjComponent::getScaleFactorP() const
{
if (m_isParametrized)
{
Parameter_sptr par = m_map->get(m_base,"sca");
if (par)
{
//Return the parametrized scaling
return par->value<V3D>();
}
}
//Not parametrized; or, no parameter for "sca" aka scale
return m_ScaleFactor;
}
/**
* Draws the objcomponent, If the handler is not set then this function does nothing.
*/
......
......@@ -844,7 +844,7 @@ namespace Mantid
}
/**
* Find soild angle of object wrt the observer with a scaleFactor for the object.
* Find solid angle of object wrt the observer with a scaleFactor for the object.
* @param observer :: point to measure solid angle from
* @param scaleFactor :: V3D giving scaling of the object
* @return :: estimate of solid angle of object. Accuracy depends on triangulation quality.
......@@ -1082,7 +1082,7 @@ namespace Mantid
* OC triangluation of the object, if it exists. This method expects a
* scaling vector scaleFactor that scales the three axes.
*
* @param observer :: Point from which solid angle is required - THIS MUST NOT BE SCALED
* @param observer :: Point from which solid angle is required.
* @param scaleFactor :: V3D each component giving the scaling of the object only (not observer)
* @return the solid angle
*/
......@@ -1094,7 +1094,7 @@ namespace Mantid
// with the triangle based method. Hence catch these two (unlikely) cases.
const BoundingBox & boundingBox = this->getBoundingBox();
double sx = scaleFactor[0], sy = scaleFactor[1], sz = scaleFactor[2];
V3D sObserver = observer / scaleFactor;
V3D sObserver = observer;
if( boundingBox.isNonNull() && boundingBox.isPointInside(sObserver) )
{
if (isValid(sObserver))
......@@ -1666,7 +1666,7 @@ namespace Mantid
/**
Try to find a point that lies within (or on) the object
@param point :: on exit set to the point value, if found
@param[out] point :: on exit set to the point value, if found
@return 1 if point found, 0 otherwise
*/
int Object::getPointInObject(Geometry::V3D& point) const
......
......@@ -280,79 +280,83 @@ public:
TS_ASSERT_DELTA(point.Z(),-31.5,1e-6);
}
ObjComponent * MakeWithScaleFactor(ObjComponent * parent, double X, double Y, double Z)
{
ParameterMap * map = new ParameterMap;
ObjComponent * ret = new ObjComponent(parent, map);
map->addV3D(ret, "sca", V3D(X,Y,Z));
return ret;
}
void testIsValidWithScaleFactor()
{
ObjComponent ocyl("ocyl", createCappedCylinder());
//set the scale factor
ocyl.setScaleFactor(2.0,1.0,1.0);
TS_ASSERT(ocyl.isValid(V3D(2.4,0.0,0.0)));
TS_ASSERT(ocyl.isValid(V3D(-6.4,0.0,0.0)));
TS_ASSERT(!ocyl.isValid(V3D(2.5,0.0,0.0)));
TS_ASSERT(!ocyl.isValid(V3D(-6.5,0.0,0.0)));
TS_ASSERT(ocyl.isValid(V3D(2.3,0.0,0.0)));
TS_ASSERT(ocyl.isValid(V3D(-6.3,0.0,0.0)));
ObjComponent * ocyl_base = new ObjComponent("ocyl", createCappedCylinder());
ObjComponent * ocyl = MakeWithScaleFactor(ocyl_base, 2.0,1.0,1.0);
TS_ASSERT(ocyl->isValid(V3D(2.4,0.0,0.0)));
TS_ASSERT(ocyl->isValid(V3D(-6.4,0.0,0.0)));
TS_ASSERT(!ocyl->isValid(V3D(2.5,0.0,0.0)));
TS_ASSERT(!ocyl->isValid(V3D(-6.5,0.0,0.0)));
TS_ASSERT(ocyl->isValid(V3D(2.3,0.0,0.0)));
TS_ASSERT(ocyl->isValid(V3D(-6.3,0.0,0.0)));
}
void testIsOnSideWithScaleFactor()
{
ObjComponent ocyl("ocyl", createCappedCylinder());
//set the scale factor
ocyl.setScaleFactor(2.0,1.0,1.0);
TS_ASSERT(ocyl.isOnSide(V3D(2.4,0.0,0.0)));
TS_ASSERT(ocyl.isOnSide(V3D(-6.4,0.0,0.0)));
TS_ASSERT(!ocyl.isOnSide(V3D(2.5,0.0,0.0)));
TS_ASSERT(!ocyl.isOnSide(V3D(-6.5,0.0,0.0)));
TS_ASSERT(!ocyl.isOnSide(V3D(2.3,0.0,0.0)));
TS_ASSERT(!ocyl.isOnSide(V3D(-6.3,0.0,0.0)));
ObjComponent * ocyl_base = new ObjComponent("ocyl", createCappedCylinder());
ObjComponent * ocyl = MakeWithScaleFactor(ocyl_base, 2.0,1.0,1.0);
TS_ASSERT(ocyl->isOnSide(V3D(2.4,0.0,0.0)));
TS_ASSERT(ocyl->isOnSide(V3D(-6.4,0.0,0.0)));
TS_ASSERT(!ocyl->isOnSide(V3D(2.5,0.0,0.0)));
TS_ASSERT(!ocyl->isOnSide(V3D(-6.5,0.0,0.0)));
TS_ASSERT(!ocyl->isOnSide(V3D(2.3,0.0,0.0)));
TS_ASSERT(!ocyl->isOnSide(V3D(-6.3,0.0,0.0)));
}
void testIntercepSurfaceWithScaleFactor()
void testInterceptSurfaceWithScaleFactor()
{
ObjComponent ocyl("ocyl", createCappedCylinder());
//set the scale factor
ocyl.setScaleFactor(2.0,1.0,1.0);
ObjComponent * ocyl_base = new ObjComponent("ocyl", createCappedCylinder());
ObjComponent * ocyl = MakeWithScaleFactor(ocyl_base, 2.0,1.0,3.0);
Track trackScale(V3D(-6.5,0,0),V3D(1.0,0,0));
TS_ASSERT_EQUALS( ocyl.interceptSurface(trackScale), 1 );
TS_ASSERT_EQUALS( ocyl->interceptSurface(trackScale), 1 );
Track::LType::const_iterator itscale=trackScale.begin();
TS_ASSERT_EQUALS(itscale->distFromStart, 8.9);
TS_ASSERT_EQUALS(itscale->entryPoint, V3D(-6.4,0.0,0.0));
TS_ASSERT_EQUALS(itscale->exitPoint, V3D( 2.4,0.0,0.0));
Track trackScaleY(V3D(-6.0,-1,0),V3D(0,1.0,0));
TS_ASSERT_EQUALS( ocyl.interceptSurface(trackScaleY), 1 );
Track trackScaleY(V3D(0.0,-2,0),V3D(0,2.0,0));
TS_ASSERT_EQUALS( ocyl->interceptSurface(trackScaleY), 1 );
Track::LType::const_iterator itscaleY=trackScaleY.begin();
TS_ASSERT_EQUALS(itscaleY->distFromStart, 1.5);
TS_ASSERT_EQUALS(itscaleY->entryPoint, V3D(-6.0,-0.5,0.0));
TS_ASSERT_EQUALS(itscaleY->exitPoint, V3D(-6.0, 0.5,0.0));
TS_ASSERT_EQUALS(itscaleY->distFromStart, 2.5);
TS_ASSERT_EQUALS(itscaleY->entryPoint, V3D(0.0,-0.5,0.0));
TS_ASSERT_EQUALS(itscaleY->exitPoint, V3D(0.0, 0.5,0.0));
Track trackScaleW(V3D(-6.0,-1.5,0),V3D(1.0,1.0,0));
TS_ASSERT_EQUALS( ocyl.interceptSurface(trackScaleW), 1 );
Track trackScaleW(V3D(0,0,-5),V3D(0,0,5));
TS_ASSERT_EQUALS( ocyl->interceptSurface(trackScaleW), 1 );
Track::LType::const_iterator itscaleW=trackScaleW.begin();
TS_ASSERT_DELTA(itscaleW->distFromStart, 2.828427, 1e-6);
TS_ASSERT_EQUALS(itscaleW->entryPoint, V3D(-5.0,-0.5,0.0));
TS_ASSERT_EQUALS(itscaleW->exitPoint, V3D(-4.0, 0.5,0.0));
TS_ASSERT_DELTA(itscaleW->distFromStart, 6.5, 1e-6);
TS_ASSERT_EQUALS(itscaleW->entryPoint, V3D(0,0,-1.5));
TS_ASSERT_EQUALS(itscaleW->exitPoint, V3D(0,0,+1.5));
}
void testBoundingBoxWithScaleFactor()
{
ObjComponent A("ocyl", createCappedCylinder());
//set the scale factor
A.setScaleFactor(2.0,1.0,1.0);
ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder());
ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0);
double xmax,ymax,zmax,xmin,ymin,zmin;
xmax=100; ymax=100; zmax=100;
xmin=-100; ymin=-100; zmin=-100;
A.getBoundingBox(xmax,ymax,zmax,xmin,ymin,zmin);
A->getBoundingBox(xmax,ymax,zmax,xmin,ymin,zmin);
TS_ASSERT_DELTA(xmax, 2.4,0.00001);
TS_ASSERT_DELTA(xmin,-6.4,0.00001);
}
void testPointInObjectWithScaleFactor()
{
ObjComponent A("ocyl", createCappedCylinder());
//set the scale factor
ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder());
ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0);
V3D scalept;
A.setScaleFactor(2.0,1.0,1.0);
TS_ASSERT_EQUALS(A.getPointInObject(scalept),1);
TS_ASSERT_EQUALS(A->getPointInObject(scalept),1);
TS_ASSERT_DELTA(scalept.X(),0.0,1e-6);
TS_ASSERT_DELTA(scalept.Y(),0.0,1e-6);
TS_ASSERT_DELTA(scalept.Z(),0.0,1e-6);
......@@ -360,44 +364,53 @@ public:
void testPointInObjectWithScaleFactor2()
{
ObjComponent A("ocyl", createCappedCylinder2());
//set the scale factor
V3D scalept;
A.setRot(Quat(90.0,V3D(0,0,1)));
A.setScaleFactor(2.0,1.0,1.0);
TS_ASSERT_EQUALS(A.getPointInObject(scalept),1);
ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder());
A_base->setRot(Quat(90.0,V3D(0,0,1)));
ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0);
V3D scalept(0,0,0);
TS_ASSERT_EQUALS(A->getPointInObject(scalept),1);
TS_ASSERT_DELTA(scalept.X(), 0.0,1e-6);
TS_ASSERT_DELTA(scalept.Y(),-2.0,1e-6);
TS_ASSERT_DELTA(scalept.Y(), 0.0,1e-6);
TS_ASSERT_DELTA(scalept.Z(), 0.0,1e-6);
}
void testPointInObjectWithScaleFactorAndWithOffset()
{
ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder());
A_base->setPos(10,0,0);
ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0);
V3D scalept(0,0,0);
TS_ASSERT_EQUALS(A->getPointInObject(scalept),1);
TS_ASSERT_DELTA(scalept.X(), 10.0,1e-6);
TS_ASSERT_DELTA(scalept.Y(), 0.0,1e-6);
TS_ASSERT_DELTA(scalept.Z(), 0.0,1e-6);
}
void testSolidAngleCappedCylinderWithScaleFactor()
{
ObjComponent A("ocyl", createCappedCylinder());
ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder());
ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0);
A.setScaleFactor(2.0,1.0,1.0);
A.setPos(10,0,0);
A.setRot(Quat(90.0,V3D(0,0,1)));
A_base->setPos(10,0,0);
A_base->setRot(Quat(90.0,V3D(0,0,1)));