June 7, 2013

Tìm giao cắt giữa hai đối tượng AcDbEntity


Hàm intersectWith()có hai mẫu sau:
virtual  Acad::ErrorStatus
intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
  
virtual  Acad::ErrorStatus
intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    const AcGePlane& projPlane,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
Cấu trúc đầu tiên của hàm intersectWith () kiểm tra sự giao cắt đơn giản của hai thực thể. Hàm thứ hai tính toán giao điểm trên mặt chiếu. Tuy nhiên, cả hai đều trả về các giao điểm nằm trên chính thực thể.

Để sử dụng mặt chiếu trong hàm intersectWith(),
  1. Chiếu hai thực thể vào trong mặt phẳng.
  1. Kiểm tra các thực thể để tìm giao điểm trên mặt chiếu.
  1. Chiếu hình chiếu giao điểm tìm được trở lại thực thể sẽ được giao điểm cần tìm.
Đối tượng mới AsdkPoly sử dụng cả hai mẫu của hàm  intersectWith().
Acad::ErrorStatus
AsdkPoly::intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    AcGePoint3dArray& points,
    int /*thisGsMarker*/,
    int /*otherGsMarker*/) const
{
    assertReadEnabled();
    Acad::ErrorStatus es = Acad::eOk;
    if (ent == NULL)
        return Acad::eNullEntityPointer;
// Ý tưởng là cắt qua từng cạnh của đa giác với thực thể cho trước
// và trả về tất cả các giao điểm.
//
// Với thực thể không phải R12 (phiên bản cũ của AutoCAD) với phương thức
// giao điểm đã được định nghĩa, chúng ta chỉ cần gọi phương thức đó
// với mỗi cạnh của đa giác.
// Với thực thể R12, từ khi các giao thức không được thực hiện,
// chúng ta sử dụng hàm giao điểm riêng cho từng thực thể.
//

// Kiểm tra thực thể có phải là AcDbLine?
    if (ent->isKindOf(AcDbLine::desc())) {
        if ((es = intLine(this, AcDbLine::cast(ent),
            intType, NULL, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDbArc::desc())) {
        if ((es = intArc(this, AcDbArc::cast(ent), intType,
            NULL, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDbCircle::desc())) {
        if ((es = intCircle(this, AcDbCircle::cast(ent),
            intType, NULL, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDb2dPolyline::desc())) {
        if ((es = intPline(this, AcDb2dPolyline::cast(ent),
            intType, NULL, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDb3dPolyline::desc())) {
        if ((es = intPline(this, AcDb3dPolyline::cast(ent),
            intType, NULL, points)) != Acad::eOk)
        {
            return es;
        }
    } else {
        AcGePoint3dArray vertexArray;
        if ((es = getVertices3d(vertexArray))
            != Acad::eOk)
        {
            return es;
        }
        if (intType == AcDb::kExtendArg
            || intType == AcDb::kExtendBoth)
        {
            intType = AcDb::kExtendThis;
        }
        AcDbLine *pAcadLine;
        for (int i = 0; i < vertexArray.length() - 1; i++) {
            pAcadLine = new AcDbLine();
            pAcadLine->setStartPoint(vertexArray[i]);
            pAcadLine->setEndPoint(vertexArray[i + 1]);
            pAcadLine->setNormal(normal());
            if ((es = ent->intersectWith(pAcadLine, intType,
                points)) != Acad::eOk)
            {
                delete pAcadLine;
                return es;
            }
            delete pAcadLine;
        }
    }
    return es;
}

Acad::ErrorStatus
AsdkPoly::intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    const AcGePlane& projPlane,
    AcGePoint3dArray& points,
    int /*thisGsMarker*/,
    int /*otherGsMarker*/) const
{
    assertReadEnabled();
    Acad::ErrorStatus es = Acad::eOk;
    if (ent == NULL)
// Ý tưởng là cắt qua từng cạnh của đa giác với thực thể cho trước
// và trả về tất cả các giao điểm.
//
// Với thực thể không phải R12 (phiên bản cũ của AutoCAD) với phương thức
// giao điểm đã được định nghĩa, chúng ta chỉ cần gọi phương thức đó
// với mỗi cạnh của đa giác.
// Với thực thể R12, từ khi các giao thức không được thực hiện,
// chúng ta sử dụng hàm giao điểm riêng cho từng thực thể.
//
    if (ent->isKindOf(AcDbLine::desc())) {
        if ((es = intLine(this, AcDbLine::cast(ent),
            intType, &projPlane, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDbArc::desc())) {
        if ((es = intArc(this, AcDbArc::cast(ent), intType,
            &projPlane, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDbCircle::desc())) {
        if ((es = intCircle(this, AcDbCircle::cast(ent),
            intType, &projPlane, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDb2dPolyline::desc())) {
        if ((es = intPline(this, AcDb2dPolyline::cast(ent),
            intType, &projPlane, points)) != Acad::eOk)
        {
            return es;
        }
    } else if (ent->isKindOf(AcDb3dPolyline::desc())) {

        if ((es = intPline(this, AcDb3dPolyline::cast(ent),
            intType, &projPlane, points)) != Acad::eOk)
        {
            return es;
        }
    } else {
        AcGePoint3dArray vertexArray;
        if ((es = getVertices3d(vertexArray))
            != Acad::eOk)
        {
            return es;
        }
        if (intType == AcDb::kExtendArg
            || intType == AcDb::kExtendBoth)
        {
            intType = AcDb::kExtendThis;
        }
        AcDbLine *pAcadLine;
        for (int i = 0; i < vertexArray.length() - 1; i++) {
            pAcadLine = new AcDbLine();
            pAcadLine->setStartPoint(vertexArray[i]);
            pAcadLine->setEndPoint(vertexArray[i + 1]);
            pAcadLine->setNormal(normal());
            if ((es = ent->intersectWith(pAcadLine, intType,
                projPlane, points)) != Acad::eOk)
            {
                delete pAcadLine;
                return es;
            }
            delete pAcadLine;
        }
        // Tất cả các điểm ta chọn trong tiến trình này đều nằm trên đường cong kia;
        // chúng ta gắn nó với giao cắt hiển nhiên. Nếu đường đối tượng kia là 3D hoặc không đồng phẳng
        // như poly, các điểm giao cắt sẽ không nằm trên poly nữa.
        //
        // Trong trường hợp này, chúng ta cần làm thêm một số việc khác.
        // Chiếu giao điểm trở lại mặt phẳng, chúng nằm trên hình chiếu của poly
        // Tìm điểm điểm trên poly thật để lấy các giao điểm tương ứng
        //
        AcGePoint3d projPt, planePt;
        AcGePoint3dArray pts;
        AcGeLine3d line;
       
        AcGePlane polyPlane;
        AcDb::Planarity plnrty;
        getPlane(polyPlane,plnrty);
        for (i = 0; i < points.length(); i++) {
            // Định nghĩa một đường thẳng xuất phát từ mặt phẳng projPt nằm
            // dọc theo vector. Xác định giao cắt của đa giác với đường thẳng đó.
            // Tìm mọi điểm và nhặt điểm một gần nhất..
            //
            projPt = points[i].orthoProject(projPlane);
            line.set(projPt, projPlane.normal());
            if ((es = intLine(this, line, pts))
                != Acad::eOk)
            {
                return es;
            }
            planePt = projPt.project(polyPlane,
                projPlane.normal());
            points[i] = pts[0];
            double length = (planePt - pts[0]).length();
            double length2;
            for (int j = 1; j < pts.length(); j++) {
                if ((length2 = (planePt - pts[j]).length())
                    < length)
                {
                    points[i] = pts[j];
                    length = length2;
                }
            }
        }
    }
    return es;
}


No comments:

Post a Comment

Featured Post

Lisp Copy tăng số trong AutoCAD | AutoLISP That la don gian

Ứng dụng được phát triển bởi đội ngũ AutoLISP Thật là đơn giản       Thông tin thêm: 👉👉👉

Popular Posts