/** * Draw a DimRadial * TODO: 1) Draw correct leader * 2) Change text position such that it's correctly placed under the text. I am not 100% sure how this is done from DXF * It could be that Attachmentpoint is simply incorrect?!?!?! or that the DXF importer is incorrect? * */ void LCDimRadial::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const { bool modified = false; // Decide to show the explecit value or the measured value double radiusCircle = this->definitionPoint().distanceTo(this->definitionPoint2()); const lc::geo::Coordinate& mousePos = middleOfText(); const bool mouseIsInside = mousePos.distanceTo(definitionPoint()) < radiusCircle; // FIXME this should not be fixed const double capSize = 2.; std::string value = lc::StringHelper::dim_value(explicitValue(), options.radialFormat(), radiusCircle); /* get text size */ painter.save(); painter.font_size(options.dimTextHeight()); TextExtends te = painter.text_extends(value.c_str()); painter.restore(); // Draw line EndCaps endCaps; auto tLinePos = !mouseIsInside ? mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), te.width + capSize) : mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), -te.width - capSize); auto tMText = !mouseIsInside ? mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), te.width / 2 + capSize / 2) : mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), -te.width / 2 - capSize / 2); painter.move_to(definitionPoint2().x(), definitionPoint2().y()); painter.line_to(mousePos.x(), mousePos.y()); painter.line_to(tLinePos.x(), mousePos.y()); painter.stroke(); endCaps.render(painter, EndCaps::CLOSEDARROW, mousePos.x(), mousePos.y(), definitionPoint2().x(), definitionPoint2().y(), capSize) ; this->drawText(value, textAngle(), lc::TextConst::AttachmentPoint::Top_center, tMText, painter, options, rect); if (modified) { painter.restore(); } }
/** * Draw a DimDiametric * TODO: draw correct leader and verification if we draw this correctly compared to other CAD drawings */ void LCDimDiametric::draw(LcPainter &painter, const LcDrawOptions &options, const lc::geo::Area &rect) const { // Decide to show the explecit value or the measured value auto diameterCircle = _dimDiametric->definitionPoint().distanceTo(_dimDiametric->definitionPoint2()); auto circle_middle_p0 = _dimDiametric->definitionPoint2().mid(_dimDiametric->definitionPoint()); // FIXME this should not be fixed const double capSize = 2.; auto value = lc::tools::StringHelper::dim_value( _dimDiametric->explicitValue(), options.diametricFormat(), diameterCircle ); /* get text size */ painter.save(); painter.font_size(options.dimTextHeight(), false); TextExtends te = painter.text_extends(value.c_str()); painter.restore(); EndCaps endCaps; const bool textisInside = _dimDiametric->middleOfText().distanceTo(circle_middle_p0) < diameterCircle / 2.; const bool textFitsInside = diameterCircle > te.width; // Draw inside if the text really fit's and if it was initially setup inside // No sure if this follow's DXF spec?? if (textisInside && textFitsInside) { painter.move_to(_dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y()); painter.line_to(_dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y()); painter.stroke(); endCaps.render( painter, EndCaps::CLOSEDARROW, _dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y(), _dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y(), capSize ); endCaps.render( painter, EndCaps::CLOSEDARROW, _dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y(), _dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y(), capSize ); this->drawText( value, _dimDiametric->textAngle(), lc::TextConst::AttachmentPoint::Top_center, _dimDiametric->middleOfText(), painter, options, rect ); } else { // When we draw text outside, we move the arrows around (facing inwards) and we draw a small leader where we place the text on // here we ignore _dimDiametric->middleOfText() and I am not sure if that's suppose to work like that (RVT) auto center = _dimDiametric->definitionPoint().mid(_dimDiametric->definitionPoint2()); auto p1 = _dimDiametric->definitionPoint().moveTo(center, -capSize * 1.5); auto p2 = _dimDiametric->definitionPoint2().moveTo(center, -capSize * 1.5); // take largest X value of both _dimDiametric->definition points (on the right) and draw text there if (p1.x() > p2.x()) { painter.move_to(p1.x() + capSize, p1.y()); painter.line_to(p1.x(), p1.y()); painter.line_to(p2.x(), p2.y()); painter.stroke(); this->drawText( value, _dimDiametric->textAngle(), lc::TextConst::AttachmentPoint::Top_left, lc::geo::Coordinate(p1.x(), p1.y()), painter, options, rect ); } else { painter.move_to(p2.x() + capSize, p2.y()); painter.line_to(p2.x(), p2.y()); painter.line_to(p1.x(), p1.y()); painter.stroke(); this->drawText( value, _dimDiametric->textAngle(), lc::TextConst::AttachmentPoint::Top_right, lc::geo::Coordinate(p2.x(), p2.y()), painter, options, rect ); } endCaps.render( painter, EndCaps::CLOSEDARROW, p1.x(), p1.y(), _dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y(), capSize ); endCaps.render( painter, EndCaps::CLOSEDARROW, p2.x(), p2.y(), _dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y(), capSize ); } }
/** * TODO items for text: * 1) Test multi-line text rendering * 2) Accept color codes during text rendering in the form of \Cx (x is the index color) * 3) Font selection * For testing there is a lua script * * We can increase performance if we pre-calculate some values and cache them so that we * don't have to keep calling text_extends and do some of the calculations * also we shouldn't draw text smaller then XX pixels when rendered on screen. */ void LCVText::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const { bool modified = false; painter.font_size(height()); painter.select_font_face("stick3.ttf"); TextExtends te = painter.text_extends(text_value().c_str()); double alignX = 0.0; double alignY = 0.0; // double alignX, alignY; // The idea of height() * .2 is just a average basline offset. Don't this value to seriously, // we could get it from font exists but that sounds over exaggerating for the moment. switch (valign()) { case lc::TextConst::VAMiddle: alignX += 0.0; alignY += -height() / 2. + (height() * .2); break; case lc::TextConst::VABottom: alignX += 0.0; alignY += -height() + (height() * .2); break; case lc::TextConst::VABaseline: alignX += 0.0; alignY += 0.0; break; case lc::TextConst::VATop: alignX += 0.0; alignY += 0.0 + (height() * .2); break; default: break; } // Horizontal Align: switch (halign()) { case lc::TextConst::HALeft: alignX += - te.width; alignY += 0.; break; case lc::TextConst::HACenter: alignX += - te.width / 2.0; alignY += 0.; break; case lc::TextConst::HAMiddle: alignX += - te.width / 2.0; alignY += 0.; break; case lc::TextConst::HARight: alignX += 0.; alignY += 0.; break; default: break; } painter.save(); painter.translate(insertion_point().x(), -insertion_point().y()); painter.rotate(-angle()); painter.translate(alignX, -alignY); painter.move_to(0., 0.); painter.text(text_value().c_str()); painter.stroke(); painter.restore(); if (modified) { painter.restore(); } }