
Der beste Reisende, der keine Spuren hinterlässt
Der beste Führer, der ohne Sprache inspiriert
Der Plan ist perfekt, wenn es überhaupt keinen Plan gibt
Und wenn ein weiser Mann die Tür schließt, werden
Sie das Geheimnis niemals lösen.
Das große Buch des Tao - Vers 27 (Übersetzung von 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. , . . , . . .
Wir müssen wissen, wann wir anhalten müssen. Das
Schiff kann nicht überfüllt werden.
Große Werte sind schwieriger zu bewachen.
Und ein zu scharfes Schwert wird schneller stumpf. Mit einem
guten Rang, der zu stolz ist.
Um
Ihr Haus anzurufen. Ihre Arbeit ist beendet. Sie können also gehen.
Dies ist der Sinn für Stärke, Leben und Weg.
Das große Buch des Tao - Vers 9 (Übersetzt von Y. Polezhaeva)