OpenCASCADE dan Matahari Tao yang Tak Terlihat

Pelancong terbaik yang tidak meninggalkan jejak

Pemimpin terbaik yang menginspirasi tanpa ucapan

Rencana itu sempurna, jika tidak ada rencana sama sekali

Dan jika orang bijak menutup pintu,

Anda tidak akan pernah mengungkap rahasianya.

The Great Book of Tao - Ayat 27 (Terjemahan oleh Y. Polezhaeva)

, ! 3D-. 3D. , , - . .

, , CAD-. 3D-. , , . , . , , CAD- 3D " ".

, CAD- OpenCascade. CAD-. , Python.

, . - . - . .

-

, CAD-, . ? , , , 3D-.

, . : " ?" . , , . , , .

. - 3D-. .

1.

OpenCascade . c Win64. , Linux , , .

OpenCascade - Python 3.7 - Win64

, OpenCascade

, conda ( ) , . , . .

2.

. , , .

#initMode = 'screen','web','stl'
def ScInit(initMode, decoration, precision, exportDir):
  pass

#default styles
#'stInfo' - for service objects
#'stMain' - for main object of drawing
#'stFocus' - for important details
def ScStyle(styleVal):
  pass

#draw objects
def ScPoint(pnt, style):
  pass
def ScLine(pnt1, pnt2, style):
  pass
def ScCircle(pnt1, pnt2, pnt3, style):
  pass
def ScShape(shape, style):
  pass
def ScLabel(pnt, text, style):
  pass

#start render
def ScStart()    

, PythonOCC, OpenCascade (c SWIG) Python-, , , .

3. OpenCASCADE

OpenCascade - . , , . . - . ,

  1. ( ) - , , , , . gp ( - geometry primitives)

  2. - , . Geom

  3. ( ) - , , . - (vertex), (edge) , , (wire) - , (face) - , (shell) - , , (solid) - , . , - 3D- . . - , (boundary representation), BRep Topo

  4. - , . , , , , AIS).

, .

  1. , . , . Python - . , , , . , , .

  2. OpenCascade OpenCascade . - Google. .

  3. OpenCascade, C++, Tcl, Java. Python.

  4. , . , . , .

. .

4. .

- r - . . . , - . .

, - , . , . - , . - - , .

( - , , ):

def getPntsBase(r):
    
    r2 = r/2
    
    gpPntMinC = gp_Pnt(0,r2,0)
    
    p0 = gp_Pnt(0,0,0)      
    p1 = getPntRotate(gpPntMinC , p0, -pi/4)      
    p2 = gp_Pnt(-r2,r2,0)      
    p3 = getPntRotate(gpPntMinC , p0, -pi/4*3)      
    p4 = gp_Pnt(0,r,0)      
    p5 = gp_Pnt(r,0,0)      
    p6 = gp_Pnt(0,-r,0)      
    p7 = gp_Pnt(r2,-r2,0)      
    
    return p0, p1, p2, p3, p4, p5, p6, p7
  
def getWireDaoClassic(ppBase):
    
    p0, p1, p2, p3, p4, p5, p6, p7  = ppBase
    
    arc1 =  GC_MakeArcOfCircle(p0,p1,p2).Value()
    arc2 =  GC_MakeArcOfCircle(p2,p3,p4).Value()
    arc3 =  GC_MakeArcOfCircle(p4,p5,p6).Value()
    arc4 =  GC_MakeArcOfCircle(p6,p7,p0).Value()
 
    edge1 = BRepBuilderAPI_MakeEdge(arc1).Edge()
    edge2 = BRepBuilderAPI_MakeEdge(arc2).Edge()
    edge3 = BRepBuilderAPI_MakeEdge(arc3).Edge()
    edge4 = BRepBuilderAPI_MakeEdge(arc4).Edge()
  
    shape =  BRepBuilderAPI_MakeWire(edge1, edge2, edge3, edge4).Wire()
    
    return shape
 
