Skip to content

Commit

Permalink
Refs #7971 - Allow default centre for Sphere shapes.
Browse files Browse the repository at this point in the history
Plus add unit test.
  • Loading branch information
PeterParker committed Oct 9, 2013
1 parent bd54999 commit 3cc0ff3
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ namespace Mantid
std::string parseSliceOfCylinderRing(Poco::XML::Element* pElem, std::map<int, Surface*>& prim, int& l_id);

Poco::XML::Element* getShapeElement(Poco::XML::Element* pElem, const std::string& name);
Poco::XML::Element* getOptionalShapeElement(Poco::XML::Element* pElem, const std::string& name);
double getDoubleAttribute(Poco::XML::Element* pElem, const std::string& name);
Kernel::V3D parsePosition(Poco::XML::Element* pElem);
void createGeometryHandler(Poco::XML::Element*,boost::shared_ptr<Object>);
Expand Down
39 changes: 35 additions & 4 deletions Code/Mantid/Framework/Geometry/src/Objects/ShapeFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,15 +332,18 @@ boost::shared_ptr<Object> ShapeFactory::createShape(Poco::XML::Element* pElem)
*/
std::string ShapeFactory::parseSphere(Poco::XML::Element* pElem, std::map<int, Surface*>& prim, int& l_id)
{
Element* pElemCentre = getShapeElement(pElem, "centre");
Element* pElemCentre = getOptionalShapeElement(pElem, "centre");
Element* pElemRadius = getShapeElement(pElem, "radius");

// getDoubleAttribute can throw - put the calls above any new
const double radius = getDoubleAttribute(pElemRadius,"val");

// create sphere
Sphere* pSphere = new Sphere;
pSphere->setCentre(parsePosition(pElemCentre));
if( pElemCentre )
pSphere->setCentre(parsePosition(pElemCentre));
else
pSphere->setCentre(V3D(0, 0, 0));
pSphere->setRadius(radius);
prim[l_id] = pSphere;

Expand Down Expand Up @@ -942,6 +945,31 @@ Poco::XML::Element* ShapeFactory::getShapeElement(Poco::XML::Element* pElem, con
}


/**
* Return a subelement of an XML element. The subelement is optional so it may not exist, but
* we also check that there is never more than one.
*
* @param pElem :: XML from instrument definition file.
* @param name :: Name of the subelement.
* @return The subelement, or a null pointer if it does not exist.
*
* @throw std::invalid_argument if XML string is invalid.
*/
Poco::XML::Element* ShapeFactory::getOptionalShapeElement(Poco::XML::Element* pElem, const std::string& name)
{
// Allow zero or one occurances of subelements with the given name.
Poco::AutoPtr<NodeList> pNL = pElem->getElementsByTagName(name);
if ( pNL->length() == 0)
return NULL;
else if ( pNL->length() > 1)
throw std::invalid_argument("XML element: <" + pElem->tagName() +
"> may contain at most one sub-element with name: <" + name + ">.");

Element* retVal = static_cast<Element*>(pNL->item(0));
return retVal;
}


/** Return value of attribute to XML element. It is an extension of poco's getAttribute method, which
* in addition check that this attribute exists and if not throws an error.
*
Expand Down Expand Up @@ -1037,9 +1065,12 @@ void ShapeFactory::createGeometryHandler(Poco::XML::Element* pElem,boost::shared
{
boost::shared_ptr<GeometryHandler> handler(new GluGeometryHandler(Obj));
Obj->setGeometryHandler(handler);
Element* pElemCentre = getShapeElement(pElem, "centre");
Element* pElemCentre = getOptionalShapeElement(pElem, "centre");
Element* pElemRadius = getShapeElement(pElem, "radius");
((GluGeometryHandler*)(handler.get()))->setSphere(parsePosition(pElemCentre),atof( (pElemRadius->getAttribute("val")).c_str() ));
V3D centre;
if( pElemCentre )
centre = parsePosition(pElemCentre);
((GluGeometryHandler*)(handler.get()))->setSphere(centre,atof( (pElemRadius->getAttribute("val")).c_str() ));
}
else if(pElem->tagName()=="cylinder")
{
Expand Down
24 changes: 24 additions & 0 deletions Code/Mantid/Framework/Geometry/test/ShapeFactoryTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,30 @@ class ShapeFactoryTest : public CxxTest::TestSuite
TS_ASSERT( !shape_sptr->isValid(V3D(7.1,2.1,9.1)) );
}

void testSphereWithDefaultCentre()
{
std::string xmlShape = "<sphere id=\"shape\"> ";
xmlShape += "<radius val=\"1.0\" /> " ;
xmlShape += "</sphere>";
xmlShape += "<algebra val=\"shape\" /> ";

boost::shared_ptr<Object> shape_sptr = getObject(xmlShape);

TS_ASSERT( shape_sptr->isValid(V3D( 1.0, 0.0, 0.0)) );
TS_ASSERT( shape_sptr->isValid(V3D( 0.0, 1.0, 0.0)) );
TS_ASSERT( shape_sptr->isValid(V3D( 0.0, 0.0, 1.0)) );
TS_ASSERT( shape_sptr->isValid(V3D(-1.0, 0.0, 0.0)) );
TS_ASSERT( shape_sptr->isValid(V3D( 0.0,-1.0, 0.0)) );
TS_ASSERT( shape_sptr->isValid(V3D( 0.0, 0.0,-1.0)) );

TS_ASSERT( !shape_sptr->isValid(V3D( 1.1, 0.0, 0.0)) );
TS_ASSERT( !shape_sptr->isValid(V3D( 0.0, 1.1, 0.0)) );
TS_ASSERT( !shape_sptr->isValid(V3D( 0.0, 0.0, 1.1)) );
TS_ASSERT( !shape_sptr->isValid(V3D(-1.1, 0.0, 0.0)) );
TS_ASSERT( !shape_sptr->isValid(V3D( 0.0,-1.1, 0.0)) );
TS_ASSERT( !shape_sptr->isValid(V3D( 0.0, 0.0,-1.1)) );
}

void testCylinder()
{
//algebra line is essential
Expand Down

0 comments on commit 3cc0ff3

Please sign in to comment.