G代码圆弧_g02和g03走圆编程-程序员宅基地

技术标签: 算法  G-Code  兴趣使然  G02/G03  

圆弧总结

说明

工作中经常画图经常会遇到圆弧,开始的时候我并不是很理解,随着深入发现其实有些坑的,这里总结记录一下,可能并不是最优的解法,但肯定是自己理解后想出来的,如果这些能给你提供一些思路和帮助,那便是极好的。

G-Code的G02/G03

G02 顺时针圆弧/G03 逆时针圆弧

在这里插入图片描述

圆心的计算

I, J, K模式
G02 X20 Y10 I0 J-10
G03 X10.5 I3.0 J4.0

G02/G03指令,是已知起始点S(Xs, Ys),终止点E(Xe, Ye),相对圆心的增量(I, J),顺逆时针状态。通过这些信息我们是可以算出圆心的。

一般来说是(I, J)是圆弧起点相对圆心的增量,即圆心O坐标是(Xs + I, Ys + J)。而我遇到的情况,(I, J)的表示可能有以下几种情况:

  • 相对圆弧起点的增量
  • 相对圆弧终点的增量
  • 绝对圆弧中心
计算

这个就很简单了,针对(I, J)表示不同时计算方式也不同

  • 相对圆弧起点时,圆心坐标

O x = X s + I ; O y = Y s + J ; O_x = X_s + I;\\ O_y = Y_s + J;\\ Ox=Xs+I;Oy=Ys+J;

  • 相对圆弧终点时,圆心坐标

O x = X e + I ; O y = Y e + J ; O_x = X_e + I;\\ O_y = Y_e + J;\\ Ox=Xe+I;Oy=Ye+J;

  • 绝对圆弧中心

O x = I ; O y = J ; O_x = I;\\ O_y = J; Ox=I;Oy=J;

R模式
G02 X20 Y10 R10 F300

注意相同的起点、终点、半径和方向,计算出来的圆心可能有两种。其中,

  • R>0时,圆弧和中心的夹角小于180°,即圆弧段小于或等于半圆;
  • R<0时,圆弧和中心的夹角大于180°,即圆弧段大于半圆。

例如下图,G02指令时,如果R>0时,圆心是黑色圆的,如果R<0,则应该是黄色的圆。
在这里插入图片描述

以下图片是我画的分析用的简易图,方便自己理解如何计算出圆心的方法。假设以下是G02圆弧,起点为C,终点为D,半径为R,加粗圆弧部分是实际路径。
在这里插入图片描述

计算

假设存在上面的情况,已知起点C(Xc, Yc), 终点D(Xd, Yd),半径R

  1. 连接CD,求得中点A(Xa, Ya)

X a = ( X c + X d ) 2 Y a = ( Y c + Y d ) 2 (1) X_a = \frac{(X_c + X_d)}{2}\\ Y_a = \frac{(Y_c + Y_d)}{2} \tag{1} Xa=2(Xc+Xd)Ya=2(Yc+Yd)(1)

  1. 现在可以得到向量 A C ⃗ \vec{AC} AC 的单位向量了
    ∣ A C ⃗ ∣ = ( X a − X c ) 2 + ( Y a − Y c ) 2 A C ^ = A C ⃗ ∣ A C ⃗ ∣ (2) |\vec{AC}| = \sqrt{(X_a - X_c)^2 + (Y_a - Y_c)^2} \\ \hat{AC} = \frac{\vec{AC}}{|\vec{AC}|} \tag{2} AC =(XaXc)2+(YaYc)2 AC^=AC AC (2)

  2. 圆上两点连线的中垂线必过圆心,这是个知识点,然后根据直角三角关系,可以知道(AO)2 = R2 - (AC)2,下面用向量的方式表示,后面会用到。

∣ A O ⃗ ∣ = R 2 − ∣ A C ⃗ ∣ 2 (3) |\vec{AO}| = \sqrt{R^2 - |\vec{AC}|^2} \tag{3} AO =R2AC 2 (3)

  1. 现在只需要将单位向量 A C ^ \hat{AC} AC^,旋转90°后就是向量 A O ⃗ \vec{AO} AO 的单位向量(这个没问题吧),如果旋转-90°就是向量 A P ⃗ \vec{AP} AP 的单位向量,然后乘以AO的长度就得到圆心了,两种情况的圆心都可以认为是对的。

