Exemplo n.º 1
0
/**
* 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();
    }

}
Exemplo n.º 2
0
/**
* 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
        );
    }
}
Exemplo n.º 3
0
void DocumentCanvas::drawEntity(LCVDrawItem_CSPtr entity) {
	lc::entity::CADEntity_CSPtr ci = std::dynamic_pointer_cast<const lc::entity::CADEntity>(entity);
	lc::MetaColor_CSPtr entityColor = ci->metaInfo<lc::MetaColor>(lc::MetaColor::LCMETANAME());
	lc::MetaLineWidthByValue_CSPtr entityLineWidth = ci->metaInfo<lc::MetaLineWidthByValue>(lc::MetaLineWidthByValue::LCMETANAME());
	lc::DxfLinePattern_CSPtr entityLinePattern = ci->metaInfo<lc::DxfLinePattern>(lc::DxfLinePattern::LCMETANAME());
	lc::Layer_CSPtr layer = ci->layer();
	
	LcPainter& painter = cachedPainter(VIEWER_DOCUMENT);
	LcDrawOptions lcDrawOptions;

	double x = 0.;
	double y = 0.;
	double w = _deviceWidth;
	double h = _deviceHeight;
	painter.device_to_user(&x, &y);
	painter.device_to_user_distance(&w, &h);
	lc::geo::Area visibleUserArea = lc::geo::Area(lc::geo::Coordinate(x, y), w, h);

	painter.save();

	// Used to give the illusation from slightly thinner lines. Not sure yet what to d with it and if I will keep it
	double alpha_compensation = 0.9;

    // Decide on line width
    // We multiply for now by 3 to ensure that 1mm lines will still appear thicker on screen
    // TODO: Find a better algo
    double width;
	if (entityLineWidth != nullptr) {
		width = entityLineWidth->width() * 1.5;
	} else {
		width = layer->lineWidth().width() * 1.5;
	}
    // Is this correct? May be we should decide on a different minimum width then 0.1, because may be on some devices 0.11 isn't visible?
    painter.line_width(std::max(width, MINIMUM_READER_LINEWIDTH));

	if (entityLinePattern != nullptr && entityLinePattern->lcPattern(width).size()>0) {
        auto path = entityLinePattern->lcPattern(width);
		painter.set_dash(&path[0], path.size(), 0., true);
	}
    else if(layer->linePattern() != nullptr && layer->linePattern()->lcPattern(width).size() > 0) {
        auto path = layer->linePattern()->lcPattern(width);
        painter.set_dash(&path[0], path.size(), 0., true);
    }

	// Decide what color to render the entity into
	if (entity->selected()) {
		painter.source_rgba(
			lcDrawOptions.selectedColor().red(),
			lcDrawOptions.selectedColor().green(),
			lcDrawOptions.selectedColor().blue(),
			lcDrawOptions.selectedColor().alpha() * alpha_compensation
		);
	} else if (entityColor != nullptr) {
		painter.source_rgba(
			entityColor->red(),
			entityColor->green(),
			entityColor->blue(),
			entityColor->alpha() * alpha_compensation);
	} else {
		lc::Color layerColor = layer->color();
		painter.source_rgba(
			layerColor.red(),
			layerColor.green(),
			layerColor.blue(),
			layerColor.alpha() * alpha_compensation);
	}

	entity->draw(painter, lcDrawOptions, visibleUserArea);

	painter.restore();	
}