/*
* Copyright (C) 2008-2012 Thorsten Liebig (Thorsten.Liebig@gmx.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include "tinyxml.h"
#include "stdint.h"
#include "CSPrimUserDefined.h"
#include "CSProperties.h"
#include "CSFunctionParser.h"
#include "CSUseful.h"
CSPrimUserDefined::CSPrimUserDefined(unsigned int ID, ParameterSet* paraSet, CSProperties* prop) : CSPrimitives(ID,paraSet,prop)
{
Type=USERDEFINED;
fParse = new CSFunctionParser();
stFunction = std::string();
CoordSystem=CARESIAN_SYSTEM;
for (int i=0;i<3;++i) {dPosShift[i].SetParameterSet(paraSet);}
PrimTypeName = std::string("User-Defined");
}
CSPrimUserDefined::CSPrimUserDefined(CSPrimUserDefined* primUDef, CSProperties *prop) : CSPrimitives(primUDef,prop)
{
Type=USERDEFINED;
fParse = new CSFunctionParser(*primUDef->fParse);
stFunction = std::string(primUDef->stFunction);
CoordSystem = primUDef->CoordSystem;
for (int i=0;i<3;++i)
dPosShift[i].Copy(&primUDef->dPosShift[i]);
PrimTypeName = std::string("User-Defined");
}
CSPrimUserDefined::CSPrimUserDefined(ParameterSet* paraSet, CSProperties* prop) : CSPrimitives(paraSet,prop)
{
Type=USERDEFINED;
fParse = new CSFunctionParser();
stFunction = std::string();
CoordSystem=CARESIAN_SYSTEM;
for (int i=0;i<3;++i)
dPosShift[i].SetParameterSet(paraSet);
PrimTypeName = std::string("User-Defined");
}
CSPrimUserDefined::~CSPrimUserDefined()
{
delete fParse;fParse=NULL;
}
void CSPrimUserDefined::SetCoordSystem(UserDefinedCoordSystem newSystem)
{
CoordSystem=newSystem;
}
void CSPrimUserDefined::SetFunction(const char* func)
{
if (func==NULL) return;
stFunction = std::string(func);
}
bool CSPrimUserDefined::GetBoundBox(double dBoundBox[6], bool PreserveOrientation)
{
UNUSED(PreserveOrientation); //has no orientation or preserved anyways
//this type has no simple bound box
double max=std::numeric_limits::max();
dBoundBox[0]=dBoundBox[2]=dBoundBox[4]=-max;
dBoundBox[1]=dBoundBox[3]=dBoundBox[5]=max;
bool accurate=false;
return accurate;
}
bool CSPrimUserDefined::IsInside(const double* Coord, double /*tol*/)
{
if (Coord==NULL) return false;
int NrPara=clParaSet->GetQtyParameter();
if (NrPara!=iQtyParameter) return false;
double *vars = new double[NrPara+6];
vars=clParaSet->GetValueArray(vars);
double inCoord[3] = {Coord[0],Coord[1],Coord[2]};
//transform incoming coordinates into cartesian coords
TransformCoordSystem(Coord,inCoord,m_MeshType,CARTESIAN);
if (m_Transform)
m_Transform->InvertTransform(inCoord,inCoord);
double x=inCoord[0]-dPosShift[0].GetValue();
double y=inCoord[1]-dPosShift[1].GetValue();
double z=inCoord[2]-dPosShift[2].GetValue();
double rxy=sqrt(x*x+y*y);
vars[NrPara]=x;
vars[NrPara+1]=y;
vars[NrPara+2]=z;
switch (CoordSystem)
{
case CARESIAN_SYSTEM: //uses x,y,z
vars[NrPara+3]=0;
vars[NrPara+4]=0;
vars[NrPara+5]=0; break;
case CYLINDER_SYSTEM: //uses x,y,z,r,a,0
vars[NrPara+3]=rxy;
vars[NrPara+4]=atan2(y,x);
vars[NrPara+5]=0;
break;
case SPHERE_SYSTEM: //uses x,y,z,r,a,t
vars[NrPara+3]=sqrt(x*x+y*y+z*z);
vars[NrPara+4]=atan2(y,x);
vars[NrPara+5]=asin(1)-atan(z/rxy);
//cout << "x::" << x << "y::" << y << "z::" << z << "r::" << vars[NrPara] << "a::" << vars[NrPara+1] << "t::" << vars[NrPara+2] << std::endl;
break;
default:
//unknown System
return false;
break;
}
double dValue=0;
if (fParse->GetParseErrorType()==FunctionParser::FP_NO_ERROR) dValue=fParse->Eval(vars);
else dValue=0;
delete[] vars;vars=NULL;
if (dValue==1)
return true;
return false;
}
bool CSPrimUserDefined::Update(std::string *ErrStr)
{
int EC=0;
bool bOK=true;
std::string vars;
switch (CoordSystem)
{
case CARESIAN_SYSTEM:
vars=std::string("x,y,z");
break;
case CYLINDER_SYSTEM:
vars=std::string("x,y,z,r,a");
break;
case SPHERE_SYSTEM:
vars=std::string("x,y,z,r,a,t");
break;
default:
//unknown System
return false;
break;
}
iQtyParameter=clParaSet->GetQtyParameter();
if (iQtyParameter>0)
{
fParameter=std::string(clParaSet->GetParameterString());
vars = fParameter + "," + vars;
}
fParse->Parse(stFunction,vars);
EC=fParse->GetParseErrorType();
//cout << fParse.ErrorMsg();
if (EC!=FunctionParser::FP_NO_ERROR) bOK=false;
if ((EC!=FunctionParser::FP_NO_ERROR) && (ErrStr!=NULL))
{
std::ostringstream oss;
oss << "\nError in User Defined Primitive Function (ID: " << uiID << "): " << fParse->ErrorMsg();
ErrStr->append(oss.str());
bOK=false;
}
for (int i=0;i<3;++i)
{
EC=dPosShift[i].Evaluate();
if (EC!=ParameterScalar::NO_ERROR) bOK=false;
if ((EC!=ParameterScalar::NO_ERROR) && (ErrStr!=NULL))
{
bOK=false;
std::ostringstream oss;
oss << "\nError in User Defined Primitive Coord (ID: " << uiID << "): ";
ErrStr->append(oss.str());
PSErrorCode2Msg(EC,ErrStr);
}
}
//update local bounding box
m_BoundBoxValid = GetBoundBox(m_BoundBox);
return bOK;
}
bool CSPrimUserDefined::Write2XML(TiXmlElement &elem, bool parameterised)
{
CSPrimitives::Write2XML(elem,parameterised);
elem.SetAttribute("CoordSystem",CoordSystem);
TiXmlElement P1("CoordShift");
WriteTerm(dPosShift[0],P1,"X",parameterised);
WriteTerm(dPosShift[1],P1,"Y",parameterised);
WriteTerm(dPosShift[2],P1,"Z",parameterised);
elem.InsertEndChild(P1);
TiXmlElement FuncElem("Function");
TiXmlText FuncText(GetFunction());
FuncElem.InsertEndChild(FuncText);
elem.InsertEndChild(FuncElem);
return true;
}
bool CSPrimUserDefined::ReadFromXML(TiXmlNode &root)
{
if (CSPrimitives::ReadFromXML(root)==false) return false;
int value;
TiXmlElement* elem=root.ToElement();
if (elem==NULL) return false;
if (elem->QueryIntAttribute("CoordSystem",&value)!=TIXML_SUCCESS) return false;
SetCoordSystem((UserDefinedCoordSystem)value);
//P1
TiXmlElement* P1=root.FirstChildElement("CoordShift");
if (P1==NULL) return false;
if (ReadTerm(dPosShift[0],*P1,"X")==false) return false;
if (ReadTerm(dPosShift[1],*P1,"Y")==false) return false;
if (ReadTerm(dPosShift[2],*P1,"Z")==false) return false;
TiXmlElement* FuncElem=root.FirstChildElement("Function");
if (FuncElem==NULL) return false;
SetFunction(FuncElem->GetText());
return true;
}