
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 - . , , . . - . ,
( ) - , , , , .
gp( - geometry primitives)- , .
Geom( ) - , , . - (vertex), (edge) , , (wire) - , (face) - , (shell) - , , (solid) - , . , - 3D- . . - , (boundary representation),
BRepTopo- , . , , , ,
AIS).
, .
, . , . Python - . , , , . , , .
OpenCascade OpenCascade . - Google. .
OpenCascade, C++, Tcl, Java. Python.
, . , . , .
. .
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')

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')

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')

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')

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')
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)
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)
WebGL-: 07
, , - . , , . , .
Open Source
3D--. . :
GitHub - - , .
, 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)