- IFC: IfcTrimmingCurve sampling code now supports trimming by points rather than by parameter values.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1052 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/2/head
parent
56a5230d3a
commit
409eb6cee7
|
@ -80,11 +80,14 @@ public:
|
||||||
bool IsClosed() const {
|
bool IsClosed() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
size_t EstimateSampleCount(float a, float b) const {
|
size_t EstimateSampleCount(float a, float b) const {
|
||||||
ai_assert(InRange(a) && InRange(b));
|
ai_assert(InRange(a) && InRange(b));
|
||||||
return static_cast<size_t>( ceil((b-a) / conv.settings.conicSamplingAngle) );
|
|
||||||
|
a = fmod(a,360.f);
|
||||||
|
b = fmod(b,360.f);
|
||||||
|
return static_cast<size_t>( fabs(ceil(( b-a)) / conv.settings.conicSamplingAngle) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
@ -340,6 +343,7 @@ public:
|
||||||
TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
|
TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
|
||||||
: BoundedCurve(entity,conv)
|
: BoundedCurve(entity,conv)
|
||||||
, entity(entity)
|
, entity(entity)
|
||||||
|
, ok()
|
||||||
{
|
{
|
||||||
base = boost::shared_ptr<const Curve>(Curve::Convert(entity.BasisCurve,conv));
|
base = boost::shared_ptr<const Curve>(Curve::Convert(entity.BasisCurve,conv));
|
||||||
|
|
||||||
|
@ -350,34 +354,39 @@ public:
|
||||||
// two representations they prefer, even though an information invariant
|
// two representations they prefer, even though an information invariant
|
||||||
// claims that they must be identical if both are present.
|
// claims that they must be identical if both are present.
|
||||||
// oh well.
|
// oh well.
|
||||||
bool ok = false;
|
bool have_param = false, have_point = false;
|
||||||
|
aiVector3D point;
|
||||||
BOOST_FOREACH(const Entry sel,entity.Trim1) {
|
BOOST_FOREACH(const Entry sel,entity.Trim1) {
|
||||||
if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
|
if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
|
||||||
range.first = *r;
|
range.first = *r;
|
||||||
ok = true;
|
have_param = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
|
||||||
if (!ok) {
|
ConvertCartesianPoint(point,*r);
|
||||||
IFCImporter::LogError("trimming by curve points not currently supported, skipping first cut point");
|
have_point = true;
|
||||||
range.first = base->GetParametricRange().first;
|
|
||||||
if (range.first == std::numeric_limits<float>::infinity()) {
|
|
||||||
range.first = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok = false;
|
if (!have_param) {
|
||||||
|
if (!have_point || !base->ReverseEval(point,range.first)) {
|
||||||
|
throw CurveError("IfcTrimmedCurve: failed to read first trim parameter, ignoring curve");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
have_param = false, have_point = false;
|
||||||
BOOST_FOREACH(const Entry sel,entity.Trim2) {
|
BOOST_FOREACH(const Entry sel,entity.Trim2) {
|
||||||
if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
|
if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
|
||||||
range.second = *r;
|
range.second = *r;
|
||||||
ok = true;
|
have_param = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
|
||||||
|
ConvertCartesianPoint(point,*r);
|
||||||
|
have_point = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!have_param) {
|
||||||
IFCImporter::LogError("trimming by curve points not currently supported, skipping second cut point");
|
if (!have_point || !base->ReverseEval(point,range.second)) {
|
||||||
range.second = base->GetParametricRange().second;
|
throw CurveError("IfcTrimmedCurve: failed to read second trim parameter, ignoring curve");
|
||||||
if (range.second == std::numeric_limits<float>::infinity()) {
|
|
||||||
range.second = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +439,7 @@ private:
|
||||||
ParamRange range;
|
ParamRange range;
|
||||||
float maxval;
|
float maxval;
|
||||||
bool agree_sense;
|
bool agree_sense;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
boost::shared_ptr<const Curve> base;
|
boost::shared_ptr<const Curve> base;
|
||||||
};
|
};
|
||||||
|
@ -556,6 +566,67 @@ size_t Curve :: EstimateSampleCount(float a, float b) const
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
float RecursiveSearch(const Curve* cv, const aiVector3D& val, float a, float b, unsigned int samples, float treshold, unsigned int recurse = 0, unsigned int max_recurse = 15)
|
||||||
|
{
|
||||||
|
ai_assert(samples>1);
|
||||||
|
|
||||||
|
const float delta = (b-a)/samples, inf = std::numeric_limits<float>::infinity();
|
||||||
|
float min_point[2] = {a,b}, min_diff[2] = {inf,inf};
|
||||||
|
float runner = a;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < samples; ++i, runner += delta) {
|
||||||
|
const float diff = (cv->Eval(runner)-val).SquareLength();
|
||||||
|
if (diff < min_diff[0]) {
|
||||||
|
min_diff[1] = min_diff[0];
|
||||||
|
min_point[1] = min_point[0];
|
||||||
|
|
||||||
|
min_diff[0] = diff;
|
||||||
|
min_point[0] = runner;
|
||||||
|
}
|
||||||
|
else if (diff < min_diff[1]) {
|
||||||
|
min_diff[1] = diff;
|
||||||
|
min_point[1] = runner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ai_assert(min_diff[0] != inf && min_diff[1] != inf);
|
||||||
|
if ( fabs(a-min_point[0]) < treshold || recurse >= max_recurse) {
|
||||||
|
return min_point[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix for closed curves to take their wrap-over into account
|
||||||
|
if (cv->IsClosed() && fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5 ) {
|
||||||
|
const Curve::ParamRange& range = cv->GetParametricRange();
|
||||||
|
const float wrapdiff = (cv->Eval(range.first)-val).SquareLength();
|
||||||
|
|
||||||
|
if (wrapdiff < min_diff[0]) {
|
||||||
|
const float t = min_point[0];
|
||||||
|
min_point[0] = min_point[1] > min_point[0] ? range.first : range.second;
|
||||||
|
min_point[1] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RecursiveSearch(cv,val,min_point[0],min_point[1],samples,treshold,recurse+1,max_recurse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
bool Curve :: ReverseEval(const aiVector3D& val, float& paramOut) const
|
||||||
|
{
|
||||||
|
// note: the following algorithm is not guaranteed to find the 'right' parameter value
|
||||||
|
// in all possible cases, but it will always return at least some value so this function
|
||||||
|
// will never fail in the default implementation.
|
||||||
|
|
||||||
|
// XXX derive treshold from curve topology
|
||||||
|
const float treshold = 1e-4;
|
||||||
|
const unsigned int samples = 16;
|
||||||
|
|
||||||
|
const ParamRange& range = GetParametricRange();
|
||||||
|
paramOut = RecursiveSearch(this,val,range.first,range.second,samples,treshold);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Curve :: SampleDiscrete(TempMesh& out,float a, float b) const
|
void Curve :: SampleDiscrete(TempMesh& out,float a, float b) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,7 +73,13 @@ bool ProcessCurve(const IfcCurve& curve, TempMesh& meshout, ConversionData& con
|
||||||
|
|
||||||
// we must have a bounded curve at this point
|
// we must have a bounded curve at this point
|
||||||
if (const BoundedCurve* bc = dynamic_cast<const BoundedCurve*>(cv.get())) {
|
if (const BoundedCurve* bc = dynamic_cast<const BoundedCurve*>(cv.get())) {
|
||||||
bc->SampleDiscrete(meshout);
|
try {
|
||||||
|
bc->SampleDiscrete(meshout);
|
||||||
|
}
|
||||||
|
catch(const CurveError& cv) {
|
||||||
|
IFCImporter::LogError(cv.s+ " (error occurred while processing curve)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
meshout.vertcnt.push_back(meshout.verts.size());
|
meshout.vertcnt.push_back(meshout.verts.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,21 @@ void AssignAddedMeshes(std::vector<unsigned int>& mesh_indices,aiNode* nd,Conver
|
||||||
|
|
||||||
// IFCCurve.cpp
|
// IFCCurve.cpp
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Custom exception for use by members of the Curve class
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
class CurveError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CurveError(const std::string& s)
|
||||||
|
: s(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Temporary representation for an arbitrary sub-class of IfcCurve. Used to sample the curves
|
// Temporary representation for an arbitrary sub-class of IfcCurve. Used to sample the curves
|
||||||
// to obtain a list of line segments.
|
// to obtain a list of line segments.
|
||||||
|
@ -219,6 +234,11 @@ public:
|
||||||
// evaluate the curve at the given parametric position
|
// evaluate the curve at the given parametric position
|
||||||
virtual aiVector3D Eval(float p) const = 0;
|
virtual aiVector3D Eval(float p) const = 0;
|
||||||
|
|
||||||
|
// try to match a point on the curve to a given parameter
|
||||||
|
// for self-intersecting curves, the result is not ambiguous and
|
||||||
|
// it is undefined which parameter is returned.
|
||||||
|
virtual bool ReverseEval(const aiVector3D& val, float& paramOut) const;
|
||||||
|
|
||||||
// get the range of the curve (both inclusive).
|
// get the range of the curve (both inclusive).
|
||||||
// +inf and -inf are valid return values, the curve is not bounded in such a case.
|
// +inf and -inf are valid return values, the curve is not bounded in such a case.
|
||||||
virtual std::pair<float,float> GetParametricRange() const = 0;
|
virtual std::pair<float,float> GetParametricRange() const = 0;
|
||||||
|
|
Loading…
Reference in New Issue