KarbonWhirlPinchCommand::KarbonWhirlPinchCommand( KoPathShape * path, qreal angle, qreal pinch, qreal radius, QUndoCommand *parent ) : QUndoCommand( parent ), d( new Private( path, angle, pinch, radius ) ) { setText( i18n( "Whirl & pinch" ) ); // save the path point data used for undo uint subpathCount = d->pathShape->subpathCount(); for( uint subpathIndex = 0; subpathIndex < subpathCount; ++subpathIndex ) { QList<PointData> subpathData; int pointCount = d->pathShape->pointCountSubpath( subpathIndex ); for( int pointIndex = 0; pointIndex < pointCount; ++pointIndex ) { KoPathPoint * p = d->pathShape->pointByIndex( KoPathPointIndex( subpathIndex, pointIndex ) ); subpathData.append( PointData( p ) ); } d->pathData.append( subpathData ); } }
int setTree( unsigned count, const Point3D< Real > * inPoints, const Point3D< Real > * inNormals, int maxDepth, int minDepth, int splatDepth, Real samplesPerNode, Real scaleFactor, bool useConfidence, Real constraintWeight, int adaptiveExponent) { if ( splatDepth < 0 ) splatDepth = 0; this->samplesPerNode = samplesPerNode; this->splatDepth = splatDepth; if( this->_boundaryType == 0 ) { maxDepth++, minDepth = std::max< int >( 1 , minDepth )+1; if (splatDepth > 0 ) splatDepth++; } else { minDepth = std::max< int >( 0 , minDepth ); } this->_minDepth = std::min< int >( minDepth , maxDepth ); this->_constrainValues = (constraintWeight>0); double pointWeightSum = 0; Point3D< Real > min , max; TreeOctNode::NeighborKey3 neighborKey; neighborKey.set( maxDepth ); this->tree.setFullDepth( _minDepth ); // Read through once to get the center and scale { for (unsigned k=0; k<count; ++k) { const Point3D< Real >& p = inPoints[k]; for( int i=0 ; i<DIMENSION ; i++ ) { if (k) { if( p[i] < min[i] ) min[i] = p[i]; else if( p[i] > max[i] ) max[i] = p[i]; } else { min[i] = max[i] = p[i]; } } } this->_center = ( max+min ) /2; this->_scale = std::max< Real >( max[0]-min[0] , std::max< Real >( max[1]-min[1] , max[2]-min[2] ) ) * 2; if( this->_boundaryType == 0 ) this->_scale *= 2; } //update scale and center with scale factor { this->_scale *= scaleFactor; for( int i=0 ; i<DIMENSION ; i++ ) this->_center[i] -= _scale/2; } if( splatDepth > 0 ) { const Point3D< Real >* _p = inPoints; const Point3D< Real >* _n = inNormals; for (unsigned k=0; k<count; ++k, ++_p, ++_n) { Point3D< Real > p = ( inPoints[k] - _center ) / _scale; if( !_inBounds(p) ) continue; Point3D< Real > myCenter = Point3D< Real >( Real(0.5) , Real(0.5) , Real(0.5) ); Real myWidth = Real(1.0); Real weight = Real(1.0); if( useConfidence ) { weight = Real( Length(inNormals[k]) ); } TreeOctNode* temp = &this->tree; int d = 0; while( d < splatDepth ) { UpdateWeightContribution( temp , p , neighborKey , weight ); if( !temp->children ) temp->initChildren(); int cIndex = TreeOctNode::CornerIndex( myCenter , p ); temp = temp->children + cIndex; myWidth /= 2; if( cIndex&1 ) myCenter[0] += myWidth/2; else myCenter[0] -= myWidth/2; if( cIndex&2 ) myCenter[1] += myWidth/2; else myCenter[1] -= myWidth/2; if( cIndex&4 ) myCenter[2] += myWidth/2; else myCenter[2] -= myWidth/2; d++; } UpdateWeightContribution( temp , p , neighborKey , weight ); } } //normals this->normals = new std::vector< Point3D<Real> >(); int cnt = 0; { for (unsigned k=0; k<count; ++k) { Point3D< Real > p = ( inPoints[k] - _center ) / _scale; if( !_inBounds(p) ) continue; Point3D< Real > n = inNormals[k] * Real(-1.0); //normalize n Real l = Real( Length( n ) ); if( l!=l || l<=EPSILON ) continue; if( !useConfidence ) n /= l; Point3D< Real > myCenter = Point3D< Real >( Real(0.5) , Real(0.5) , Real(0.5) ); Real myWidth = Real(1.0); Real pointWeight = Real(1.0f); if ( samplesPerNode > 0 && splatDepth ) { pointWeight = SplatOrientedPoint( p , n , neighborKey , splatDepth , samplesPerNode , _minDepth , maxDepth ); } else { TreeOctNode* temp = &this->tree; int d = 0; if( splatDepth ) { while( d < splatDepth ) { int cIndex = TreeOctNode::CornerIndex(myCenter,p); temp = &temp->children[cIndex]; myWidth /= 2; if(cIndex&1) myCenter[0] += myWidth/2; else myCenter[0] -= myWidth/2; if(cIndex&2) myCenter[1] += myWidth/2; else myCenter[1] -= myWidth/2; if(cIndex&4) myCenter[2] += myWidth/2; else myCenter[2] -= myWidth/2; d++; } pointWeight = GetSampleWeight( temp , p , neighborKey ); } { for (int i=0 ; i<DIMENSION ; i++ ) n[i] *= pointWeight; } while( d < maxDepth ) { if( !temp->children ) temp->initChildren(); int cIndex = TreeOctNode::CornerIndex(myCenter,p); temp = &temp->children[cIndex]; myWidth /= 2; if(cIndex&1) myCenter[0] += myWidth/2; else myCenter[0] -= myWidth/2; if(cIndex&2) myCenter[1] += myWidth/2; else myCenter[1] -= myWidth/2; if(cIndex&4) myCenter[2] += myWidth/2; else myCenter[2] -= myWidth/2; d++; } SplatOrientedPoint( temp , p , n , neighborKey ); } pointWeightSum += pointWeight; if ( this->_constrainValues ) { int d = 0; TreeOctNode* temp = &this->tree; Point3D< Real > myCenter = Point3D< Real >( Real(0.5) , Real(0.5) , Real(0.5) ); Real myWidth = Real(1.0); while( true ) { int idx = temp->nodeData.pointIndex; if( idx == -1 ) { idx = static_cast<int>( this->_points.size() ); this->_points.push_back( PointData( p , Real(1.0) ) ); temp->nodeData.pointIndex = idx; } else { this->_points[idx].weight += Real(1.0); this->_points[idx].position += p; } int cIndex = TreeOctNode::CornerIndex( myCenter , p ); if ( !temp->children ) break; temp = &temp->children[cIndex]; myWidth /= 2; if( cIndex&1 ) myCenter[0] += myWidth/2; else myCenter[0] -= myWidth/2; if( cIndex&2 ) myCenter[1] += myWidth/2; else myCenter[1] -= myWidth/2; if( cIndex&4 ) myCenter[2] += myWidth/2; else myCenter[2] -= myWidth/2; d++; } } ++cnt; } } if( this->_boundaryType == 0 ) pointWeightSum *= Real(4.0); constraintWeight *= static_cast<Real>(pointWeightSum); constraintWeight /= static_cast<Real>(cnt); MemoryUsage( ); if( this->_constrainValues ) { for( TreeOctNode* node=this->tree.nextNode() ; node ; node=this->tree.nextNode(node) ) { if( node->nodeData.pointIndex != -1 ) { int idx = node->nodeData.pointIndex; this->_points[idx].position /= this->_points[idx].weight; int e = ( this->_boundaryType == 0 ? node->depth()-1 : node->depth() ) * adaptiveExponent - ( this->_boundaryType == 0 ? maxDepth-1 : maxDepth ) * (adaptiveExponent-1); if ( e < 0 ) this->_points[idx].weight /= Real( 1<<(-e) ); else this->_points[idx].weight *= Real( 1<< e ); this->_points[idx].weight *= Real( constraintWeight ); } } } #if FORCE_NEUMANN_FIELD if( this->_boundaryType == 1 ) { for( TreeOctNode* node=this->tree.nextNode() ; node ; node=this->tree.nextNode( node ) ) { int d , off[3]; node->depthAndOffset( d , off ); int res = 1<<d; if( node->nodeData.normalIndex < 0 ) continue; Point3D< Real >& normal = (*this->normals)[node->nodeData.normalIndex]; for( int d=0 ; d<3 ; d++ ) if ( off[d]==0 || off[d]==res-1 ) normal[d] = 0; } } #endif // FORCE_NEUMANN_FIELD MemoryUsage(); return cnt; }