A O ⃗ = A O ^   ∗ ∣ A O ⃗ ∣ (4) \vec{AO} = \hat{AO}\ * |\vec{AO}|\tag{4} AO =AO^ AO (4)

R模式实际算法省略,因为经验有限,我并没有遇到过这个情况,当前仅讨论这个情况下计算出圆心的理论算法。

圆弧夹角的计算

这个地方,我感觉相对是比较麻烦的,因为必须要考虑圆弧方向,角度的值域范围,并不能简单粗暴的 终点角度 − 起点角度 终点角度- 起点角度 终点角度起点角度

#define 	PI 		3.1415926535897932384626433
#define 	EPS 	0.000001

//!< 基础点
struct Point
{
    
	double x;
    double y;
};
typedef Point Vector;

//!< 计算两向量夹角
float calc2VecAngle(const Vector& v1, const Vector& v2, const int& isCw)
{
    
    //!< atan2 计算得到的弧度范围是[-PI, PI],可以转换成[0, 2 * PI]来计算
    float startAngNew = atan2f(v1.y, v1.x);
    float startAngNew2 = atan2f(v2.y, v2.x);

    if (startAngNew < EPS)
        startAngNew += 2 * PI;
    if (startAngNew2 < EPS)
        startAngNew2 += 2 * PI;

    float sweepNew = abs(startAngNew - startAngNew2);
    if (isCw != 0)
    {
    
        //!< 两向量之间的夹角,需要根据顺/逆时针,和所处角度象限判断
        if (startAngNew < startAngNew2 && isCw > EPS ||
            startAngNew > startAngNew2 && isCw < EPS)
        {
    
            sweepNew = abs(2 * PI - abs(sweepNew));
        }
    }
    return sweepNew;
}

//!< 已知圆弧,圆心,起点,终点,方向,计算出圆弧夹角(弧度制) 
void calcArcAngle(Point center, Point s, Point e, bool isClockWise, double& angle)
{
    
    //!< 起点终点相同的情况,就是个整圆
    if (s == e)
    {
    
        angle = PI * 2;
    }
    else
    {
    
        Vector v1, v2;
        v1.x = start.x - center.x;
        v1.y = start.y - center.y;

        v2.x = end.x - center.x;
        v2.y = end.y - center.y;

        angle = calc2VecAngle(v1, v2, (cw ? 1 : -1));
    }
}

在圆弧上

上面的方法中,可以已知圆弧圆心,圆弧起点,圆弧终点,方向,是可以计算判断出某个点在不在圆弧上。

//!< 两点的距离
double getLength(const Point& p1, const Point& p2)
{
    
	return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));   
}

//!< 计算角度,需要用到atan2f值域[-π, π],这个很重要
//!< 可以转换成[0, 2π]来计算
double getAngle(const Point& p1, const Point& p2)
{
    
    double ang = atan2f((p2.y - p1.y), (p2.x - p1.x)); // [-π, π]
    if (ang < EPS) {
         // [-π, 0]
        ang += PI * 2.0f;
    }
    return ang;
}

