QPolygonF straightArrow( QPointF po, QPointF pd, qreal startWidth, qreal width, qreal headSize, QgsArrowSymbolLayer::HeadType headType, qreal offset ) { QPolygonF polygon; // implicitly shared // vector length qreal length = euclidian_distance( po, pd ); // shift points if there is not enough room for the head(s) if (( headType == QgsArrowSymbolLayer::HeadSingle ) && ( length < headSize ) ) { po = pd - ( pd - po ) / length * headSize; length = headSize; } else if (( headType == QgsArrowSymbolLayer::HeadReversed ) && ( length < headSize ) ) { pd = po + ( pd - po ) / length * headSize; length = headSize; } else if (( headType == QgsArrowSymbolLayer::HeadDouble ) && ( length < 2 * headSize ) ) { QPointF v = ( pd - po ) / length * headSize; QPointF npo = ( po + pd ) / 2.0 - v; QPointF npd = ( po + pd ) / 2.0 + v; po = npo; pd = npd; length = 2 * headSize; } qreal bodyLength = length - headSize; // unit vector QPointF unitVec = ( pd - po ) / length; // perpendicular vector QPointF perpVec( -unitVec.y(), unitVec.x() ); // set offset po += perpVec * offset; pd += perpVec * offset; if ( headType == QgsArrowSymbolLayer::HeadDouble ) { // first head polygon << po; polygon << po + unitVec * headSize + perpVec * headSize; polygon << po + unitVec * headSize + perpVec * ( width * 0.5 ); polygon << po + unitVec * bodyLength + perpVec * ( width * 0.5 ); // second head polygon << po + unitVec * bodyLength + perpVec * headSize; polygon << pd; polygon << po + unitVec * bodyLength - perpVec * headSize; polygon << po + unitVec * bodyLength - perpVec * ( width * 0.5 ); // end of the first head polygon << po + unitVec * headSize - perpVec * ( width * 0.5 ); polygon << po + unitVec * headSize - perpVec * headSize; } else if ( headType == QgsArrowSymbolLayer::HeadSingle ) { polygon << po - perpVec * ( startWidth * 0.5 ); polygon << po + perpVec * ( startWidth * 0.5 ); polygon << po + unitVec * bodyLength + perpVec * ( width * 0.5 ); polygon << po + unitVec * bodyLength + perpVec * headSize; polygon << pd; polygon << po + unitVec * bodyLength - perpVec * headSize; polygon << po + unitVec * bodyLength - perpVec * ( width * 0.5 ); } else if ( headType == QgsArrowSymbolLayer::HeadReversed ) { // first head polygon << po; polygon << po + unitVec * headSize + perpVec * headSize; polygon << po + unitVec * headSize + perpVec * ( width * 0.5 ); polygon << pd + perpVec * ( startWidth * 0.5 ); polygon << pd - perpVec * ( startWidth * 0.5 ); polygon << po + unitVec * headSize - perpVec * ( width * 0.5 ); polygon << po + unitVec * headSize - perpVec * headSize; } // close the polygon polygon << polygon.first(); return polygon; }
void BGNode::drawFace(ofShader & mEyeShader) { /* int n = neighbours.size(); ofVec2f toVector(1,0); if(n > 0) toVector = (neighbours[0]->position - position).normalize(); ofVec2f perpVec(-toVector.y, toVector.x); */ ofSetColor(255); float offset = .05 * nodeRadius; float perpOffset = .6 * nodeRadius; float eyeRadius = .6 * nodeRadius; ofVec2f toVector = mSurfaceNormal; ofVec2f perpVec(-toVector.y, toVector.x); ofVec2f goalPos = position; if(neighbours.size() > 0) goalPos = neighbours[0]->position; float texFactor = .6 * nodeRadius; for(int i=0; i<2; ++i) { int factor = i == 0 ? 1 : -1; ofVec2f pos = position + toVector * offset + factor * perpVec * perpOffset; ofMesh eyeMesh; eyeMesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); for(int j=0; j<4; ++j) { ofVec2f texPos(j % 2, j / 2); ofVec2f vPos = pos + (texPos.x - .5) * texFactor * perpVec + (texPos.y - .5) * texFactor * toVector; eyeMesh.addVertex(ofVec3f(vPos.x, vPos.y, 0)); eyeMesh.addTexCoord(texPos); } ofVec2f goalPos = position; if(neighbours.size() > 0) goalPos = neighbours[0]->position; ofVec2f toGoal = goalPos - pos; float toGoalLength = toGoal.length(); ofVec2f pupilPos = pos; if(toGoalLength > 0.01) pupilPos = pos + .25 * eyeRadius / toGoalLength * toGoal; mEyeShader.begin(); mEyeShader.setUniform2f("uCenter", pos.x, pos.y); mEyeShader.setUniform2f("uFocusPoint", goalPos.x, goalPos.y); mEyeShader.setUniform2f("uPupilLoc", pupilPos.x, pupilPos.y); mEyeShader.setUniform1i("uFlipHorizontally", i > 0); eyeMesh.draw(); mEyeShader.end(); } ofMesh mouthMesh; mouthMesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); for(int i=0; i<21; ++i) { float t = i / 20.0; float x = .6 * (t - .5) * nodeRadius; float yVar = 2 * abs(t - .5); float y = (-yVar * yVar * (1 - yVar) * .6 - .3) * nodeRadius; for(int it=0; it<2; ++it) { mouthMesh.addVertex(position + y * toVector + x * perpVec); mouthMesh.addColor(ofColor(0)); y -= 3; } } mouthMesh.draw(); }