38 QDomElement rulesElem = elem.firstChildElement( QStringLiteral(
"rules" ) );
57 , mFilterExp( filterExp )
58 , mDescription( description )
59 , mElseRule( elseRule )
67 qDeleteAll( mChildren );
73 if ( mSymbol.get() == symbol )
76 mSymbol.reset( symbol );
82 for (
Rule *
c : mChildren )
85 l +=
c->descendants();
90 void QgsRuleBased3DRenderer::Rule::initFilter()
92 if ( mElseRule || mFilterExp.compare( QLatin1String(
"ELSE" ), Qt::CaseInsensitive ) == 0 )
95 mFilter.reset(
nullptr );
97 else if ( !mFilterExp.isEmpty() )
103 mFilter.reset(
nullptr );
107 void QgsRuleBased3DRenderer::Rule::updateElseRules()
110 for ( Rule *rule : std::as_const( mChildren ) )
112 if ( rule->isElse() )
120 mChildren.append( rule );
121 rule->mParent =
this;
127 mChildren.insert( i, rule );
128 rule->mParent =
this;
134 delete mChildren.at( i );
135 mChildren.removeAt( i );
143 if ( key == mRuleKey )
146 for (
Rule *rule : std::as_const( mChildren ) )
157 if ( key == mRuleKey )
160 for (
Rule *rule : std::as_const( mChildren ) )
172 Rule *newrule =
new Rule( symbol, mFilterExp, mDescription );
175 for (
Rule *rule : std::as_const( mChildren ) )
183 QDomElement elemSymbol = ruleElem.firstChildElement( QStringLiteral(
"symbol" ) );
184 if ( !elemSymbol.isNull() )
186 QString symbolType = elemSymbol.attribute( QStringLiteral(
"type" ) );
189 symbol->
readXml( elemSymbol, context );
192 QString filterExp = ruleElem.attribute( QStringLiteral(
"filter" ) );
193 QString description = ruleElem.attribute( QStringLiteral(
"description" ) );
194 QString ruleKey = ruleElem.attribute( QStringLiteral(
"key" ) );
195 Rule *rule =
new Rule( symbol, filterExp, description );
197 if ( !ruleKey.isEmpty() )
198 rule->mRuleKey = ruleKey;
200 rule->
setActive( ruleElem.attribute( QStringLiteral(
"active" ), QStringLiteral(
"1" ) ).toInt() );
202 QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral(
"rule" ) );
203 while ( !childRuleElem.isNull() )
205 Rule *childRule = create( childRuleElem, context );
214 childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral(
"rule" ) );
222 QDomElement ruleElem = doc.createElement( QStringLiteral(
"rule" ) );
226 QDomElement elemSymbol = doc.createElement( QStringLiteral(
"symbol" ) );
227 elemSymbol.setAttribute( QStringLiteral(
"type" ), mSymbol->type() );
228 mSymbol->writeXml( elemSymbol, context );
229 ruleElem.appendChild( elemSymbol );
232 if ( !mFilterExp.isEmpty() )
233 ruleElem.setAttribute( QStringLiteral(
"filter" ), mFilterExp );
234 if ( !mDescription.isEmpty() )
235 ruleElem.setAttribute( QStringLiteral(
"description" ), mDescription );
237 ruleElem.setAttribute( QStringLiteral(
"active" ), 0 );
238 ruleElem.setAttribute( QStringLiteral(
"key" ), mRuleKey );
240 for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
254 Q_ASSERT( !handlers.value(
this ) );
257 handlers[
this] = handler;
261 for (
Rule *rule : std::as_const( mChildren ) )
263 rule->createHandlers(
layer, handlers );
272 QgsFeature3DHandler *handler = handlers[
this];
273 if ( !handler->prepare( context, attributeNames ) )
275 handlers.remove(
this );
282 attributeNames.unite( mFilter->referencedColumns() );
283 mFilter->prepare( &context.expressionContext() );
287 for (
Rule *rule : std::as_const( mChildren ) )
289 rule->prepare( context, attributeNames, handlers );
295 if ( !isFilterOK( feature, context ) )
298 bool registered =
false;
301 if ( handlers.contains(
this ) && mIsActive )
303 handlers[
this]->processFeature( feature, context );
307 bool matchedAChild =
false;
310 for (
Rule *rule : std::as_const( mChildren ) )
313 if ( !rule->isElse() )
315 const RegisterResult res = rule->registerFeature( feature, context, handlers );
317 matchedAChild |= ( res == Registered || res == Inactive );
318 registered |= matchedAChild;
323 if ( !matchedAChild )
325 for (
Rule *rule : std::as_const( mElseRules ) )
327 const RegisterResult res = rule->registerFeature( feature, context, handlers );
328 matchedAChild |= ( res == Registered || res == Inactive );
329 registered |= res != Filtered;
333 if ( !mIsActive || ( matchedAChild && !registered ) )
335 else if ( registered )
342 bool QgsRuleBased3DRenderer::Rule::isFilterOK(
QgsFeature &f, Qgs3DRenderContext &context )
const
344 if ( ! mFilter || mElseRule )
347 context.expressionContext().setFeature( f );
348 QVariant res = mFilter->evaluate( &context.expressionContext() );
349 return res.toInt() != 0;
375 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
376 for (
int i = 0; i < origDescendants.count(); ++i )
377 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
397 constexpr
double MINIMUM_VECTOR_Z_ESTIMATE = -5000000;
398 constexpr
double MAXIMUM_VECTOR_Z_ESTIMATE = 5000000;
400 return new QgsRuleBasedChunkedEntity( vl, MINIMUM_VECTOR_Z_ESTIMATE, MAXIMUM_VECTOR_Z_ESTIMATE,
tilingSettings(), mRootRule, map );
405 QDomDocument doc = elem.ownerDocument();
409 QDomElement rulesElem = mRootRule->
save( doc, context );
410 rulesElem.setTagName( QStringLiteral(
"rules" ) );
411 elem.appendChild( rulesElem );