def slide_01_DaoClassic(r):
    
    drawCircle(r, 'stInfo')
    pntsBase = getPntsBase(r)
    drawPoints(pntsBase, 'stFocus', 'b')
    shapeDaoClassic = getWireDaoClassic(pntsBase)
    ScShape(shapeDaoClassic, 'stMain')
Gambar 01. Garis besar Tao klasik
01.

WebGL-: 01

. 3D- 3D- -. 3D - 1 - - 2 - SideBySide.

- - .


, , 6- , , CAD- . , , - . 3D- , , , .

DegreeToRadian. pi pi, pi/4, -pi/8 . - , , . 9- . - , , - . , .

. 8 , - , . , . - 1 - 1 , 2 - 2 . , , , .


, .

5.

, . . , .

. . Offset. - .

def getShapeOffset(shape, offset):
    tool = BRepOffsetAPI_MakeOffset()
    tool.AddWire(shape)
    tool.Perform(offset)
    shape = tool.Shape()  
    return shape

def slide_02_DaoConcept(r, offset):
    
    drawCircle(r + offset, 'stInfo')
    pntsBase = getPntsBase(r)
    wireDaoClassic = getWireDaoClassic(pntsBase)
    wireDao0 = getShapeOffset(wireDaoClassic, -offset)
    ScShape(wireDao0, 'stMain')
  
    pntsDao0 = getPntsOfShape(wireDao0)
    drawPoints(pntsDao0, 'stFocus', 'd')
  
    wireDao1 = getShapeOZRotate(wireDao0, pi)
    ScShape(wireDao1, 'stInfo')
Gambar 02. Garis Besar Tao menjorok
02.

WebGL-: 02

, . , . . . - 3D.

6. . .

? , . - . . - , .

, - , . -.

. , , - . . ? , . , Y -r/4 .

k. = 0 . k = 1 . . - ( )

def getPntDaoFocus(r):
    return gp_Pnt(0,-r/4,0)


def getPntsForDaoSec(pntDaoStart, pntUpLimit, pntDaoEnd, pntDownLimit, pntFocus, k):
    angleLimit = 0
    pntLimit = getPntScale(pntFocus, pntUpLimit, 1.2)
    angleStart = getAngle(pntFocus, pntLimit, pntDaoStart)
    angleEnd = getAngle(pntFocus, pntLimit, pntDaoEnd)
    kLimit = (angleLimit - angleStart)/(angleEnd - angleStart)
    if k < kLimit: #head
        kHead = (k - 0) / (kLimit- 0)
        xStart = pntUpLimit.X()
        xEnd = pntDaoStart.X()
        dx = (xEnd-xStart)*(1 - kHead)
        pnt0 = getPntTranslate(pntFocus, dx, 0, 0)
        pnt1 = getPntTranslate(pntLimit, dx, 0, 0)
    else: #tail    
        kTail = (k - kLimit) / (1 - kLimit)
        angle = -angleEnd*kTail
        pnt0 = pntFocus
        pnt1 = getPntRotate(pntFocus, pntLimit, angle)
    return pnt0, pnt1


def getWireDaoSec(shapeDao, pntFocus, k):
    
    pntsDao = getPntsOfShape(shapeDao)
    pntDownLimit, pntDaoStart, pntUpLimit, pntDaoEnd = pntsDao
    
    p1, p2 = getPntsForDaoSec(pntDaoStart, pntUpLimit, pntDaoEnd, pntDownLimit, 
                              pntFocus, k)
    sectionPlane = getFacePlane(p1, p2, 3)
    
    pnt0, pnt1 =  getPntsEdgesFacesIntersect(shapeDao, sectionPlane)
    pntUp = getPntSectionUp(pnt0, pnt1)
    circle = GC_MakeCircle(pnt0, pntUp, pnt1).Value()
    edge = BRepBuilderAPI_MakeEdge(circle).Edge()
    wire =  BRepBuilderAPI_MakeWire(edge).Wire()
    return wire

   