//!< angle的取值限制为圆上的任意角度
bool isOn(const Point& center, const Point& start, const Point& end, const bool& cw, const double& angle, const double& eps)
{
    
    //!< 如果圆是个整圆,任一角度都在圆弧上
    if (start == end)
    {
    
        return true;
    }

    //[0, 2π]
    double startAng = getAngle(center, start);
    double endAng = getAngle(center, end);
    double curAng = angle;

    bool bIsOn = false;
    //!< 顺时针
    if (cw)
    {
    
        //!< 圆弧起始角度 > 终止角度的情况
        if (startAng > endAng)
        {
    
            //!< curAng 满足区间 [endAng, startAng]
            if (curAng >= endAng && curAng <= startAng)
            {
    
                bIsOn = true;
            }
        }
        //!< 圆弧起始角度 < 终止角度
        else
        {
    
            //!< 顺时针时 起始角度 < 终止角度则说明圆弧经过了0°, 则此时可以
            //!< 在两个区间判断角度, 满足任一区间即可, [endAng, 2π], [0, startAng]
            if ((curAng >= endAng && curAng <= 2*PI) ||
                (curAng >= eps && curAng <= startAng)
            {
    
                bIsOn = true;
            }
        }
    }
    //!< 逆时针
    else
    {
    
        //!< 圆弧起始角度 < 终止角度的情况
        if (startAng < endAng)
        {
    
            //!< curAng的值域在[startAng, endAng]
            if (curAng >= startAng && curAng <= endAng)
            {
    
                bIsOn = true;
            }
        }
        //!< 圆弧起始角度 > 终止角度
        else
        {
    
            //!< 逆时针时 起始角度 > 终止角度则说明圆弧经过了0°, 则此时可以
            //!< 在两个区间判断角度, 满足任一区间即可, [startAng, 2π], [0, endAng]
            if ((curAng >= startAng && curAng <= 2*PI) ||
                (curAng >= eps && curAng <= endAng)
            {
    
                bIsOn = true;
            }
        }
    }
    return bIsOn;
}

//!< 判断点是不是在圆弧上
bool isOn(const Point& center, const Point& start, const Point& end, const bool& cw, const Point& curPt, const double& eps)
{
    
    double radius = getLength(center, start);
    double len = getLength(center, pt);
    
    //!< 半径不匹配肯定是不在圆上的
    if (abs(len - radius) > eps)
        return false;

    double curAng = getAngle(m_center, pt);
	return isOn(center, start, end, cw, curAng, eps);
}

圆弧外接矩形计算

不带角度

下图中黑色圆弧为实际圆弧,黑色点为圆的四个顶点位置,绿色为需要计算的圆弧外接矩形,这个时候求圆弧外接矩形是分两种情况的:

  • 小于90°
    小于90°的圆弧

  • 大于等于90°
    大于90°的圆弧

计算
  1. 从圆的上下左右四个顶点中,找出在圆弧上的顶点
  2. 计算出已知点集的外接矩形
#define MAX_NUM  1E20
#define MIN_NUM  -1E20

//!< 外接矩形
struct rect
{
    
    float left;
    float top;
    float right;
    float bottom;
};

//!< 计算圆弧的外接矩形
rect calcRectangle(const Point& center, const Point& start, const Point& end, const bool& cw)
{
    
    rect rc;
    double radius = getLength(center, start);
    
    //!< 如果是个整圆
    if (start == end)
    {
    
        rc.left = center.x - radius;
        rc.right = center.x + radius;
        rc.top = center.y + radius;
        rc.bottom = center.y - radius;
    }
	else
    {
    
        std::vector<sPoint> vArcVertex;
        vArcVertex.push_back(start);
        vArcVertex.push_back(end);    

        //!< 判断圆的四个顶点是不是在圆弧上,在圆弧上的顶点参与计算外接矩形
        sPoint ptCirList[] = {
     center + Point(0, radius), 
            center + Point(radius, 0),
            center + Point(-radius, 0),
            center + Point(0, -radius) };
        for (int i = 0; i < 4; i++)
        {
    
            if (isOn(center, start, end, cw, ptCirList[i], EPS))
            {
    
                vArcVertex.push_back(ptCirList[i]);
            }
        }

        rc.right = rc.top = MIN_NUM;
        rc.left = rc.bottom = MAX_NUM;
        for (auto& pt : vArcVertex)
        {
    
            rc.left = min(rc.left, pt.x);
            rc.right = max(rc.right, pt.x);
            rc.top = max(rc.top, pt.y);
            rc.bottom = min(rc.bottom, pt.y);
        }        
    }
    return rc;
}

圆弧相对距离的点

在这里插入图片描述

//!< 根据某点旋转
void rotate(Point& src, const Point& center, const float& sweepAng)
{
    
    float xOrg = src.x, yOrg = src.y;
    src.x = center.x + (xOrg - center.x) * cos(angle) - (yOrg - center.y) * sin(angle);
    src.y = center.y + (xOrg - center.x) * sin(angle) + (yOrg - center.y) * cos(angle);
}

//!< 圆弧上以起点位置,计算相对偏移distance的点
Point getSatrtOffsetOnArc(const Point& center, const Point& start, const Point& end, const bool& cw, const float& distance)
{
    
    //!< 计算圆弧半径
    double radius = getLength(center, start);
    //!< 圆弧长度对应圆心角
	float sweepAng =  distance / radius;
	Point curPoint = start;
	if (cw)
        sweepAng = -sweepAng;

	rotate(curPoint, center, sweepAng);
	return curPoint;
}

圆弧与线段相交

在这里插入图片描述

计算
  1. 判断圆心到线段的最短距离是不是小于半径,大于半径的时候肯定是不会与圆弧相交的
  2. 求出圆弧与直线的交点,最多两个,需要满足既在圆弧上,也在线段上
//!< 判断点p是否在线段(s, e)上
bool isOnLineSeg(const Point& s, const Point& e, const Point& p, const float& eps)
{
    
    float c = getLength(s, e);
    float a = getLength(s, p);
    float b = getLength(e, p);
    //!< 构成三角形,运用定理两边之和大于第三边,等于第三边则构成线段,点p在线段上
    if (abs(a + b - c) < eps)
        return true;
    else
        return false;
}

//!< 求出圆弧与线段相交的交点
vector<Point> getArcLineSegCross(const Point& center, const Point& start, const Point& end, const bool& cw, const Point& s, const Point& e, const float& eps)
{
    
    float x1 = s.x;
    float y1 = s.y;
    float dx = e.x - s.x;
    float dy = e.y - s.y;

    float cx = center.x;
    float cy = center.y;
    float r = getLength(center, start);

    //!< 圆弧与直线相交,求得两交点的公式
    float a = dx * dx + dy * dy;
    float b = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
    float c = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy) - r * r;

    vector<Point> vCrossPoint;
    float discriminant = b * b - 4 * a * c;
    if (discriminant > eps)
    {
    
        float t1 = (-b + sqrt(discriminant)) / (2 * a);
        float t2 = (-b - sqrt(discriminant)) / (2 * a);
        
        Point intersection1 = {
     x1 + t1 * dx, y1 + t1 * dy };
        Point intersection2 = {
     x1 + t2 * dx, y1 + t2 * dy };
		
        Point intersectionArray[] = {
    intersection1, intersection2};
        
        int resultSize = 2;
        //!< 相切的情况, 只有一个解
        if (abs(t1 - t2) < eps)
        {
    
            resultSize = 1;
        }
        
        for (int i = 0; i < resultSize; i++)
        {
    
            if (isOn(center, start, end, cw, intersectionArray[i], eps) &&
               isOnLineSeg(s, e, intersectionArray[i], eps))
            {
    
             	vCrossPoint.push(intersection1);   
            }
        }        
    }
    return vCrossPoint;
}

线段外与圆相切的问题

需要做的效果

在这里插入图片描述

已知
  1. 已知线段起点终点
  2. 鼠标位置
  3. 需要构建一个相切与该线段的圆,圆弧终点为鼠标当前点,起点为线段端点(就认为是起点吧)
计算
  1. 鼠标位置与线段端点连线组成线段AB,提前可知圆上任意两点连线即(AB)的中垂线必过圆心,所以AB的中垂线必过圆心
  2. 因为原线段需要与所求的圆弧相切,即原线段端点的垂线也必过该圆心
  3. 以上所得两直线的交点即为圆心
//!< 计算线段的中垂线
void getMidPerpendicularLine(const Point& s1, const Point& e1, Point& s2, Point& e2, const float& eps)
{
    
    Point midPoint = (s1 + e1) / 2.0f;
    float len = getLength(s1, e1) / 2.0f;
    if (abs(s1.x - e1.x) < eps && abs(s1.y - e1.y) < eps)
    {
    
        //!< 同一个点, 不做任何处理
    }
    else if (abs(s1.x - e1.x) < eps)
    {
    
        s2.x = midPoint.x;
        s2.y = midPoint.y + len;

        e2.x = midPoint.x;
        e2.y = midPoint.y - len;
    }
    else if (abs(s1.y - e1.y) < eps)
    {
    
        s2.x = midPoint.x + len;
        s2.y = midPoint.y;

        e2.x = midPoint.x - len;
        e2.y = midPoint.y;
    }
    else
    {
    
        //!< 沿着中点随便旋转90°都可以组成中垂线
        s2 = s1;
		rotate(s2, midPoint, PI / 2);
        
        e2 = e1;
		rotate(e2, midPoint, PI / 2);
    }
}

//!< 两直线求交点
bool getLineCross(const Point& p1, const Point& p2, const Point& p3, const Point& p4, sPoint& p, const float& eps)
{
    
    //!< 构建直线L1
    int sign = 1;
    double a1 = p2.y - p1.y;
    if (a1 < eps)
    {
    
        sign = -1;
        a1 = sign * a1;
    }
    double b1 = sign * (p1.x - p2.x);
    double c1 = sign * (p1.y * p2.x - p1.x * p2.y);

    //!< 构建直线L2
    sign = 1;
    double a2 = p4.y - p3.y;
    if (a2 < eps)
    {
    
        sign = -1;
        a2 = sign * a2;
    }
    double b2 = sign * (p3.x - p4.x);
    double c2 = sign * (p3.y * p4.x - p3.x * p4.y);

    //!< 求L1和L2的交点
    double d = a1 * b2 - a2 * b1;
    if (abs(d) < eps) // 不相交 
        return false;
    
    p.x = (c2 * b1 - c1 * b2) / d;
    p.y = (a2 * c1 - a1 * c2) / d;
    return true;
}

//!< 计算相切的圆弧, 假设以线段起点为圆弧起点,鼠标位置为圆弧终点来计算圆弧
//!< 这里需要注意的是,圆弧的方向,需要提前自己确定
void calcTangentArc(const Point& s, const Point& e, const Point& mousePos, Point& center, Point& arcStart, Point& arcEnd, const float& eps)
{
    
    //!< 过线段起点的垂线s, p1
    Point p1;
    rotate(e, s, PI / 2);
    
    //!< 线段的中垂线pArc1, pArc2
    Point pArc1, pArc2;
    getMidPerpendicularLine(s, mousePos, pArc1, pArc2, EPS);
    
    Point pArcCenter;
    //!< 如果有交点,算出圆心
    if (getLineCross(s, p1, pArc1, pArc3, pArcCenter, EPS))
    {
    
        center = pArcCenter;
        arcStart = s;
        arcEnd = mousePos;
    }
}
实现效果

下面的效果中,我是已知轮廓的方向的,所以做出了镜像的圆弧

在这里插入图片描述

圆弧分割成多线段

一些时候画圆弧+线段连起来的时候,一些API并并不能完美的画出来,起点是对的,终点会有些偏差,可能缩小的时候看不出来差别,放大到了节点处会出现断开的情况。一些做法画圆弧,不用画圆弧的函数来做,把圆弧分成很多个线段,连起来。这样起点和终点可以保证正确。

//!< 圆弧分割成多线段集
void vector<Point> toPoints(const Point& center, const Point& start, const Point& end, const bool& cw, const int& ptCnts)
{
    
    std::vector<sPoint> vPts;
    // 起点,圆心,终点
    float radius = getLength(center, start);
    float startAngle = getAngle(center, start);
    float sweepAngle = 0.0f;
    calcArcAngle(center, start, end, cw, sweepAngle)

    sPoint ptCur = start;
    vPts.push_back(ptCur);
    for (int i = 1; i < ptCnts; i++)
    {
    
        ptCur.x = center.x + radius * cos(startAngle + (cw ? -1 : 1) * (sweepAngle * i / count));
        ptCur.y = center.y + radius * sin(startAngle + (cw ? -1 : 1) * (sweepAngle * i / count));
        vPts.push_back(ptCur);
    }
    ptCur = end;
    vPts.push_back(ptCur);

    return vPts;
}

解析实现效果

在这里插入图片描述

最后

感谢各位大佬的无私奉献。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yoyo18520/article/details/135351162

智能推荐

前端开发之vue-grid-layout的使用和实例-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏34次。vue-grid-layout的使用、实例、遇到的问题和解决方案_vue-grid-layout

Power Apps-上传附件控件_powerapps点击按钮上传附件-程序员宅基地

文章浏览阅读218次。然后连接一个数据源,就会在下面自动产生一个添加附件的组件。把这个控件复制粘贴到页面里,就可以单独使用来上传了。插入一个“编辑”窗体。_powerapps点击按钮上传附件

C++ 面向对象(Object-Oriented)的特征 & 构造函数& 析构函数_"object(cnofd[\"ofdrender\"])十条"-程序员宅基地

文章浏览阅读264次。(1) Abstraction (抽象)(2) Polymorphism (多态)(3) Inheritance (继承)(4) Encapsulation (封装)_"object(cnofd[\"ofdrender\"])十条"

修改node_modules源码,并保存,使用patch-package打补丁,git提交代码后,所有人可以用到修改后的_修改 node_modules-程序员宅基地

文章浏览阅读133次。删除node_modules,重新npm install看是否成功。在 package.json 文件中的 scripts 中加入。修改你的第三方库的bug等。然后目录会多出一个目录文件。_修改 node_modules

【】kali--password:su的 Authentication failure问题,&sudo passwd root输入密码时Sorry, try again._password: su: authentication failure-程序员宅基地

文章浏览阅读883次。【代码】【】kali--password:su的 Authentication failure问题,&sudo passwd root输入密码时Sorry, try again._password: su: authentication failure

整理5个优秀的微信小程序开源项目_微信小程序开源模板-程序员宅基地

文章浏览阅读1w次,点赞13次,收藏97次。整理5个优秀的微信小程序开源项目。收集了微信小程序开发过程中会使用到的资料、问题以及第三方组件库。_微信小程序开源模板

随便推点

Centos7最简搭建NFS服务器_centos7 搭建nfs server-程序员宅基地

文章浏览阅读128次。Centos7最简搭建NFS服务器_centos7 搭建nfs server

Springboot整合Mybatis-Plus使用总结(mybatis 坑补充)_mybaitis-plus ruledataobjectattributemapper' and '-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏3次。前言mybatis在持久层框架中还是比较火的,一般项目都是基于ssm。虽然mybatis可以直接在xml中通过SQL语句操作数据库,很是灵活。但正其操作都要通过SQL语句进行,就必须写大量的xml文件,很是麻烦。mybatis-plus就很好的解决了这个问题。..._mybaitis-plus ruledataobjectattributemapper' and 'com.picc.rule.management.d

EECE 1080C / Programming for ECESummer 2022 Laboratory 4: Global Functions Practice_eece1080c-程序员宅基地

文章浏览阅读325次。EECE 1080C / Programming for ECESummer 2022Laboratory 4: Global Functions PracticePlagiarism will not be tolerated:Topics covered:function creation and call statements (emphasis on global functions)Objective:To practice program development b_eece1080c

洛谷p4777 【模板】扩展中国剩余定理-程序员宅基地

文章浏览阅读53次。被同机房早就1年前就学过的东西我现在才学,wtcl。设要求的数为\(x\)。设当前处理到第\(k\)个同余式,设\(M = LCM ^ {k - 1} _ {i - 1}\) ,前\(k - 1\)个的通解就是\(x + i * M\)。那么其实第\(k\)个来说,其实就是求一个\(y\)使得\(x + y * M ≡ a_k(mod b_k)\)转化一下就是\(y * M ...

android 退出应用没有走ondestory方法,[Android基础论]为何Activity退出之后,系统没有调用onDestroy方法?...-程序员宅基地

文章浏览阅读1.3k次。首先,问题是如何出现的?晚上复查代码,发现一个activity没有调用自己的ondestroy方法我表示非常的费解,于是我检查了下代码。发现再finish代码之后接了如下代码finish();System.exit(0);//这就是罪魁祸首为什么这样写会出现问题System.exit(0);////看一下函数的原型public static void exit (int code)//Added ..._android 手动杀死app,activity不执行ondestroy

SylixOS快问快答_select函数 导致堆栈溢出 sylixos-程序员宅基地

文章浏览阅读894次。Q: SylixOS 版权是什么形式, 是否分为<开发版税>和<运行时版税>.A: SylixOS 是开源并免费的操作系统, 支持 BSD/GPL 协议(GPL 版本暂未确定). 没有任何的运行时版税. 您可以用她来做任何 您喜欢做的项目. 也可以修改 SylixOS 的源代码, 不需要支付任何费用. 当然笔者希望您可以将使用 SylixOS 开发的项目 (不需要开源)或对 SylixOS 源码的修改及时告知笔者.需要指出: SylixOS 本身仅是笔者用来提升自己水平而开发的_select函数 导致堆栈溢出 sylixos

推荐文章

热门文章

相关标签