1ca6efa10a
- slicing multiplanare orizzontale - sistemata distanza su spina per slicing multiplanare 45°.
1005 lines
45 KiB
Lua
1005 lines
45 KiB
Lua
-- RunCalcSolids.lua by Egaltech s.r.l. 2022/11/02
|
|
-- Calcolo percorsi di lavoro per Stampa 3d
|
|
|
|
-- Tabella per definizione modulo
|
|
local RunCalcSolids = {}
|
|
|
|
-- Intestazioni
|
|
require( 'EgtBase')
|
|
|
|
EgtOutLog( ' RunCalcSolids started', 1)
|
|
|
|
-- Dati
|
|
local AMD = require( 'AddManData')
|
|
|
|
--------------------------------------------------------------------
|
|
local s_dTol = 0.1
|
|
local s_nSimplifiedSection = 0
|
|
local s_dMultiPlanarH = 0
|
|
local s_dColorFactor = 0.9
|
|
local s_nPartId
|
|
|
|
---------------------------------------------------------------------
|
|
local function GetLayerParamsForSolidCalc( nPartId)
|
|
local LayerParams = {}
|
|
LayerParams.bSpiralVase = EgtGetInfo( nPartId, KEY_SPIRAL_VASE, 'b') or false
|
|
LayerParams.dLayHeight = EgtGetInfo( nPartId, KEY_SLICE_STEP, 'd')
|
|
LayerParams.vtSlicing = EgtGetInfo( nPartId, KEY_SLICE_DIR, 'v') or EgtGetInfo( nPartId, 'SlicingDir', 'v')
|
|
LayerParams.dStrand = EgtGetInfo( nPartId, KEY_STRAND, 'd')
|
|
LayerParams.vtCorr = EgtGetInfo( nPartId, KEY_MOVED_PART2, 'v') or V_NULL()
|
|
return LayerParams
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CalcSectionParams( dStrand, dH)
|
|
local dBevelX = 0
|
|
local dBevelY = 0
|
|
if s_nSimplifiedSection == 0 then
|
|
-- sezione ottagonale
|
|
dBevelX = dStrand / 10
|
|
dBevelY = dH / 6
|
|
end
|
|
return dBevelX, dBevelY
|
|
end
|
|
|
|
----------------------------------------------------------------------
|
|
local function CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand)
|
|
|
|
local dBevelX, dBevelY = CalcSectionParams( dStrand, dH)
|
|
local nSrfId = EgtSurfTmRectSwept( nSolidGrp, dStrand, dH, dBevelX, dBevelY, nCrvId, GDB_RSCT.BEVEL, s_dTol)
|
|
return nSrfId
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CreateSection( ptS, vtDir, dStrand, dH, vtSlicing, nSolidGrp)
|
|
|
|
local dBevelX, dBevelY = CalcSectionParams( dStrand, dH)
|
|
local ptA = ptS - dH * vtSlicing + ( 0.5 * dStrand - dBevelX) * vtDir
|
|
local ptB = ptA + dBevelY * vtSlicing + dBevelX * vtDir
|
|
local ptC = ptB + ( dH - 2 * dBevelY) * vtSlicing
|
|
local ptD = ptA + dH * vtSlicing
|
|
local ptE = ptD - ( dStrand - 2 * dBevelX) * vtDir
|
|
local ptF = ptC - dStrand * vtDir
|
|
local ptG = ptB - dStrand * vtDir
|
|
local ptH = ptA - ( dStrand - 2 * dBevelX) * vtDir
|
|
|
|
local nId = EgtCurveCompoFromPoints( nSolidGrp, {ptA, ptB, ptC, ptD, ptE, ptF, ptG, ptH, ptA}, GDB_RT.GLOB)
|
|
EgtInvertCurve( nId)
|
|
|
|
return nId
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
local function CreateSpiralVaseCap( nSectId, vtDir, nSolidGrp)
|
|
|
|
local vPt = {}
|
|
local nLast = EgtIf( s_nSimplifiedSection == 1, 3, 7)
|
|
for i = 0, nLast do
|
|
vPt[i + 1] = EgtUP( nSectId, i, GDB_ID.ROOT)
|
|
end
|
|
|
|
local vCrvs = {}
|
|
-- calcolo gli archi che definiscono la superficie laterale
|
|
if s_nSimplifiedSection == 1 then
|
|
-- sezione quadrata
|
|
vCrvs[1] = EgtArc2PV( nSolidGrp, vPt[1], vPt[2], vtDir, GDB_RT.GLOB)
|
|
vCrvs[2] = EgtArc2PV( nSolidGrp, vPt[4], vPt[3], vtDir, GDB_RT.GLOB)
|
|
else
|
|
-- sezione ottagonale
|
|
vCrvs[1] = EgtArc2PV( nSolidGrp, vPt[1], vPt[2], vtDir, GDB_RT.GLOB)
|
|
vCrvs[2] = EgtArc2PV( nSolidGrp, vPt[8], vPt[3], vtDir, GDB_RT.GLOB)
|
|
vCrvs[3] = EgtArc2PV( nSolidGrp, vPt[7], vPt[4], vtDir, GDB_RT.GLOB)
|
|
vCrvs[4] = EgtArc2PV( nSolidGrp, vPt[6], vPt[5], vtDir, GDB_RT.GLOB)
|
|
end
|
|
-- creo le rigate
|
|
local vSurfs = {}
|
|
for i = 1, #vCrvs - 1 do
|
|
vSurfs[i] = EgtSurfTmRuled( nSolidGrp, vCrvs[i], vCrvs[i+1], GDB_RUL.ISOPAR, s_dTol)
|
|
end
|
|
-- calcolo le superfici top e bottom del cap
|
|
local nCrvBottom = EgtCurveCompo( nSolidGrp, {vCrvs[1]}, false, GDB_RT.GLOB)
|
|
EgtCloseCurveCompo( nCrvBottom)
|
|
local nSurfBottom = EgtSurfTmByRegion( nSolidGrp, nCrvBottom, s_dTol)
|
|
local nCrvTop = EgtCurveCompo( nSolidGrp, {vCrvs[#vCrvs]}, false, GDB_RT.GLOB)
|
|
EgtCloseCurveCompo( nCrvTop)
|
|
local nSurfTop = EgtSurfTmByRegion( nSolidGrp, nCrvTop, s_dTol)
|
|
table.insert( vSurfs, nSurfTop)
|
|
table.insert( vSurfs, nSurfBottom)
|
|
|
|
local nCapSrf = EgtSurfTmByTriangles( nSolidGrp, vSurfs)
|
|
|
|
-- cancello curve di costruzione
|
|
EgtErase( vCrvs)
|
|
EgtErase( nCrvTop)
|
|
EgtErase( nCrvBottom)
|
|
|
|
return nCapSrf
|
|
end
|
|
|
|
-------------------------------------------------------------------------------
|
|
local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, vtSlicing, dH, dStrand)
|
|
|
|
-- gruppo temporaneo per conti
|
|
local nGrpTmp = EgtGroup( nSolidGrp, Frame3d( ORIG(), vtSlicing, GDB_RT.GLOB))
|
|
|
|
-- accorcio leggermente la curva per evitare problemi di inconsistent orientation nel solido
|
|
local dLen = EgtCurveLength( nCrvId)
|
|
EgtTrimCurveEndAtLen( nCrvId, dLen - 20 * GEO.EPS_SMALL)
|
|
|
|
local ptS = EgtSP( nCrvId, GDB_ID.ROOT)
|
|
local vtS = EgtSV( nCrvId, GDB_ID.ROOT)
|
|
local ptE = EgtEP( nCrvId, GDB_ID.ROOT)
|
|
local vtE = EgtEV( nCrvId, GDB_ID.ROOT)
|
|
local dDelta = ( ptE - ptS) * vtSlicing
|
|
-- se non è vero spiral vase, chiamo funzione standard
|
|
if dDelta < GEO.EPS_SMALL then
|
|
EgtErase( nGrpTmp)
|
|
return CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand)
|
|
end
|
|
|
|
-- appiattisco la curva
|
|
local nCrvCopy = EgtCopyGlob( nCrvId, nGrpTmp)
|
|
EgtModifyCurveExtrusion( nCrvCopy, vtSlicing, GDB_RT.GLOB)
|
|
EgtProjectCurveOnPlane( nCrvCopy, ptS, vtSlicing, GDB_RT.GLOB)
|
|
EgtMergeCurvesInCurveCompo( nCrvCopy)
|
|
EgtChangeClosedCurveStartPoint( nCrvCopy, ptS, GDB_RT.GLOB)
|
|
|
|
-- calcolo la sezione iniziale
|
|
local vtDir = EgtSV( nCrvCopy, GDB_ID.ROOT)
|
|
vtDir:rotate( vtSlicing, 90)
|
|
local nSectId = CreateSection( ptS, vtDir, dStrand, dH, vtSlicing, nGrpTmp)
|
|
-- creo la sezione finale
|
|
local vtDir2 = EgtEV( nCrvCopy, GDB_ID.ROOT)
|
|
vtDir2:rotate( vtSlicing, 90)
|
|
local nSectE = CreateSection( ptE, vtDir2, dStrand, dH, vtSlicing, nGrpTmp)
|
|
|
|
-- creo il solido aperto (tubo)
|
|
local vCrvs = {}
|
|
local _, dParE = EgtCurveDomain( nSectId)
|
|
for i = 0, dParE do
|
|
local ptRef = EgtUP( nSectId, i, GDB_ID.ROOT)
|
|
local dOffs = ( ptS - ptRef) * vtDir
|
|
vCrvs[i+1] = EgtOffsetCurveAdv( nCrvCopy, dOffs)
|
|
if not vCrvs[i+1] or vCrvs[i+1] == GDB_ID.NULL then
|
|
EgtErase( nGrpTmp)
|
|
return nil
|
|
end
|
|
local dMove = ( ptRef - ptS) * vtSlicing
|
|
EgtMove( vCrvs[i+1], vtSlicing * dMove, GDB_RT.GLOB)
|
|
EgtSpiralizeCurveAlongExtrusion( vCrvs[i+1], dDelta)
|
|
|
|
-- modifico la curva per congiungerla ai caps
|
|
EgtApproxCurve( vCrvs[i+1], GDB_CA.LINES, s_dTol)
|
|
EgtModifyCurveStartPoint( vCrvs[i+1], ptRef, GDB_RT.GLOB)
|
|
local ptRefEnd = EgtUP( nSectE, i, GDB_ID.ROOT)
|
|
local _, _, dParMinDist = EgtPointCurveDist( ptRefEnd, vCrvs[i+1], GDB_ID.ROOT)
|
|
local _, dParE = EgtCurveDomain( vCrvs[i+1])
|
|
if abs( dParE - dParMinDist) > GEO.EPS_SMALL and dParMinDist > 0.5 * dParE then
|
|
EgtTrimCurveEndAtParam( vCrvs[i+1], dParMinDist)
|
|
end
|
|
EgtModifyCurveEndPoint( vCrvs[i+1], ptRefEnd, GDB_RT.GLOB)
|
|
end
|
|
|
|
local vSurfs = {}
|
|
for i = 1, #vCrvs - 1 do
|
|
vSurfs[i] = EgtSurfTmRuled( nGrpTmp, vCrvs[i], vCrvs[i+1], GDB_RUL.MINDIST, s_dTol)
|
|
if not vSurfs[i] or vSurfs[i] == GDB_ID.NULL then
|
|
EgtErase( nGrpTmp)
|
|
return nil
|
|
end
|
|
end
|
|
|
|
-- creazione del mezzo disco iniziale
|
|
vSurfs[#vCrvs] = CreateSpiralVaseCap( nSectId, - vtS, nSolidGrp)
|
|
-- creazione del mezzo disco finale
|
|
vSurfs[#vCrvs+1] = CreateSpiralVaseCap( nSectE, vtE, nSolidGrp)
|
|
EgtInvertSurf( vSurfs[#vCrvs+1])
|
|
|
|
local nSolidId = EgtSurfTmByTriangles( nSolidGrp, vSurfs)
|
|
|
|
-- cancello le curve usate per la costruzione
|
|
EgtErase( nGrpTmp)
|
|
|
|
return nSolidId
|
|
end
|
|
|
|
--------------------------------------------------------------------------------------
|
|
local function CreateSolid( nCrvId, nSolidGrp, LayerParams, dH, dStrand)
|
|
if LayerParams.bSpiralVase then
|
|
return CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams.vtSlicing, dH, dStrand)
|
|
else
|
|
return CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand)
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CreateDirectionArrow( nCrvId, nSolidGrp, vtSlicing, dStrand, nSliceNbr)
|
|
|
|
local ptS = EgtSP( nCrvId, GDB_RT.GLOB)
|
|
local vtS = EgtSV( nCrvId, GDB_RT.GLOB)
|
|
local dCrvLen = EgtCurveLength( nCrvId)
|
|
if dCrvLen > 2 * dStrand then
|
|
local dPar = EgtCurveParamAtLength( nCrvId, 4/5 * dStrand)
|
|
ptS = EgtUP( nCrvId, dPar, GDB_RT.GLOB)
|
|
vtS = EgtUV( nCrvId, dPar, -1, GDB_RT.GLOB)
|
|
end
|
|
|
|
local vt2 = Vector3d( vtS)
|
|
vt2:rotate( vtSlicing, 90)
|
|
local dLen = 4/5 * dStrand
|
|
local pt1 = ptS + 0.5 * dLen * vt2
|
|
local pt2 = ptS - 0.5 * dLen * vt2
|
|
local pt3 = ptS + vtS * dLen
|
|
local nCompo = EgtCurveCompoFromPoints( nSolidGrp, { pt1, pt2, pt3, pt1}, GDB_RT.GLOB)
|
|
EgtMove( nCompo, 100 * GEO.EPS_SMALL * vtSlicing, GDB_RT.GLOB)
|
|
local nSrf = EgtSurfFlatRegion( nSolidGrp, { nCompo})
|
|
EgtErase( nCompo)
|
|
EgtSetColor( nSrf, RED())
|
|
EgtSetInfo( nSrf, KEY_SLICE_NBR, nSliceNbr)
|
|
EgtSetStatus( nSrf, GDB_ST.OFF)
|
|
EgtSetMode( nSrf, GDB_MD.HIDDEN)
|
|
EgtSetName( nSrf, DIR_ARROW)
|
|
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dH, dStrand)
|
|
|
|
-- tento la creazione del solido
|
|
local nSurf = CreateSolid( nCrvId, nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL)
|
|
if nSurf then
|
|
EgtErase( nCrvId)
|
|
table.insert( vSurfs, nSurf)
|
|
return true
|
|
else
|
|
-- se curva singola esco perchè non è possibile spezzare ulteriormente
|
|
local _, dParE = EgtCurveDomain( nCrvId)
|
|
if abs( dParE - 1) < GEO.EPS_SMALL then
|
|
EgtErase( nCrvId)
|
|
return false
|
|
end
|
|
-- se non si tratta di curva singola, spezzo a metà e tento sulle due sottocurve
|
|
local dParSplit = floor( dParE / 2 + 0.5)
|
|
local nCrvSplit = EgtSplitCurveAtParam( nCrvId, dParSplit)
|
|
if not nCrvSplit then
|
|
-- errore nello split
|
|
EgtErase( nCrvId)
|
|
return false
|
|
end
|
|
local bOk = CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dH, dStrand)
|
|
bOk = bOk and CreateRecursiveSolid( nCrvSplit, vSurfs, nSolidGrp, LayerParams, dH, dStrand)
|
|
return bOk
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CalcSolidGuides( nCrvId, dStrand, nSolidGrp)
|
|
|
|
-- suddivido la curva in modo opportuno
|
|
local nCopyId = EgtCopyGlob( nCrvId, nSolidGrp)
|
|
local nId
|
|
local nParts = 1
|
|
local LEN_REF = 100
|
|
local bZigZagInfill = EgtGetInfo( nCopyId, KEY_ZIG_ZAG_INFILL, 'b') or false
|
|
if bZigZagInfill then
|
|
nId, nParts = EgtSplitCurveAtCorners( nCopyId, 80)
|
|
else
|
|
local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i')
|
|
local dLen = EgtCurveLength( nCrvId)
|
|
if dLen > LEN_REF and nType ~= TYPE.LINK and nType ~= TYPE.COASTING then
|
|
nParts = EgtClamp( floor( dLen / LEN_REF), 1, 10)
|
|
end
|
|
nId = EgtSplitCurve( nCopyId, nParts)
|
|
end
|
|
|
|
if not nId then return end
|
|
|
|
-- verifico in modo euristico se la curva torna indietro su se stessa come se fossero due shell collegate ( verifico se è presente un sottotratto di lunghezza
|
|
-- circa pari allo strand non in tangenza con i sottotratti vicini). Nel caso la spezzo per evitare problemi nel calcolo di solidi swept
|
|
local vGuideIds = {}
|
|
for nInd = 0, nParts - 1 do
|
|
local nGuideId = nId + nInd
|
|
table.insert( vGuideIds, nGuideId)
|
|
if EgtGetType( nGuideId) == GDB_TY.CRV_COMPO then
|
|
local _, dE = EgtCurveDomain( nGuideId)
|
|
for dU = 1, dE - 2 do
|
|
local dLen = EgtCurveCompoLength( nGuideId, dU)
|
|
if abs( dLen - dStrand) < 500 * GEO.EPS_SMALL then
|
|
-- verifico gli angoli
|
|
local vtPrev = EgtUV( nGuideId, dU, -1, GDB_ID.ROOT)
|
|
local vtCurrS = EgtUV( nGuideId, dU, 1, GDB_ID.ROOT)
|
|
local vtCurrE = EgtUV( nGuideId, dU + 1, -1, GDB_ID.ROOT)
|
|
local vtNext = EgtUV( nGuideId, dU + 1, 1, GDB_ID.ROOT)
|
|
if vtPrev * vtCurrS < GEO.EPS_SMALL and vtCurrE * vtNext < GEO.EPS_SMALL then
|
|
local nNewId = EgtSplitCurveAtParam( nGuideId, dU + 0.5)
|
|
table.insert( vGuideIds, nNewId)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return vGuideIds
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nSliceNbr, dLayerH)
|
|
|
|
local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i')
|
|
if nType == TYPE.WIPE then return true end
|
|
-- scelta del colore
|
|
local Color = EgtStdColor( 'GRAY')
|
|
if nType == TYPE.OUTER_SHELL or nType == TYPE.EXTRA_OUTER_SHELL then
|
|
Color = EgtStdColor( 'TEAL')
|
|
elseif nType == TYPE.INNER_SHELL or nType == TYPE.EXTRA_SHELL then
|
|
Color = EgtStdColor( 'ORANGE')
|
|
elseif nType == TYPE.LINK then
|
|
Color = EgtStdColor( 'GRAY')
|
|
elseif nType == TYPE.INFILL then
|
|
Color = EgtStdColor( 'YELLOW')
|
|
elseif nType == TYPE.COASTING then
|
|
Color = EgtStdColor( 'BLUE')
|
|
elseif nType == TYPE.RIB then
|
|
Color = EgtStdColor( 'OLIVE')
|
|
elseif nType == TYPE.AUX_SOLID then
|
|
Color = EgtStdColor( 'AQUA')
|
|
end
|
|
|
|
if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then
|
|
Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue())
|
|
end
|
|
|
|
-- parametri della passata
|
|
local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd') or LayerParams.dStrand
|
|
local dH = dLayerH or LayerParams.dLayHeight
|
|
|
|
-- freccia direzionale
|
|
local sName = EgtGetName( nCrvId)
|
|
if nType ~= TYPE.COASTING and nType ~= TYPE.LINK and sName ~= LEAD_IN_CRV and sName ~= LEAD_OUT_CRV and sName ~= LINK_CRV then
|
|
CreateDirectionArrow( nCrvId, nSolidGrp, LayerParams.vtSlicing, dStrand, nSliceNbr)
|
|
end
|
|
|
|
-- spezzo la curva guida in diversi sottotratti per i quali calcolare i solidi
|
|
local vGuideIds = CalcSolidGuides( nCrvId, dStrand, nSolidGrp)
|
|
if not vGuideIds then
|
|
return false
|
|
end
|
|
|
|
local bOk = true
|
|
for i = 1, #vGuideIds do
|
|
local nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 5 * GEO.EPS_SMALL)
|
|
if not nSrfId then
|
|
EgtOutLog( 'Warning : CreateSolid failed '.. '(layer '..tostring( nSliceNbr)..', curve '..tostring( nCrvId)..')')
|
|
-- ritento con strand più piccolo
|
|
nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL)
|
|
|
|
if not nSrfId then
|
|
EgtOutLog( 'Warning : CreateSolid_1 failed '.. '(layer '..tostring( nSliceNbr)..', curve '..tostring( nCrvId)..')')
|
|
-- se non ultima, provo a spostare l'estremità finale
|
|
if i < #vGuideIds then
|
|
local nCopyId = EgtCopy( vGuideIds[i] + 1, vGuideIds[i], GDB_IN.AFTER)
|
|
if nCopyId then
|
|
local LEN_TRIM = 10
|
|
local bOk1 = EgtTrimCurveEndAtLen( nCopyId, LEN_TRIM)
|
|
local bOk2 = EgtAddCurveCompoCurve( vGuideIds[i], nCopyId)
|
|
local bOk3 = EgtTrimCurveStartAtLen( vGuideIds[i] + 1, LEN_TRIM)
|
|
nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 5 * GEO.EPS_SMALL)
|
|
if not nSrfId then
|
|
nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ritento spezzando la curva in modo ricorsivo fino ad inidividuare delle sottocurve su cui è possibile calcolare il solido
|
|
if not nSrfId then
|
|
EgtOutLog( 'Warning : CreateSolid_2 failed')
|
|
local nGrp = EgtGroup( nSolidGrp, Frame3d( ORIG(), LayerParams.vtSlicing), GDB_RT.GLOB)
|
|
EgtRelocateGlob( vGuideIds[i], nGrp)
|
|
EgtApproxCurve( vGuideIds[i], GDB_CA.LINES, 100 * GEO.EPS_SMALL)
|
|
EgtRelocateGlob( vGuideIds[i], nSolidGrp)
|
|
|
|
local vSurfs = {}
|
|
local bOk = CreateRecursiveSolid( vGuideIds[i], vSurfs, nSolidGrp, LayerParams, dH, dStrand)
|
|
if #vSurfs > 0 then
|
|
nSrfId = EgtSurfTmByTriangles( nSolidGrp, vSurfs)
|
|
end
|
|
if not nSrfId or bOk == false then
|
|
EgtOutLog( 'Warning : CreateSolid_3 failed')
|
|
end
|
|
EgtErase( nGrp)
|
|
end
|
|
end
|
|
|
|
if nSrfId then
|
|
EgtSetColor( nSrfId, Color)
|
|
EgtSetInfo( nSrfId, KEY_TYPE, nType)
|
|
EgtSetInfo( nSrfId, KEY_SLICE_NBR, nSliceNbr)
|
|
else
|
|
bOk = false
|
|
EgtOutLog( 'Warning : CreateSolid_Sewing failed')
|
|
end
|
|
EgtErase( vGuideIds[i])
|
|
end
|
|
|
|
return bOk
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
------------------------- MULTIPLANAR ------------------------------
|
|
--------------------------------------------------------------------
|
|
local function CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, nLayerId, bFirst)
|
|
|
|
-- creo solidi standard con spessore massimo ammesso ( tranne nel primo layer che viene fatto ad altezza costante)
|
|
local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i')
|
|
local dH = EgtIf( bFirst, LayerParams.dLayHeight, s_dMultiPlanarH)
|
|
for i = 1, #vIds do
|
|
CreateSolidFromCurve( vIds[i], nSolidGrpId, LayerParams, nSliceNbr, dH)
|
|
end
|
|
|
|
-- deformo i solidi per rispettare l'altezza reale della passata
|
|
if not bFirst then
|
|
local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.vtSlicing * LayerParams.dLayHeight + LayerParams.vtCorr
|
|
local nPrevLayerId = EgtGetPrev( nLayerId)
|
|
local vtSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_DIR, 'v')
|
|
local ptSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_POS, 'p') + vtSlicingPrev * LayerParams.dLayHeight + LayerParams.vtCorr
|
|
local dCosAng = vtSlicingPrev * LayerParams.vtSlicing
|
|
|
|
local vSolids = EgtGetAllInGroup( nSolidGrpId)
|
|
for i = 1, #vSolids do
|
|
local nVertexCnt = EgtSurfTmVertexCount( vSolids[i])
|
|
for j = 0, nVertexCnt - 1 do
|
|
local ptVertex = EgtSurfTmGetVertex( vSolids[i], j, GDB_RT.GLOB)
|
|
-- distanza dal piano di slicing corrente e precedente lungo vtSlicing
|
|
local dDistCurr = abs( ( ptVertex - ptSlicing) * LayerParams.vtSlicing)
|
|
local dDistPrev = ( ptVertex - ptSlicingPrev) * vtSlicingPrev / dCosAng
|
|
-- calcolo la nuova posizione sapendo che l'altezza dello strand passa da s_dMultiPlanarH a dNewH
|
|
local dNewH = dDistCurr + dDistPrev
|
|
local dDelta = dDistCurr - dDistCurr * dNewH / s_dMultiPlanarH
|
|
local ptNew = ptVertex + dDelta * LayerParams.vtSlicing
|
|
EgtSurfTmMoveVertex( vSolids[i], j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CreatePartialSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, nLayerId, bFirst)
|
|
|
|
-- 1) le prime curve sono solidi multiplanari standard
|
|
for i = 1, #vIds - 1 do
|
|
CreateMultiPlanarSolids( { vIds[i]}, nSolidGrpId, LayerParams, nLayerId, bFirst)
|
|
end
|
|
|
|
-- 2) l'ultima curva è il tratto che si alza fino al layer successivo
|
|
local nGrpTmp = EgtGroup( nSolidGrpId)
|
|
local dStrand = EgtGetInfo( vIds[#vIds], KEY_CRV_STRAND, 'd') or LayerParams.dStrand
|
|
|
|
-- a) calcolo il solido
|
|
-- appiattisco la curva ( proiezione obliqua sul piano corrente lungo vtSlicing del piano successivo)
|
|
local nNextLayerId = EgtGetNext( nLayerId)
|
|
local vtSlicingNext = EgtGetInfo( nNextLayerId, KEY_SLICE_DIR, 'v')
|
|
local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * LayerParams.vtSlicing + LayerParams.vtCorr
|
|
local nProjCrv = EgtCopyGlob( vIds[#vIds], nGrpTmp)
|
|
local _, dE = EgtCurveDomain( nProjCrv)
|
|
for dU = 0, dE do
|
|
local ptCurr = EgtUP( nProjCrv, dU, GDB_ID.ROOT)
|
|
local dDist = ( ptCurr - ptSlicing) * LayerParams.vtSlicing / ( vtSlicingNext * LayerParams.vtSlicing)
|
|
EgtModifyCurveCompoJoint( nProjCrv, dU, ptCurr - dDist * vtSlicingNext, GDB_RT.GLOB)
|
|
end
|
|
|
|
-- calcolo la sezione iniziale
|
|
local ptS = EgtSP( vIds[#vIds], GDB_ID.ROOT)
|
|
local ptE = EgtEP( vIds[#vIds], GDB_ID.ROOT)
|
|
local vtDir = EgtSV( nProjCrv, GDB_ID.ROOT)
|
|
vtDir:rotate( LayerParams.vtSlicing, 90)
|
|
local nSectId = CreateSection( ptS, vtDir, dStrand, s_dMultiPlanarH, LayerParams.vtSlicing, nGrpTmp)
|
|
-- creo la sezione finale
|
|
local vtDir2 = EgtEV( nProjCrv, GDB_ID.ROOT)
|
|
vtDir2:rotate( LayerParams.vtSlicing, 90)
|
|
local nSectE = CreateSection( ptE, vtDir2, dStrand, s_dMultiPlanarH, LayerParams.vtSlicing, nGrpTmp)
|
|
|
|
-- creo le guide per il solido aperto ( tubo)
|
|
local dMaxDist = ( EgtEP( vIds[#vIds], GDB_ID.ROOT) - ptSlicing) * LayerParams.vtSlicing / ( vtSlicingNext * LayerParams.vtSlicing)
|
|
local vCrvs = {}
|
|
local _, dParE = EgtCurveDomain( nSectId)
|
|
for i = 0, dParE do
|
|
local ptRef = EgtUP( nSectId, i, GDB_ID.ROOT)
|
|
local dOffs = ( ptS - ptRef) * vtDir
|
|
vCrvs[i+1] = EgtOffsetCurveAdv( nProjCrv, dOffs)
|
|
if not vCrvs[i+1] or vCrvs[i+1] == GDB_ID.NULL then
|
|
EgtErase( nGrpTmp)
|
|
return false
|
|
end
|
|
|
|
-- proiezione obliqua "graduale"
|
|
EgtApproxCurve( vCrvs[i+1], GDB_CA.SPECIAL_LINES, 0.01)
|
|
local _, dE = EgtCurveDomain( vCrvs[i+1])
|
|
local dLen = EgtCurveLength( vCrvs[i+1])
|
|
local vDelta = {}
|
|
for dU = 0, dE do
|
|
local dCurrLen = EgtCurveLengthAtParam( vCrvs[i+1], dU)
|
|
vDelta[dU] = dMaxDist * dCurrLen / dLen
|
|
end
|
|
for dU = 0, dE do
|
|
local ptCurr = EgtUP( vCrvs[i+1], dU, GDB_ID.ROOT)
|
|
EgtModifyCurveCompoJoint( vCrvs[i+1], dU, ptCurr + vDelta[dU] * vtSlicingNext, GDB_RT.GLOB)
|
|
end
|
|
|
|
local dMove = ( ptRef - ptS) * LayerParams.vtSlicing
|
|
EgtMove( vCrvs[i+1], LayerParams.vtSlicing * dMove, GDB_RT.GLOB)
|
|
end
|
|
-- creazione delle superfici del tubo
|
|
local vSurfs = {}
|
|
for i = 1, #vCrvs - 1 do
|
|
vSurfs[i] = EgtSurfTmRuled( nGrpTmp, vCrvs[i], vCrvs[i+1], GDB_RUL.MINDIST, s_dTol)
|
|
if not vSurfs[i] or vSurfs[i] == GDB_ID.NULL then
|
|
EgtErase( nGrpTmp)
|
|
return false
|
|
end
|
|
end
|
|
-- creazione del mezzo disco iniziale e finale
|
|
vSurfs[#vCrvs] = CreateSpiralVaseCap( nSectId, - EgtSV( vIds[#vIds], GDB_ID.ROOT), nSolidGrpId)
|
|
vSurfs[#vCrvs + 1] = CreateSpiralVaseCap( nSectE, EgtEV( vIds[#vIds], GDB_ID.ROOT), nSolidGrpId)
|
|
EgtInvertSurf( vSurfs[#vSurfs])
|
|
local nSolidId = EgtSurfTmByTriangles( nSolidGrpId, vSurfs)
|
|
|
|
-- b) deformo il solido per limitarlo al piano di slicing precedente
|
|
local ptSlicingPrev
|
|
local vtSlicingPrev
|
|
local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i')
|
|
if nSliceNbr == 1 then
|
|
vtSlicingPrev = LayerParams.vtSlicing
|
|
ptSlicingPrev = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.vtCorr
|
|
else
|
|
local nPrevLayId = EgtGetPrev( nLayerId)
|
|
vtSlicingPrev = EgtGetInfo( nPrevLayId, KEY_SLICE_DIR, 'v')
|
|
ptSlicingPrev = EgtGetInfo( nPrevLayId, KEY_SLICE_POS, 'p') + vtSlicingPrev * LayerParams.dLayHeight + LayerParams.vtCorr
|
|
end
|
|
local dCosAng = vtSlicingPrev * LayerParams.vtSlicing
|
|
|
|
-- estendo la curva proiettata per gestire correttamente la deformazione dei caps
|
|
local nProjExtCrv = EgtCopyGlob( nProjCrv, nGrpTmp)
|
|
EgtExtendCurveStartByLen( nProjExtCrv, dStrand)
|
|
EgtExtendCurveEndByLen( nProjExtCrv, dStrand)
|
|
local dLen = EgtCurveLength( nProjCrv)
|
|
|
|
local nVertexCnt = EgtSurfTmVertexCount( nSolidId)
|
|
for j = 0, nVertexCnt - 1 do
|
|
|
|
local ptVertex = EgtSurfTmGetVertex( nSolidId, j, GDB_RT.GLOB)
|
|
|
|
-- calcolo la distanza dal piano precedente lungo vtSlicing
|
|
local dDistPrevPlane = ( ptVertex - ptSlicingPrev) * vtSlicingPrev / dCosAng
|
|
-- calcolo la distanza approssimata dalla curva del toolpath
|
|
local _, ptMinDist, dMinPar = EgtPointCurveDist( ptVertex, nProjExtCrv, GDB_ID.ROOT)
|
|
local dCurrLen = EgtCurveLengthAtParam( nProjExtCrv, dMinPar) - dStrand
|
|
local ptRef = ptMinDist + dMaxDist * dCurrLen / dLen * vtSlicingNext
|
|
local dDistCrv = ( ptRef - ptVertex) * LayerParams.vtSlicing
|
|
|
|
-- calcolo la nuova posizione sapendo che l'altezza dello strand passa da s_dMultiPlanarH a dNewH
|
|
local dNewH = dDistCrv + dDistPrevPlane
|
|
local dDelta = dDistCrv - dDistCrv * dNewH / s_dMultiPlanarH
|
|
local ptNew = ptVertex + dDelta * LayerParams.vtSlicing
|
|
EgtSurfTmMoveVertex( nSolidId, j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1))
|
|
end
|
|
|
|
local Color = EgtStdColor( 'TEAL')
|
|
if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then
|
|
Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue())
|
|
end
|
|
EgtSetColor( nSolidId, Color)
|
|
|
|
EgtErase( nGrpTmp)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CreateFullSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, nLayerId)
|
|
|
|
local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i')
|
|
local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * LayerParams.vtSlicing + LayerParams.vtCorr
|
|
|
|
-- recupero il piano precedente e il suo toolpath
|
|
local nPrevLayerId = EgtGetPrev( nLayerId)
|
|
local vtSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_DIR, 'v')
|
|
local ptSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * vtSlicingPrev + LayerParams.vtCorr
|
|
local dCosAng = vtSlicingPrev * LayerParams.vtSlicing
|
|
local nPrevCrvGrp = EgtGetFirstNameInGroup( nPrevLayerId, CONTOUR_GRP .. '*')
|
|
local nPrevTPathGrp = EgtGetFirstNameInGroup( nPrevCrvGrp, TOOLPATH_GRP)
|
|
local nPrevTPath = EgtGetFirstNameInGroup( nPrevTPathGrp, SHELL_CRV .. '*')
|
|
|
|
-- gruppo temporaneo per conti
|
|
local nGrpTmp = EgtGroup( nSolidGrpId)
|
|
|
|
for i = 1, #vIds do
|
|
local dStrand = EgtGetInfo( vIds[i], KEY_CRV_STRAND, 'd') or LayerParams.dStrand
|
|
|
|
-- creo la freccia direzionale
|
|
CreateDirectionArrow( vIds[i], nSolidGrpId, LayerParams.vtSlicing, dStrand, nSliceNbr)
|
|
|
|
-- appiattisco la curva ( proiezione sul piano di slicing)
|
|
local nProjCrv = EgtCopyGlob( vIds[i], nGrpTmp)
|
|
EgtProjectCurveOnPlane( nProjCrv, ptSlicing, LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
local dLen = EgtCurveLength( nProjCrv)
|
|
|
|
-- suddivido la curva piana
|
|
local vGuideIds = CalcSolidGuides( nProjCrv, dStrand, nGrpTmp)
|
|
local dCumLen = 0
|
|
for k = 1, #vGuideIds do
|
|
|
|
-- calcolo il solido sulla porzione della curva di proiezione
|
|
local nSolidId = CreateStandardSolid( vGuideIds[k], nSolidGrpId, s_dMultiPlanarH, dStrand)
|
|
|
|
-- estendo la guida per gestire al meglio i caps
|
|
local nCrvRef = EgtCopyGlob( vGuideIds[k], nGrpTmp)
|
|
EgtExtendCurveStartByLen( nCrvRef, dStrand)
|
|
EgtExtendCurveEndByLen( nCrvRef, dStrand)
|
|
|
|
-- recupero la curva precedente. Se estremi la limito per gestire al meglio la corrispondenza tra i toolpath
|
|
local nPrevTPathRef = nPrevTPath
|
|
if k == 1 then
|
|
nPrevTPathRef = EgtCopyGlob( nPrevTPath, nGrpTmp)
|
|
EgtTrimCurveEndAtLen( nPrevTPathRef, 0.5 * EgtCurveLength( nPrevTPathRef))
|
|
elseif k == #vGuideIds then
|
|
nPrevTPathRef = EgtCopyGlob( nPrevTPath, nGrpTmp)
|
|
EgtTrimCurveStartAtLen( nPrevTPathRef, 0.5 * EgtCurveLength( nPrevTPathRef))
|
|
end
|
|
|
|
-- deformo i solidi :
|
|
-- 1) traslazione dei vertici per portarli alla quota corretta del toolpath corrente
|
|
-- 2) deformazione della sezione in base alla distanza dal toolpath precedente
|
|
local nVertexCnt = EgtSurfTmVertexCount( nSolidId)
|
|
for j = 0, nVertexCnt - 1 do
|
|
local ptVertex = EgtSurfTmGetVertex( nSolidId, j, GDB_RT.GLOB)
|
|
|
|
-- ricavo il punto di riferimento sulla proiezione del toolpath
|
|
local _, ptMinDist, dParMinDist = EgtPointCurveDist( ptVertex, nCrvRef, GDB_ID.ROOT)
|
|
local dCurrLen = EgtCurveLengthAtParam( nCrvRef, dParMinDist) - dStrand + dCumLen
|
|
|
|
-- 1) proietto il punto sul piano corrente e calcolo la traslazione da applicare in base alla distanza dal piano precedente ( analogamente a CalcToolPath)
|
|
local dDistCrv = ( ptSlicing - ptVertex) * LayerParams.vtSlicing
|
|
local ptProj = ptVertex + dDistCrv * LayerParams.vtSlicing
|
|
local dDistPlanePrev = ( ptProj - ptSlicingPrev) * vtSlicingPrev / dCosAng
|
|
local dDeltaPos
|
|
if nSliceNbr == 2 and dCurrLen < 0.5 * dLen then
|
|
dDeltaPos = 0.5 * dDistPlanePrev
|
|
else
|
|
dDeltaPos = dDistPlanePrev * ( dLen - dCurrLen) / dLen
|
|
end
|
|
|
|
-- 2) per calcolare la vera altezza del solido calcolo la distanza dal toolpath precedente guardando il punto di riferimento sul percorso corrente
|
|
local dNewH
|
|
if nSliceNbr == 2 then
|
|
-- il primo layer è ad altezza costante quindi è semplice distanza dal piano precedente lungo vtSlicing
|
|
dNewH = ( ptProj - ptSlicingPrev) * vtSlicingPrev / dCosAng - dDeltaPos
|
|
else
|
|
local _, ptMinDistPrev = EgtPointCurveDist( ptMinDist, nPrevTPathRef, GDB_ID.ROOT)
|
|
local dDistPlanePrev2 = ( ptMinDist - ptSlicingPrev) * vtSlicingPrev / dCosAng
|
|
local dDeltaPos2
|
|
if nSliceNbr == 2 and dCurrLen < 0.5 * dLen then
|
|
dDeltaPos2 = 0.5 * dDistPlanePrev2
|
|
else
|
|
dDeltaPos2 = dDistPlanePrev2 * ( dLen - dCurrLen) / dLen
|
|
end
|
|
dNewH = ( ptMinDist - ptMinDistPrev) * LayerParams.vtSlicing - dDeltaPos2
|
|
-- aggiungo un piccolo extra per tener conto che la distanza è stata calcolata sulle curve centrali del solido
|
|
local dExtra = ( LayerParams.vtSlicing ^ vtSlicingPrev):len() / dCosAng * dStrand * 0.5
|
|
dNewH = dNewH + dExtra
|
|
end
|
|
|
|
local dDelta = dDistCrv - dDistCrv * dNewH / s_dMultiPlanarH
|
|
local ptNew = ptVertex + ( dDelta - dDeltaPos) * LayerParams.vtSlicing
|
|
EgtSurfTmMoveVertex( nSolidId, j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1))
|
|
end
|
|
|
|
-- imposto colore
|
|
local Color = EgtStdColor( 'TEAL')
|
|
if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then
|
|
Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue())
|
|
end
|
|
EgtSetColor( nSolidId, Color)
|
|
|
|
dCumLen = dCumLen + EgtCurveLength( vGuideIds[i])
|
|
end
|
|
end
|
|
|
|
EgtErase( nGrpTmp)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CreateFullSpiralVaseMultiPlanarSolidsLastLayer( vIds, nSolidGrpId, LayerParams, nLayerId)
|
|
-- le curve sono piane quindi i solidi possono essere calcolati nel modo classico
|
|
-- i solidi della shell sono deformati in base alla distanza dalla curva precedente
|
|
-- eventuali solidi di lead out e coasting sono calcolati con un valore di altezza costante pari all'ultimo valore di altezza dei solidi della shell
|
|
|
|
local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i')
|
|
|
|
local nPrevLayerId = EgtGetPrev( EgtGetPrev( nLayerId))
|
|
local vtSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_DIR, 'v')
|
|
local ptSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_POS, 'p') + vtSlicingPrev * LayerParams.dLayHeight + LayerParams.vtCorr
|
|
local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.vtSlicing * LayerParams.dLayHeight + LayerParams.vtCorr
|
|
local dCosAng = vtSlicingPrev * LayerParams.vtSlicing
|
|
|
|
-- 1) curva shell
|
|
local nGrpTmp = EgtGroup( nSolidGrpId)
|
|
local dStrand = EgtGetInfo( vIds[1], KEY_CRV_STRAND, 'd') or LayerParams.dStrand
|
|
local vShellGuides = CalcSolidGuides( vIds[1], dStrand, nGrpTmp)
|
|
|
|
local dLen = EgtCurveLength( vIds[1])
|
|
-- se non c'è lead out alla lunghezza totale della shell devo aggiungere anche quella del coasting
|
|
if EgtGetInfo( s_nPartId, KEY_LEAD_OUT_TYPE, 'i') == LEAD_TYPE.NONE then
|
|
dLen = dLen + EgtGetInfo( s_nPartId, KEY_COASTING_LEN, 'd')
|
|
end
|
|
local dCumLen = 0
|
|
|
|
-- creo la freccia direzionale
|
|
CreateDirectionArrow( vIds[1], nSolidGrpId, LayerParams.vtSlicing, dStrand, nSliceNbr)
|
|
|
|
for i = 1, #vShellGuides do
|
|
|
|
-- calcolo il solido associato
|
|
local nSolidId = CreateStandardSolid( vShellGuides[i], nSolidGrpId, s_dMultiPlanarH, dStrand)
|
|
|
|
-- estensione della guida per gestire meglio i caps
|
|
local nCrvRef = EgtCopyGlob( vShellGuides[i], nGrpTmp)
|
|
EgtExtendCurveStartByLen( nCrvRef, dStrand)
|
|
EgtExtendCurveEndByLen( nCrvRef, dStrand)
|
|
|
|
-- deformo in base alla distanza dalla curva precedente
|
|
local nVertexCnt = EgtSurfTmVertexCount( nSolidId)
|
|
for j = 0, nVertexCnt - 1 do
|
|
local ptVertex = EgtSurfTmGetVertex( nSolidId, j, GDB_RT.GLOB)
|
|
|
|
-- ricavo il punto di riferimento sulla guida
|
|
local _, _, dParMinDist = EgtPointCurveDist( ptVertex, nCrvRef, GDB_ID.ROOT)
|
|
local dCurrLen = EgtCurveLengthAtParam( nCrvRef, dParMinDist) - dStrand + dCumLen
|
|
|
|
-- calcolo la nuova altezza del solido in base alla distanza dalla curva precedente
|
|
local dDistCurr = ( ptSlicing - ptVertex) * LayerParams.vtSlicing
|
|
local ptProj = ptVertex + dDistCurr * LayerParams.vtSlicing
|
|
local dDistPrev = ( ptProj - ptSlicingPrev) * vtSlicingPrev / dCosAng
|
|
local dNewH = dDistPrev * ( dLen - dCurrLen) / dLen
|
|
dNewH = max( dNewH, 500 * GEO.EPS_SMALL)
|
|
|
|
-- calcolo la nuova posizione sapendo che l'altezza dello strand passa da s_dMultiPlanarH a dNewH
|
|
local dDelta = dDistCurr - dDistCurr * dNewH / s_dMultiPlanarH
|
|
local ptNew = ptVertex + dDelta * LayerParams.vtSlicing
|
|
EgtSurfTmMoveVertex( nSolidId, j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1))
|
|
end
|
|
|
|
dCumLen = dCumLen + EgtCurveLength( vShellGuides[i])
|
|
|
|
-- imposto colore
|
|
local Color = EgtStdColor( 'TEAL')
|
|
if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then
|
|
Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue())
|
|
end
|
|
EgtSetColor( nSolidId, Color)
|
|
end
|
|
|
|
-- 2) curve di uscita
|
|
-- calcolo altezza finale del solido shell
|
|
local ptE = EgtEP( vIds[1], GDB_ID.ROOT)
|
|
local dH = ( ( ptE - ptSlicingPrev) * vtSlicingPrev / dCosAng) * ( dLen - EgtCurveLength( vIds[1])) / dLen
|
|
dH = max( dH, 500 * GEO.EPS_SMALL)
|
|
for i = 2, #vIds do
|
|
CreateSolidFromCurve( vIds[i], nSolidGrpId, LayerParams, nSliceNbr, dH)
|
|
end
|
|
|
|
EgtErase( nGrpTmp)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function RunCalcSolids.Exec()
|
|
|
|
-- per determinare il tempo di calcolo
|
|
EgtStartCounter()
|
|
|
|
-- verifico se richiesta sezione semplificata ( rettangolare)
|
|
local sIniFile = EgtGetIniFile()
|
|
s_nSimplifiedSection = EgtGetNumberFromIni( 'Solids', 'SimplifiedSection', 0, sIniFile)
|
|
|
|
local nPartIndex = 1
|
|
local nPartId = EgtGetFirstNameInGroup( GDB_ID.ROOT, PART .. nPartIndex) or EgtGetFirstNameInGroup( GDB_ID.ROOT, PART)
|
|
while nPartId do
|
|
|
|
s_nPartId = nPartId
|
|
if EgtGetInfo( nPartId, KEY_PART_ON_TABLE, 'b') then
|
|
-- verifico se necessario calcolare il solido
|
|
local bCalcSolid = EgtGetInfo( nPartId, KEY_CALC_SOLIDS, 'b') or false
|
|
|
|
if bCalcSolid then
|
|
|
|
-- recupero il suo frame
|
|
local nFrameId = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( nPartId, 'Frame'), 'FramePart')
|
|
local ptOrig = EgtSP( nFrameId or GDB_ID.NULL, GDB_ID.ROOT)
|
|
EgtSetInfo( nPartId, KEY_ORIG_REF, ptOrig)
|
|
|
|
-- recupero i suoi slice
|
|
local vLayIds = EgtGetNameInGroup( nPartId, SLICE_LAYER .. '*')
|
|
if not vLayIds or #vLayIds == 0 then
|
|
EgtOutBox( 'No sliced part in this project!', 'Error', 'ERROR')
|
|
return
|
|
end
|
|
|
|
EgtSetInfo( nPartId, KEY_HAS_SOLIDS, 1)
|
|
local nSlicingType = EgtGetInfo( nPartId, KEY_SLICING_TYPE, 'i')
|
|
|
|
-- recupero i parametri necessari al calcolo dei solidi
|
|
local LayerParams = GetLayerParamsForSolidCalc( nPartId)
|
|
|
|
-- se slicing multiplanare considero come altezza standard quella massima ammessa
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
local sMachIni = EgtGetCurrMachineDir() .. '\\' .. EgtGetCurrMachineName() .. '.ini'
|
|
local dMaxFactor = EgtGetNumberFromIni( '3dPrinting', KEY_MAX_STRANDH_FACTOR, 2, sMachIni)
|
|
s_dMultiPlanarH = min( dMaxFactor, 5) * LayerParams.dLayHeight
|
|
end
|
|
|
|
local bFirst = true
|
|
for nIdx = 1, #vLayIds do
|
|
|
|
-- flag di interruzione perchè trovati solidi già ok
|
|
local bSolidsOk = false
|
|
-- indice layer ( per log)
|
|
local nSliceNbr = EgtGetInfo( vLayIds[ nIdx], KEY_SLICE_NBR, 'i')
|
|
-- scorro tutti i gruppi di contorni
|
|
local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") or GDB_ID.NULL
|
|
while nCrvGrpId ~= GDB_ID.NULL do
|
|
|
|
-- recupero il gruppo dei percorsi utensile
|
|
local nTPathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, TOOLPATH_GRP) or GDB_ID.NULL
|
|
if nTPathGrpId == GDB_ID.NULL then
|
|
EgtOutBox( 'Error no tool paths', 'SolidCalc')
|
|
return
|
|
end
|
|
|
|
-- recupero il gruppo dei solidi
|
|
local nSolidGrpId = EgtGetFirstNameInGroup( nCrvGrpId, SOLID_GRP) or GDB_ID.NULL
|
|
if nSolidGrpId == GDB_ID.NULL then
|
|
nSolidGrpId = EgtGroup( nCrvGrpId)
|
|
EgtSetName( nSolidGrpId, SOLID_GRP)
|
|
EgtSetLevel( nSolidGrpId, GDB_LV.TEMP)
|
|
|
|
local vIds = EgtGetAllInGroup( nTPathGrpId)
|
|
|
|
if #vIds > 0 then
|
|
-- slicing multiplanare
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
LayerParams.vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v')
|
|
|
|
if LayerParams.bSpiralVase then
|
|
local dTransitionLen = EgtGetInfo( nPartId, KEY_SPIRAL_VASE_LEN, 'd') or 0
|
|
-- a) spiral vase completo ( con transizione in altezza su tutto il layer)
|
|
if dTransitionLen < GEO.EPS_SMALL then
|
|
if bFirst then
|
|
-- il primo layer va gestito come uno spiral vase con transizione parziale ( curva a quota costante e ultimo tratto che si alza)
|
|
CreatePartialSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], bFirst)
|
|
elseif nIdx == #vLayIds then
|
|
-- gestione speciale per lead out e coasting
|
|
CreateFullSpiralVaseMultiPlanarSolidsLastLayer( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx])
|
|
else
|
|
CreateFullSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx])
|
|
end
|
|
|
|
-- b) spiral vase con transizione parziale
|
|
else
|
|
if nIdx == #vLayIds then
|
|
-- ultimo layer è un multiplanare standard perchè non ha tratto finale che si alza
|
|
CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], false)
|
|
else
|
|
CreatePartialSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], bFirst)
|
|
end
|
|
end
|
|
-- c) multiplanare standard
|
|
else
|
|
CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], bFirst)
|
|
end
|
|
|
|
-- slicing standard spiral vase
|
|
elseif LayerParams.bSpiralVase then
|
|
-- i tratti di ingresso, uscita e quelli a quota costante vanno gestiti singolarmente, quelli a quota variabile vanno concatenati
|
|
local vChainedIds = {}
|
|
local vTmpIds = {}
|
|
for i = 1, #vIds do
|
|
local sName = EgtGetName( vIds[i])
|
|
local dDelta = ( EgtEP( vIds[i], GDB_ID.ROOT) - EgtSP( vIds[i], GDB_ID.ROOT)) * LayerParams.vtSlicing
|
|
if abs( dDelta) < GEO.EPS_SMALL or sName == LEAD_IN_CRV or sName == LEAD_OUT_CRV or sName == COASTING_CRV or sName == WIPE_CRV then
|
|
-- inserisco il gruppo di tratti da concatenare e lo resetto
|
|
if #vTmpIds > 0 then
|
|
table.insert( vChainedIds, vTmpIds)
|
|
vTmpIds = {}
|
|
end
|
|
-- inserisco la curva singola corrente
|
|
table.insert( vChainedIds, { vIds[i]})
|
|
else
|
|
table.insert( vTmpIds, vIds[i])
|
|
end
|
|
end
|
|
-- inserisco ultimo gruppo
|
|
if #vTmpIds > 0 then
|
|
table.insert( vChainedIds, vTmpIds)
|
|
end
|
|
|
|
for i = 1, #vChainedIds do
|
|
if #vChainedIds[i] == 1 then
|
|
CreateSolidFromCurve( vChainedIds[i][1], nSolidGrpId, LayerParams, nSliceNbr)
|
|
else
|
|
local nNewCrv = EgtCurveCompo( nSolidGrpId, vChainedIds[i], false)
|
|
local dStrand = EgtGetInfo( vChainedIds[i][1], KEY_CRV_STRAND, 'd') or LayerParams.dStrand
|
|
EgtSetInfo( nNewCrv, KEY_CRV_STRAND, dStrand)
|
|
EgtSetInfo( nNewCrv, KEY_TYPE, TYPE.OUTER_SHELL)
|
|
CreateSolidFromCurve( nNewCrv, nSolidGrpId, LayerParams, nSliceNbr)
|
|
EgtErase( nNewCrv)
|
|
end
|
|
end
|
|
|
|
-- slicing standard
|
|
else
|
|
for i = 1, #vIds do
|
|
CreateSolidFromCurve( vIds[i], nSolidGrpId, LayerParams, nSliceNbr)
|
|
end
|
|
end
|
|
bFirst = false
|
|
end
|
|
else
|
|
bSolidsOk = true
|
|
break
|
|
end
|
|
|
|
--passo al gruppo di contorni successivo
|
|
nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*") or GDB_ID.NULL
|
|
end
|
|
if bSolidsOk then
|
|
break
|
|
end
|
|
local nStep = 10
|
|
if nIdx > 400 then
|
|
nStep = 80
|
|
elseif nIdx > 200 then
|
|
nStep = 40
|
|
elseif nIdx > 100 then
|
|
nStep = 20
|
|
end
|
|
if ( nIdx % nStep) == 0 then
|
|
EgtDraw()
|
|
end
|
|
|
|
if EgtProcessEvents( EgtIf( PRINT, 400, 0) + nIdx / #vLayIds * 100, 0) == 1 then
|
|
-- se interrompo cancello i solidi realizzati
|
|
for i = 1, #vLayIds do
|
|
local vGrpId = EgtGetNameInGroup( vLayIds[i], CONTOUR_GRP .. '*') or {}
|
|
for j = 1, #vGrpId do
|
|
local nSolidId = EgtGetFirstNameInGroup( vGrpId[j], SOLID_GRP .. '*') or GDB_ID.NULL
|
|
EgtErase( nSolidId)
|
|
end
|
|
end
|
|
-- rimuovo info della presenza solidi
|
|
EgtSetInfo( nPartId, KEY_HAS_SOLIDS, false)
|
|
EgtDraw()
|
|
return
|
|
end
|
|
end
|
|
|
|
-- eventuale aggiornamento delle ViewInfo
|
|
local nViewId = EgtGetFirstNameInGroup( GDB_ID.ROOT, VIEWPARAMS)
|
|
if nViewId then
|
|
EgtSetInfo( nViewId, SOLID_GRP, true)
|
|
end
|
|
end
|
|
end
|
|
|
|
nPartIndex = nPartIndex + 1
|
|
nPartId = EgtGetFirstNameInGroup( GDB_ID.ROOT, PART .. nPartIndex) or EgtGetNextName( nPartId, PART)
|
|
end
|
|
|
|
EgtDraw()
|
|
|
|
-- report tempo di calcolo in log
|
|
EgtOutLog( string.format( ' CalcSolidsTime = %.2f ms', EgtStopCounter()))
|
|
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
return RunCalcSolids
|