def slide_03_DaoSecPrincipe(r, offset, k, h):
    
    drawCircle(r + offset,  'stInfo')
    pntsBase = getPntsBase(r)
    wireDaoClassic = getWireDaoClassic(pntsBase)
    wireDao0 = getShapeOffset(wireDaoClassic, -offset)
    ScShape(wireDao0, 'stMain')
    
    # for oure goal we need divide Dao on Head and Tail
    # Head sections is parallell
    # Tail sections is focused on focus point
    pntsDao0 = getPntsOfShape(wireDao0)
    pntDownLimit, pntDaoStart, pntUpLimit, pntDaoEnd  = pntsDao0
    
    # we need focus to determine tail sections 
    pntFocus = getPntDaoFocus(r)
    ScPoint(pntFocus, 'stMain')
    ScLabel(pntFocus, 'F' ,'stMain')
    
    # we need two points to determine section
    pnt1, pnt2 = getPntsForDaoSec(pntDaoStart, pntUpLimit, pntDaoEnd, 
                                  pntDownLimit, pntFocus, k)
    ScLine(pnt1, pnt2, 'stFocus')
    
    # !!! we need use plane to detect intercsect (not line) becouse 3D
    planeSec = getFacePlane(pnt1, pnt2, h)
    ScShape(planeSec, 'stFocus')

    pntsSec =  getPntsEdgesFacesIntersect(wireDao0, planeSec)
    drawPoints(pntsSec, 'stFocus')
    
    wireSec = getWireDaoSec(wireDao0, pntFocus, k)
    ScShape(wireSec, 'stFocus') 
Gambar 03 Prinsip konstruksi bagian
03

WebGL-: 03

- . -. , , k. . , . , .

? - ? , . , 3D . .

2D, . 2D 3D , . , 3D :) 3D .


, 3D-. , - , - , . - .

. . , .

. , , , 3D-. , , , , . , - , , . . 3D- (, ).

( ). ( ), , . , - ( ). . , . . , . . - , - - . . , . , , .


, .

, , . . , k 0 1 c .

def slide_04_DaoManySec(r, offset, kStart, kEnd, cnt):
    
    drawCircle(r + offset, 'stInfo')
    pntsBase = getPntsBase(r)
    wireDaoClassic = getWireDaoClassic(pntsBase)
    wireDao0 = getShapeOffset(wireDaoClassic, -offset)
    ScShape(wireDao0, 'stMain')
    
    pntsDao0 = getPntsOfShape(wireDao0)
    pntDownLimit, pntDaoStart, pntUpLimit, pntDaoEnd  = pntsDao0
    
    pntFocus = getPntDaoFocus(r)
    
    for i in range(cnt+1):
        k = i/cnt
        kkScale = kEnd - kStart
        kk = kStart + k* kkScale
        p0,p1 = getPntsForDaoSec(pntDaoStart, pntUpLimit, pntDaoEnd, 
        pntDownLimit, pntFocus, kk)
        ScLine(p0, p1, 'stFocus')
        wireSec = getWireDaoSec(wireDao0, pntFocus, kk)
        ScShape(wireSec, 'stMain') 
Gambar 04 Bentuk Tao dari penampang
04

WebGL-: 04

. ? ?

, . , . . ( ), ( ).

- , . .

7.

- , . . - . , . - , , , . , .

.

  • Python , .

  • , . . .

. , , - . .

def slide_05_DaoSkinning (r, offset):
    
    drawCircle(r + offset,  'stInfo')
    pntsBase = getPntsBase(r)
    wireDaoClassic = getWireDaoClassic(pntsBase)
    wireDao0 = getShapeOffset(wireDaoClassic, -offset)
    ScShape(wireDao0, 'stMain')
    
    pntsDao0 = getPntsOfShape(wireDao0)
    pntDownLimit, pntDaoStart, pntUpLimit, pntDaoEnd  = pntsDao0
    
    pntFocus = getPntDaoFocus(r)
    drawPoints(pntFocus, 'stMain')
  
    ks = [ 3, 9 , 16, 24, 35, 50, 70, 85] 
    wiresSec = []
 
    for k in  ks:
       wireSec = getWireDaoSec(wireDao0, pntFocus, k/100)
       ScShape(wireSec, 'stMain')
       wiresSec += [wireSec]    
    
    solidDao0 = getShapeSkin(pntDaoStart, wiresSec, pntDaoEnd)
    ScShape(solidDao0, 'stFocus')
