【项目实训】线形箭头的变化

        若是普通的箭头,则使用<maker>通过设置maker-end,maker-start便可以使得箭头方向随着线条的方向改变而改变。对于那种棒状的箭头,并没有成熟的API接口可以使用,只好采用记录所有转折点的方式,通过<path>绘制。

通过记录所有关键点的方式绘制箭头,同时也意味着图形的变化会导致关键点的变化,而且其变换方式较为复杂。如图,橙色关键点用来调控组件的宽度,以及箭头的形状,蓝色关键点则用来调整组件的位置。

可以将其看做一条位于中间的线,随后将其扩充,最后依次连接,整个图形是对称的,可以多次利用这个性质。

在计算过程中会用到一些基础的计算几何知识。比如点关于直线的对称点,点位于直线的左侧或者右侧,点在直线上的垂足。等等。

计算对称点

Lewzen::Point2D Line::getFlipPoint(Lewzen::Point2D p) {
        double x1 = startPoint->getX(), y1 = startPoint->getY(), x2 = endPoint->getX(), y2 = endPoint->getY();
        double a = y2 - y1, b = x1 - x2, c = x2 * y1 - x1 * y2;
        double m = p.get_x(), n = p.get_y();
        Lewzen::Point2D cz((b * b * m - a * b * n - a * c) / (a * a + b * b),
                           (a * a * n - a * b * m - b * c) / (a * a + b * b));
        return Lewzen::Point2D(2 * cz.get_x() - p.get_x(), 2 * cz.get_y() - p.get_y());
    }

点是否在线的同侧

 void Line::onSameSideF() {
        auto s = Lewzen::Point2D(startPoint->getX(),startPoint->getY());

        auto e = Lewzen::Point2D(pointList[2]->getX(),pointList[2]->getY());

        int sz = pointList.size()-1;
        auto s1 = Lewzen::Point2D(pointList[sz-2]->getX(),pointList[sz-2]->getY());
        auto e1 = Lewzen::Point2D(endPoint->getX(),endPoint->getY());

        double x1 = s.get_x(), y1 = s.get_y(), x2 = e.get_x(), y2 = e.get_y();
        double x0 = arrowCPoint->getX(),y0 = arrowCPoint->getY();
        double flagS = (x2-x1)*(y0-y1)-(y2-y1)*(x0-x1);

        x1 = s1.get_x();
        y1 = s1.get_y();
        x2 = e1.get_x();
        y2 = e1.get_y();
        x0 = midCPoint->getX();
        y0 = midCPoint->getY();
        double flagE = (x2-x1)*(y0-y1)-(y2-y1)*(x0-x1);
        if(flagS*flagE < 0){
            auto t = getFlipP(Lewzen::Point2D(arrowPoint->getX(),arrowPoint->getY()),s,e);
            arrowPoint->setX(t.get_x());
            arrowPoint->setY(t.get_y());

            t = getFlipP(Lewzen::Point2D(arrowCPoint->getX(),arrowCPoint->getY()),s,e);
            arrowCPoint->setX(t.get_x());
            arrowCPoint->setY(t.get_y());
        }

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值