|
Quantum GIS API Documentation
master-ce49b66
|
00001 /*************************************************************************** 00002 qgsvectorfieldsymbollayer.cpp 00003 ----------------------------- 00004 begin : Octorer 25, 2011 00005 copyright : (C) 2011 by Marco Hugentobler 00006 email : marco dot hugentobler at sourcepole dot ch 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "qgsvectorfieldsymbollayer.h" 00019 #include "qgsvectorlayer.h" 00020 00021 QgsVectorFieldSymbolLayer::QgsVectorFieldSymbolLayer(): mXAttribute( "" ), mYAttribute( "" ), mDistanceUnit( QgsSymbolV2::MM ), mScale( 1.0 ), 00022 mVectorFieldType( Cartesian ), mAngleOrientation( ClockwiseFromNorth ), mAngleUnits( Degrees ), mXIndex( -1 ), mYIndex( -1 ) 00023 { 00024 setSubSymbol( new QgsLineSymbolV2() ); 00025 } 00026 00027 QgsVectorFieldSymbolLayer::~QgsVectorFieldSymbolLayer() 00028 { 00029 } 00030 00031 void QgsVectorFieldSymbolLayer::setOutputUnit( QgsSymbolV2::OutputUnit unit ) 00032 { 00033 mDistanceUnit = unit; //other units are not used 00034 } 00035 00036 QgsSymbolV2::OutputUnit QgsVectorFieldSymbolLayer::outputUnit() const 00037 { 00038 return mDistanceUnit; 00039 } 00040 00041 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::create( const QgsStringMap& properties ) 00042 { 00043 QgsVectorFieldSymbolLayer* symbolLayer = new QgsVectorFieldSymbolLayer(); 00044 if ( properties.contains( "x_attribute" ) ) 00045 { 00046 symbolLayer->setXAttribute( properties["x_attribute"] ); 00047 } 00048 if ( properties.contains( "y_attribute" ) ) 00049 { 00050 symbolLayer->setYAttribute( properties["y_attribute"] ); 00051 } 00052 if ( properties.contains( "distance_unit" ) ) 00053 { 00054 symbolLayer->setDistanceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["distance_unit"] ) ); 00055 } 00056 if ( properties.contains( "scale" ) ) 00057 { 00058 symbolLayer->setScale( properties["scale"].toDouble() ); 00059 } 00060 if ( properties.contains( "vector_field_type" ) ) 00061 { 00062 symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) ); 00063 } 00064 if ( properties.contains( "angle_orientation" ) ) 00065 { 00066 symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) ); 00067 } 00068 if ( properties.contains( "angle_units" ) ) 00069 { 00070 symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) ); 00071 } 00072 return symbolLayer; 00073 } 00074 00075 bool QgsVectorFieldSymbolLayer::setSubSymbol( QgsSymbolV2* symbol ) 00076 { 00077 if ( symbol->type() == QgsSymbolV2::Line ) 00078 { 00079 mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol ); 00080 return true; 00081 } 00082 return false; 00083 } 00084 00085 void QgsVectorFieldSymbolLayer::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context ) 00086 { 00087 if ( !mLineSymbol ) 00088 { 00089 return; 00090 } 00091 00092 const QgsRenderContext& ctx = context.renderContext(); 00093 00094 const QgsFeature* f = context.feature(); 00095 if ( !f ) 00096 { 00097 //preview 00098 QPolygonF line; 00099 line << QPointF( 0, 50 ); 00100 line << QPointF( 100, 50 ); 00101 mLineSymbol->renderPolyline( line, 0, context.renderContext() ); 00102 } 00103 00104 double xComponent = 0; 00105 double yComponent = 0; 00106 00107 double xVal = 0; 00108 if ( mXIndex != -1 ) 00109 { 00110 xVal = f->attribute( mXIndex ).toDouble(); 00111 } 00112 double yVal = 0; 00113 if ( mYIndex != -1 ) 00114 { 00115 yVal = f->attribute( mYIndex ).toDouble(); 00116 } 00117 00118 switch ( mVectorFieldType ) 00119 { 00120 case Cartesian: 00121 xComponent = xVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit ); 00122 yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit ); 00123 break; 00124 case Polar: 00125 convertPolarToCartesian( xVal, yVal, xComponent, yComponent ); 00126 xComponent = xComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit ); 00127 yComponent = yComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit ); 00128 break; 00129 case Height: 00130 xComponent = 0; 00131 yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit ); 00132 break; 00133 default: 00134 break; 00135 } 00136 00137 xComponent *= mScale; 00138 yComponent *= mScale; 00139 00140 QPolygonF line; 00141 line << point; 00142 line << QPointF( point.x() + xComponent, point.y() - yComponent ); 00143 mLineSymbol->renderPolyline( line, f, context.renderContext() ); 00144 } 00145 00146 void QgsVectorFieldSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) 00147 { 00148 if ( mLineSymbol ) 00149 { 00150 mLineSymbol->startRender( context.renderContext() ); 00151 } 00152 00153 const QgsVectorLayer* layer = context.layer(); 00154 if ( layer ) 00155 { 00156 mXIndex = layer->fieldNameIndex( mXAttribute ); 00157 mYIndex = layer->fieldNameIndex( mYAttribute ); 00158 } 00159 else 00160 { 00161 mXIndex = -1; 00162 mYIndex = -1; 00163 } 00164 } 00165 00166 void QgsVectorFieldSymbolLayer::stopRender( QgsSymbolV2RenderContext& context ) 00167 { 00168 if ( mLineSymbol ) 00169 { 00170 mLineSymbol->stopRender( context.renderContext() ); 00171 } 00172 } 00173 00174 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::clone() const 00175 { 00176 QgsSymbolLayerV2* clonedLayer = QgsVectorFieldSymbolLayer::create( properties() ); 00177 if ( mLineSymbol ) 00178 { 00179 clonedLayer->setSubSymbol( mLineSymbol->clone() ); 00180 } 00181 return clonedLayer; 00182 } 00183 00184 QgsStringMap QgsVectorFieldSymbolLayer::properties() const 00185 { 00186 QgsStringMap properties; 00187 properties["x_attribute"] = mXAttribute; 00188 properties["y_attribute"] = mYAttribute; 00189 properties["distance_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mDistanceUnit ); 00190 properties["scale"] = QString::number( mScale ); 00191 properties["vector_field_type"] = QString::number( mVectorFieldType ); 00192 properties["angle_orientation"] = QString::number( mAngleOrientation ); 00193 properties["angle_units"] = QString::number( mAngleUnits ); 00194 return properties; 00195 } 00196 00197 void QgsVectorFieldSymbolLayer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const 00198 { 00199 element.appendChild( doc.createComment( "VectorField not implemented yet..." ) ); 00200 mLineSymbol->toSld( doc, element, props ); 00201 } 00202 00203 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::createFromSld( QDomElement &element ) 00204 { 00205 Q_UNUSED( element ); 00206 return NULL; 00207 } 00208 00209 void QgsVectorFieldSymbolLayer::drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size ) 00210 { 00211 if ( mLineSymbol ) 00212 { 00213 mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size ); 00214 } 00215 } 00216 00217 QSet<QString> QgsVectorFieldSymbolLayer::usedAttributes() const 00218 { 00219 QSet<QString> attributes; 00220 if ( !mXAttribute.isEmpty() ) 00221 { 00222 attributes.insert( mXAttribute ); 00223 } 00224 if ( !mYAttribute.isEmpty() ) 00225 { 00226 attributes.insert( mYAttribute ); 00227 } 00228 return attributes; 00229 } 00230 00231 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const 00232 { 00233 //convert angle to degree and to north orientation 00234 if ( mAngleOrientation == CounterclockwiseFromEast ) 00235 { 00236 if ( angle <= 90 ) 00237 { 00238 angle = 90 - angle; 00239 } 00240 else 00241 { 00242 angle = 360 - angle + 90; 00243 } 00244 } 00245 00246 if ( mAngleUnits == Degrees ) 00247 { 00248 angle = angle * M_PI / 180.0; 00249 } 00250 00251 x = length * sin( angle ); 00252 y = length * cos( angle ); 00253 }