Gbr 05 Menarik permukaan melalui beberapa bagian
05

WebGL-: 05

, . , , . , . - . . - .

. . OpenCascade gp_Trsf. . . , . . . .

. OpenCascade . . gp_GTrsf. .

180 ... , pi ... , ... pi :) .

def getSolidDao(r, offset):
    
    pntsBase = getPntsBase(r)
    wireDaoClassic = getWireDaoClassic(pntsBase)
    wireDao = getShapeOffset(wireDaoClassic, -offset)
    
    pntsDao = getPntsOfShape(wireDao)
    pntDownLimit, pntDaoStart, pntUpLimit, pntDaoEnd  = pntsDao
    
    pntFocus = getPntDaoFocus(r)
   
    ks = [ 3, 9 , 16, 24, 35, 50, 70, 85] 
    wiresSec = []
 
    for k in  ks:
       wireSec = getWireDaoSec(wireDao, pntFocus, k/100)
       wiresSec += [wireSec]    
    
    solidDao = getShapeSkin(pntDaoStart, wiresSec, pntDaoEnd)
    solidDao = getShapeZScale(solidDao, 0.7)
    return solidDao
   
def slide_06_DaoComplete (r, offset):
    
    solidDao0 = getSolidDao(r, offset)
    ScShape(solidDao0, stDao0)
    solidDao1  = getShapeOZRotate(solidDao0, pi)
    ScShape(solidDao1, stDao1)

Gambar 06 Bentuk Akhir dari Tao
06

WebGL-: 06

8.

, , . .

- . , - . Open Source.

, . , , gap - - - 1 .

def getDaoCase(r, offset, h):
    r2 = r*2                                    
    h2 = h/2
    rTop = r + offset
    rSphere = gp_Vec(0,rTop,h2).Magnitude()
    sphere = BRepPrimAPI_MakeSphere(rSphere).Shape()
    limit = BRepPrimAPI_MakeBox( gp_Pnt(-r2, -r2, -h2), gp_Pnt(r2, r2, h2) ).Shape()
    case = BRepAlgoAPI_Common(sphere, limit).Shape()
    case = getShapeTranslate(case, 0,0,-h2)
 
    
    solidDao0 = getSolidDao(r, offset)
    solidDao1  = getShapeOZRotate(solidDao0, pi)
   
    case = BRepAlgoAPI_Cut(case, solidDao0).Shape()
    case = BRepAlgoAPI_Cut(case, solidDao1).Shape()
  
    return case
    
def slide_07_DaoWithCase (r, offset, caseH, caseZMove ,gap):
    
    solidDao0 = getSolidDao(r, offset+gap)
    ScShape(solidDao0, stDao0)
    solidDao1  = getShapeOZRotate(solidDao0, pi)
    ScShape(solidDao1, stDao1)
    
    case = getDaoCase(r, offset, caseH)
    
    case = getShapeTranslate(case, 0,0, caseZMove)
    ScShape(case, stCase)
Gambar 07. Bentuk Tao dengan alas
07.

WebGL-: 07

, , - . , , . , .

Open Source

3D--. . :

, OpenCascade. , . . , . . .

Kita perlu tahu kapan harus berhenti

Kapal tidak bisa diisi berlebihan

Nilai-nilai yang besar lebih sulit untuk dijaga

Dan pedang yang terlalu tajam akan cepat tumpul Dengan

pangkat yang baik terlalu bangga

Untuk memanggil rumahmu ke rumahmu

Pekerjaanmu sudah selesai, jadi bisa pergi

Inilah arti dari kekuatan, kehidupan dan jalan

The Great Book of Tao - Ayat 9 (Terjemahan oleh Y. Polezhaeva)




All Articles