Files
egwwindowlua/Designing/WinLib/WinCalculate.lua
T
SaraP 65e0b550c6 DataWindow :
- cambio profilo su split
- sistemata identificazione dei cambi profilo dopo gli spostamenti degli outlines degli split per misura luce
- preview con pezzi dello stesso colore.
2026-04-23 15:39:35 +02:00

9448 lines
412 KiB
Lua

--
-- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT
-- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT
-- EEEE GGGG GGGG TTTT
-- EEEE GGGG TTTT
-- EEEEEEE GGGG GGGGGGG TTTT
-- EEEEEEE GGGG GGGGGGG TTTT
-- EEEE GGGG GGGG TTTT
-- EEEE GGGG GGGG TTTT
-- EEEEEEEEEE GGGGGGGGGG TTTT
-- EEEEEEEEEE GGGGGG TTTT
--
-- by Egalware s.r.l.
-- Window project software by Egalware s.r.l. 2023/05/02
-- Tabella per definizione modulo
local WinCalculate = {}
-- Include
local JSON = require( 'JSON')
local XML = require( 'xml2lua')
local XMLHandler = require( 'xml2lua_tree')
local s_nRedisConnectionId = 0 -- 0 connessione non definita, > 0 connessione definita
local s_dDowelTol = 1
local s_dSimplSolidApprox = 0.2 -- approssimazione lineare nel caso di solidi semplificati
local s_nSashNbr = 0 -- contatore delle ante per assegnare nomi
local s_dAngledCos = 0.995 -- coseno limite oltre il quale viene forzata giunzione angled
---------------------------------------------------------------------
local s_bCalcSolid = false
function WinCalculate.GetCalcSolid()
return s_bCalcSolid
end
function WinCalculate.SetCalcSolid( bValue)
s_bCalcSolid = bValue
end
local s_bSimplSolid = false
function WinCalculate.SetSimplifiedSolid( bValue)
s_bSimplSolid = bValue
end
local s_bCalcPreview = false
function WinCalculate.SetCalcPreview( bValue)
s_bCalcPreview = bValue
end
---------------------------------------------------------------------
-- funzione che copia la info di chiave sInfo da nSou a nDest
local function CopyInfo( nDest, nSou, sInfo, Default)
local sVal = EgtGetInfo( nSou, sInfo) or Default
EgtSetInfo( nDest, sInfo, sVal)
end
---------------------------------------------------------------------
local function AddInfo( nId, sInfo, sVal)
local vInfo = EgtGetInfo( nId, sInfo, 'vs') or {}
table.insert( vInfo, sVal)
EgtSetInfo( nId, sInfo, vInfo)
end
---------------------------------------------------------------------
-- funzione che restituisce o crea il layer ausiliario per soldi di ferramenta e accessori
local function GetAuxLayer()
local nAuxLayerId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AUX)
if not nAuxLayerId then
nAuxLayerId = EgtGroup( GDB_ID.ROOT)
EgtSetName( nAuxLayerId, WIN_AUX)
EgtSetLevel( nAuxLayerId, GDB_LV.SYSTEM)
end
return nAuxLayerId
end
---------------------------------------------------------------------
-- funzione che trova il punto di intersezione fra due curve considerandole estese
local function FindIntersectionPoint( nCrv1, nCrv2, ptRef)
local ptInt = EgtIP( nCrv1, nCrv2, ptRef)
-- se il punto di intersezione non esiste ritento estendendo le curve
if not ptInt then
local nGrp = EgtGroup( EgtGetParent( nCrv1))
local dExtraLen = 10000
local nCrvA, nCrvB
local nType1 = EgtGetType( nCrv1)
local nType2 = EgtGetType( nCrv2)
-- se compo viene gestita estensione solo sulla sua prima/ultima curva
if nType1 == GDB_TY.CRV_COMPO then
local _, dE = EgtCurveDomain( nCrv1)
nCrv1 = EgtCopyCompoSubCurve( nCrv1, dE - 1, nGrp)
nType1 = EgtGetType( nCrv1)
end
if nType2 == GDB_TY.CRV_COMPO then
nCrv2 = EgtCopyCompoSubCurve( nCrv2, 0, nGrp)
nType2 = EgtGetType( nCrv2)
end
if nType1 == GDB_TY.CRV_LINE and nType2 == GDB_TY.CRV_LINE then
-- caso linea-linea : estendo le due linee
nCrvA = EgtCopyGlob( nCrv1, nGrp)
nCrvB = EgtCopyGlob( nCrv2, nGrp)
EgtExtendCurveStartByLen( nCrvA, dExtraLen)
EgtExtendCurveEndByLen( nCrvA, dExtraLen)
EgtExtendCurveStartByLen( nCrvB, dExtraLen)
EgtExtendCurveEndByLen( nCrvB, dExtraLen)
elseif nType1 == GDB_TY.CRV_ARC and nType2 == GDB_TY.CRV_ARC then
-- caso arco-arco : cerco intersezione tra le due circonferenze
nCrvA = EgtCircle( nGrp, EgtCP( nCrv1), EgtArcRadius( nCrv1))
nCrvB = EgtCircle( nGrp, EgtCP( nCrv2), EgtArcRadius( nCrv2))
elseif ( nType1 == GDB_TY.CRV_ARC and nType2 == GDB_TY.CRV_LINE) or
( nType1 == GDB_TY.CRV_LINE and nType2 == GDB_TY.CRV_ARC) then
-- caso arco-linea : cerco intersezione fra la linea e la circonferenza
local nArc = EgtIf( EgtGetType( nCrv1) == GDB_TY.CRV_ARC, nCrv1, nCrv2)
local nLine = EgtIf( nArc == nCrv1, nCrv2, nCrv1)
nCrvA = EgtCircle( nGrp, EgtCP( nArc), EgtArcRadius( nArc))
nCrvB = EgtCopyGlob( nLine, nGrp)
EgtExtendCurveStartByLen( nCrvB, dExtraLen)
EgtExtendCurveEndByLen( nCrvB, dExtraLen)
end
ptInt = EgtIP( nCrvA, nCrvB, ptRef)
EgtErase( nGrp)
end
return ptInt
end
---------------------------------------------------------------------
-- funzione che controlla se vi è overlap tra nOrigId e una porzione della sua estensione ( nCrvId)
local function CheckExtensionOverlap( nCrvId, nOrigId)
local dParS = EgtCurveParamAtPoint( nOrigId, EgtSP( nCrvId))
local dParE = EgtCurveParamAtPoint( nOrigId, EgtEP( nCrvId))
if not dParS and not dParE then
-- se il nuovo tratto non poggia sull'originale, verifico se è l'originale a poggiare sul nuovo
local dPar1 = EgtCurveParamAtPoint( nCrvId, EgtSP( nOrigId))
local dPar2 = EgtCurveParamAtPoint( nCrvId, EgtEP( nOrigId))
if dPar1 or dPar2 then
return true
end
elseif dParS and not AreSamePointApprox( EgtSP( nCrvId), EgtEP( nOrigId)) then
return true
elseif dParE and not AreSamePointApprox( EgtEP( nCrvId), EgtSP( nOrigId)) then
return true
end
return false
end
---------------------------------------------------------------------
-- funzione che crea una copia estesa della curva con estensione di lunghezza "illimitata"
local function CreateCurveExtension( nCrvId, nGrpId)
-- recupero tipo di estensione
local bTangStart = EgtGetInfo( nCrvId, WIN_TANG_START, 'b') or false
local bTangEnd = EgtGetInfo( nCrvId, WIN_TANG_END, 'b') or false
local dExtraLen = 10000
local nExtId
if EgtGetType( nCrvId) == GDB_TY.CRV_LINE then
-- estensione immediata
nExtId = EgtCopyGlob( nCrvId, nGrpId)
EgtExtendCurveStartByLen( nExtId, dExtraLen)
EgtExtendCurveEndByLen( nExtId, dExtraLen)
elseif EgtGetType( nCrvId) == GDB_TY.CRV_ARC then
-- il risultato sarà una circonferenza ( se start ed end non vanno estesi in tangenza) oppure una composita ( se uno degli estremi va esteso in tangenza)
if not bTangStart and not bTangEnd then
-- se estensione standard su entrambi gli estremi trasformo arco in circonferenza
nExtId = EgtCopyGlob( nCrvId, nGrpId)
local dAngOld = EgtArcAngCenter( nCrvId)
EgtModifyArcAngCenter( nExtId, EgtIf( dAngOld > 0, 360, -360))
elseif bTangStart and bTangEnd then
nExtId = EgtCurveCompo( nGrpId, nCrvId, false)
EgtAddCurveCompoLineTg( nExtId, dExtraLen, true)
EgtAddCurveCompoLineTg( nExtId, dExtraLen, false)
elseif bTangStart and not bTangEnd then
local nExtArcId = EgtCopyGlob( nCrvId, nGrpId)
local dAngOld = EgtArcAngCenter( nCrvId)
EgtModifyArcAngCenter( nExtArcId, EgtIf( dAngOld > 0, 340, -340))
nExtId = EgtCurveCompo( nGrpId, nExtArcId)
EgtAddCurveCompoLineTg( nExtId, dExtraLen, false)
elseif not bTangStart and bTangEnd then
local nExtArcId = EgtCopyGlob( nCrvId,nGrpId)
EgtInvertCurve( nExtArcId)
local dAngOld = EgtArcAngCenter( nExtArcId)
EgtModifyArcAngCenter( nExtArcId, EgtIf( dAngOld > 0, 340, -340))
EgtInvertCurve( nExtArcId)
nExtId = EgtCurveCompo( nGrpId, nExtArcId)
EgtAddCurveCompoLineTg( nExtId, dExtraLen)
end
elseif EgtGetType( nCrvId) == GDB_TY.CRV_COMPO then
-- se composita formata da una sola sottocurva la gestisco come curva semplice
local _, dEnd = EgtCurveDomain( nCrvId)
if abs( dEnd - 1) < GEO.EPS_SMALL then
local nSimpleCrv = EgtCopyCompoSubCurve( nCrvId, 0, nGrpId)
EgtSetInfo( nSimpleCrv, WIN_TANG_START, bTangStart)
EgtSetInfo( nSimpleCrv, WIN_TANG_END, bTangEnd)
nExtId = CreateCurveExtension( nSimpleCrv, nGrpId)
EgtErase( nSimpleCrv)
else
nExtId = EgtCopyGlob( nCrvId, nGrpId)
-- start
if EgtCurveCompoRadius( nExtId, 0) > 0 then
if bTangStart then
EgtAddCurveCompoLineTg( nExtId, dExtraLen, false)
else
local ptC = EgtCurveCompoCenter( nExtId, 0)
local dAngOld = EgtCurveCompoAngCenter( nExtId, 0)
EgtRemoveCurveCompoCurve( nExtId, false)
local nNewArc = EgtArcCPA( nGrpId, ptC, EgtSP( nExtId), EgtIf( dAngOld > 0, -340, 340), 0)
EgtInvertCurve( nNewArc)
EgtAddCurveCompoCurve( nExtId, nNewArc, true, false)
end
else
EgtExtendCurveStartByLen( nExtId, dExtraLen)
end
-- end
local _, dEnd = EgtCurveDomain( nExtId)
if EgtCurveCompoRadius( nExtId, dEnd - 1) > 0 then
if bTangEnd then
EgtAddCurveCompoLineTg( nExtId, dExtraLen)
else
local ptC = EgtCurveCompoCenter( nExtId, dEnd - 1)
local dAngOld = EgtCurveCompoAngCenter( nExtId, dEnd - 1)
EgtRemoveCurveCompoCurve( nExtId, true)
local nNewArc = EgtArcCPA( nGrpId, ptC, EgtEP( nExtId), EgtIf( dAngOld > 0, 340, -340), 0)
EgtAddCurveCompoCurve( nExtId, nNewArc)
end
else
EgtExtendCurveEndByLen( nExtId, dExtraLen)
end
end
end
return nExtId
end
---------------------------------------------------------------------
-- funzione che data una lista di curve ordinate e orientate che creano una curva chiusa, ne individua la regione definita
local function CalcIntersectionRegion( vCrvs, nGrp)
local nSurfId
-- gruppo temporaneo per i conti
local nGrpTmp = EgtGroup( nGrp)
EgtSetStatus( nGrpTmp, GDB_ST.OFF)
-- costruisco le regioni definite dai semipiani delle linee che compongono il contorno e calcolo le estensioni per gli archi e le composite ( che vanno gestite come gli archi)
local dExtraLen = 10000
local vSemiPlanes = {}
local tArcs = {}
for i = 1, #vCrvs do
if EgtGetType( vCrvs[i]) == GDB_TY.CRV_LINE then
local vtDir = EgtSV( vCrvs[i])
local vtOrtho = Vector3d( vtDir)
vtOrtho:rotate( Z_AX(), 90)
local nSemiPlaneId = EgtSurfFrRectangle( nGrpTmp, ORIG(), Point3d( EgtCurveLength( vCrvs[i]) + 2 * dExtraLen, dExtraLen, 0))
local frRect = Frame3d( EgtSP( vCrvs[i]) - vtDir * dExtraLen, vtDir, vtOrtho, Z_AX())
EgtTransform( nSemiPlaneId, frRect)
table.insert( vSemiPlanes, nSemiPlaneId)
elseif EgtGetType( vCrvs[i]) == GDB_TY.CRV_ARC then
local nCrvId = CreateCurveExtension( vCrvs[i], nGrpTmp)
table.insert( tArcs, { nCrvId = nCrvId, nOrigId = vCrvs[i], dRad = EgtArcRadius( vCrvs[i])})
else
-- se composita deve contenere un arco, recupero il suo raggio
local _, dEnd = EgtCurveDomain( vCrvs[i])
local dRad = 0
for j = 0, dEnd - 1 do
dRad = EgtCurveCompoRadius( vCrvs[i], j)
if dRad > 0 then break end
end
local nCrvId = CreateCurveExtension( vCrvs[i], nGrpTmp)
table.insert( tArcs, { nCrvId = nCrvId, nOrigId = vCrvs[i], dRad = dRad})
end
end
-- calcolo la regione definita dai semipiani
for i = 2, #vSemiPlanes do
EgtSurfFrIntersect( vSemiPlanes[1], vSemiPlanes[i])
EgtErase( vSemiPlanes[i])
end
nSurfId = vSemiPlanes[1]
-- se presenti archi, calcolo il loro contributo alla regione
if #tArcs > 0 then
local nCrvBorder = EgtExtractSurfFrChunkLoops( nSurfId, 0, nGrpTmp)
-- riordino per raggio decrescente ( per gestire prima quelle più grandi che potrebbero contenere le altre)
table.sort( tArcs, function ( a, b) return a.dRad > b.dRad end)
for i = 1, #tArcs do
-- limito la curva estesa alla regione
local nSurfTrim = EgtSurfFlatRegion( nGrpTmp, nCrvBorder)
local nCrv, nCnt = EgtTrimCurveWithRegion( tArcs[i].nCrvId, nSurfTrim, true, false)
-- se errore lo ignoro
if not nCrv then
nCnt = 0
end
if nCnt > 0 then
-- unisco tratto iniziale e finale se consecutivi
if nCnt > 1 and AreSamePointApprox( EgtSP( nCrv), EgtEP( nCrv + nCnt - 1)) then
if EgtGetType( nCrv) == GDB_TY.CRV_ARC then
EgtModifyCurveStartPoint( nCrv, EgtSP( nCrv + nCnt - 1))
EgtErase( nCrv + nCnt - 1)
else
EgtAddCurveCompoCurve( nCrv, nCrv + nCnt - 1, true, false)
end
nCnt = nCnt - 1
end
-- spezzo in corrispondenza di eventuali punti tangenti alla regione
local vArcs = EgtTableFill( nCrv, nCnt)
for j = nCrv, nCrv + nCnt - 1 do
local nInters, nPntCnt, nCrvCnt = EgtCurveCurveInters( j, nCrvBorder, nGrpTmp)
if nInters then
if nCnt == 1 then
EgtChangeClosedCurveStartPoint( j, EgtSP( nInters))
end
local nCurrCrv = j
for nPntId = nInters, nInters + nPntCnt - 1 do
local dPar = EgtCurveParamAtPoint( nCurrCrv, EgtSP( nPntId))
local nNewCrv = EgtSplitCurveAtParam( nCurrCrv, dPar)
if nNewCrv then
table.insert( vArcs, nNewCrv)
nCurrCrv = nNewCrv
end
end
end
end
-- modifico il bordo corrente considerando solo i tratti che poggiano sulle curve originali
for j = 1, #vArcs do
if CheckExtensionOverlap( vArcs[j], tArcs[i].nOrigId) then
local dParS = EgtCurveParamAtPoint( nCrvBorder, EgtSP( vArcs[j]), 100 * GEO.EPS_SMALL)
local dParE = EgtCurveParamAtPoint( nCrvBorder, EgtEP( vArcs[j]), 100 * GEO.EPS_SMALL)
EgtTrimCurveStartEndAtParam( nCrvBorder, dParE, dParS)
EgtAddCurveCompoCurve( nCrvBorder, vArcs[j])
break
end
end
end
end
-- ricostruisco la superficie
nSurfId = EgtSurfFlatRegion( nGrpTmp, nCrvBorder)
end
EgtRelocateGlob( nSurfId, nGrp)
EgtErase( nGrpTmp)
return nSurfId
end
---------------------------------------------------------------------
-- funzione che data una lista di curve ordinate e orientate le estende o le taglia per creare una curva chiusa
local function TrimOrderedCurves( vCrvs, bDelete, nSurfId)
local nGrpTmp = EgtGroup( GDB_ID.ROOT)
EgtSetStatus( nGrpTmp, GDB_ST.OFF)
-- se non calcolata, costruisco la regione definita dalle curve
if not nSurfId then
nSurfId = CalcIntersectionRegion( vCrvs, nGrpTmp)
end
-- copia estesa delle curve per verificare gli overlaps
local vExtCrvs = {}
for i = 1, #vCrvs do
vExtCrvs[i] = CreateCurveExtension( vCrvs[i], nGrpTmp)
end
-- recupero le curve di bordo della regione
local nBorderId = EgtExtractSurfFrChunkLoops( nSurfId, 0, nGrpTmp)
local nCrvBorder, nCnt = EgtExplodeCurveCompo( nBorderId)
-- associo ad ogni curva originale le curve di bordo corrispondenti
-- per gestire correttamente associazione devo partire da una curva di vCrvs e un tratto di nCrvBorder in corrispondenza biunivoca
-- ( possono esserci curve di vCrvs senza corrispondente o con più corrispondenti tra le curve di bordo)
local nFirstIdxCrv = 1
local nFirstIdxBorder = 1
for i = 1, #vCrvs do
local vCrvBorderRef = {}
for nId = nCrvBorder, nCrvBorder + nCnt - 1 do
local dDist = EgtPointCurveDist( EgtMP( nId), vExtCrvs[i])
if dDist < GEO.EPS_SMALL then
table.insert( vCrvBorderRef, nId)
end
end
if #vCrvBorderRef == 1 then
-- preparo indici in modo che siano 0-based
nFirstIdxCrv = i - 1
nFirstIdxBorder = vCrvBorderRef[1] - nCrvBorder
break
end
end
-- creo tabella di corrispondenze vCrvs -> CrvBorder
local tabAss = {}
local nC = nFirstIdxCrv
local nB = nFirstIdxBorder
repeat
-- cerco la curva originale associata partendo dall'ultima trovata
local dDist = EgtPointCurveDist( EgtMP( nCrvBorder + nB), vExtCrvs[nC+1])
local nSafeCnt = 0
while dDist > 2 * GEO.EPS_SMALL and nSafeCnt < #vExtCrvs do
nSafeCnt = nSafeCnt + 1
nC = ( nC + 1) % #vCrvs
dDist = EgtPointCurveDist( EgtMP( nCrvBorder + nB), vExtCrvs[nC+1])
end
-- se non ho trovato curva associata errore
if nSafeCnt == #vExtCrvs then
return
end
-- se la curva originale trovata è già associata ad una curva di bordo, verifico se posso associare alla curva di bordo corrente la curva originale consecutiva
-- ( per gestire estensioni che si sovrappongono a curve originali)
if tabAss[vCrvs[nC + 1]] then
local nNext = ( nC + 1) % #vCrvs
dDist = EgtPointCurveDist( EgtMP( nCrvBorder + nB), vExtCrvs[nNext+1])
while dDist < GEO.EPS_SMALL do
nC = nNext
nNext = ( nNext + 1) % #vCrvs
dDist = EgtPointCurveDist( EgtMP( nCrvBorder + nB), vExtCrvs[nNext+1])
end
end
-- aggiungo associazione
local nOrigCrv = vCrvs[nC + 1]
if tabAss[nOrigCrv] then
table.insert( tabAss[nOrigCrv], nCrvBorder + nB)
else
tabAss[nOrigCrv] = { nCrvBorder + nB}
end
-- passo alla curva di bordo successiva
nB = ( nB + 1) % nCnt
until nB == nFirstIdxBorder
-- sostituisco le curve originali con quelle di bordo appena calcolate
local vResultCurves = {}
local vExtraCurves = {}
for i = 1, #vCrvs do
if not tabAss[vCrvs[i]] then
-- se non ha curve di bordo associate è curva extra da gestire in modo speciale
if bDelete then
EgtErase( vCrvs[i])
else
-- se non va eliminata la restituisco come curva extra
EgtSetStatus( vCrvs[i], GDB_ST.OFF)
table.insert( vExtraCurves, vCrvs[i])
end
else
local nCrvId
if #tabAss[vCrvs[i]] > 1 then
-- se ha associata più di una curva di bordo creo la compo corrispondente
nCrvId = EgtCurveCompo( nGrpTmp, tabAss[vCrvs[i]])
else
nCrvId = tabAss[vCrvs[i]][1]
end
-- assegno il nome
local sName = EgtGetName( vCrvs[i])
if sName then
EgtSetName( nCrvId, sName)
end
-- copio le info
local vInfo = EgtGetAllInfo( vCrvs[i])
for j = 1, #vInfo do
local sInfo = EgtSplitString( vInfo[j], '=')
EgtSetInfo( nCrvId, sInfo[1], sInfo[2])
end
-- riposiziono
EgtRelocateGlob( nCrvId, vCrvs[i], GDB_IN.AFTER)
-- modifico l'id assegnando quello della curva originale che sostituisce
EgtErase( vCrvs[i])
EgtChangeId( nCrvId, vCrvs[i])
table.insert( vResultCurves, vCrvs[i])
end
end
EgtErase( nGrpTmp)
return vResultCurves, vExtraCurves
end
---------------------------------------------------------------------
-- funzione che crea il bisettore parabolico tra linea e arco
local function CalcParabolicBisector( nCrv1, nCrv2, dDim, nGrp, bArcExternal, bLineExternal)
-- modifico le curve affinchè abbiano estremo in comune
local ptInt = FindIntersectionPoint( nCrv1, nCrv2, EgtSP( nCrv2))
EgtModifyCurveStartPoint( nCrv2, ptInt)
EgtModifyCurveEndPoint( nCrv1, ptInt)
-- calcolo coefficienti dell'equazione del bisettore ( equazione presa da Vroni)
local nArc, nLine, nSign
if EgtGetType( nCrv1) == GDB_TY.CRV_ARC then
nArc = nCrv1
nLine = nCrv2
nSign = -1
else
nArc = nCrv2
nLine = nCrv1
nSign = 1
end
local ptC = EgtCP( nArc)
local dRad = EgtArcRadius( nArc)
-- equazione della retta
local dCoeffA = - EgtSV( nLine):getY()
local dCoeffB = EgtSV( nLine):getX()
local dCoeffC = - dCoeffA * ptInt:getX() - dCoeffB * ptInt:getY()
local dDist = dCoeffA * ptC:getX() + dCoeffB * ptC:getY() + dCoeffC
local dA = ptC:getX() - dCoeffA * dDist
local dB = ptC:getY() - dCoeffB * dDist
local dZ = ptC:getZ()
local k1 = EgtIf( bArcExternal, 1, -1) -- 1 esterno alla circonferenza / -1 interno alla circonferenza
local k2 = EgtIf( bLineExternal, 1, -1) -- 1 a destra della linea / -1 a sinistra della linea
-- campiono il bisettore ( è parametrizzato sul valore di offset t)
local vPoints = {}
local nTot = 50
for i = 1, nTot do
local t = dDim / ( nTot - 1) * ( i - 1)
local dDiscriminant = dRad * dRad + 2 * t * ( k1 * dRad - k2 * dDist) - dDist * dDist
local dX, dY
if dDiscriminant < GEO.EPS_ZERO then
dX = dA - k2 * dCoeffA * t
dY = dB - k2 * dCoeffB * t
else
dX = dA - k2 * dCoeffA * t + nSign * dCoeffB * sqrt( dDiscriminant)
dY = dB - k2 * dCoeffB * t - nSign * dCoeffA * sqrt( dDiscriminant)
end
vPoints[i] = Point3d( dX, dY, dZ)
end
local nCompo = EgtCurveCompoFromPoints( nGrp, vPoints)
return nCompo
end
---------------------------------------------------------------------
local function CreateTestBoxFromOutline( nOutlineId, nProfileId, b3Profile)
local frBox
local b3Box
local dDimStd = b3Profile:getDimX()
local dDimReal = EgtGetInfo( nOutlineId, WIN_PART_DIM, 'd')
if EgtGetType( nOutlineId) == GDB_TY.CRV_LINE then
-- oriento il box come la curva
frBox = Frame3d( EgtSP( nOutlineId), Z_AX(), EgtSV( nOutlineId))
b3Box = EgtGetBBoxRef( nOutlineId, GDB_BB.STANDARD, frBox)
-- ingrandisco il box con punti opportuni per tenere conto delle dimensioni del pezzo
local vtDir = VectorFromRotated( EgtSV( nOutlineId), Z_AX(), 90)
local ptMin = EgtSP( nOutlineId) + vtDir * abs( b3Profile:getMin():getX() * dDimReal / dDimStd)
local ptMax = EgtSP( nOutlineId) - vtDir * abs( b3Profile:getMax():getX() * dDimReal / dDimStd)
ptMin:toLoc( frBox)
ptMax:toLoc( frBox)
b3Box:Add( ptMin)
b3Box:Add( ptMax)
else
-- calcolo il rettangolo di area minima che racchiude il pezzo
local nOffsMax = EgtOffsetCurveAdv( nOutlineId, b3Profile:getMax():getX() * dDimReal / dDimStd)
local nOffsMin = EgtOffsetCurveAdv( nOutlineId, b3Profile:getMin():getX() * dDimReal / dDimStd)
EgtInvertCurve( nOffsMin)
local nCompo = EgtCurveCompo( EgtGetParent( nOutlineId), nOffsMax)
EgtAddCurveCompoLine( nCompo, EgtSP( nOffsMin))
EgtAddCurveCompoCurve( nCompo, nOffsMin)
EgtCloseCurveCompo( nCompo)
frBox = EgtCurveMinAreaRectangleXY( nCompo)
b3Box = EgtGetBBoxRef( nCompo, GDB_BB.STANDARD, frBox)
EgtErase( nCompo)
end
return b3Box, frBox
end
---------------------------------------------------------------------
-- funzione che data una curva di outline restituisce l'id del suo profilo teorico ( ovvero quello del file dei profili)
local function GetOutlineTheoricProfileId( nOutlineId, bForceBottomRail, nBottomRail)
-- recupero se è pezzo di telaio o anta
local nParentId = EgtGetParent( EgtGetParent( nOutlineId))
local nAreaType = EgtGetInfo( nParentId or GDB_ID.NULL, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL
while nParentId and ( nAreaType == WIN_AREATYPES.SPLIT or nAreaType == WIN_AREATYPES.NULL) do
nParentId = EgtGetParent( nParentId)
nAreaType = EgtGetInfo( nParentId or GDB_ID.NULL, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL
end
-- recupero il gruppo contenente il profilo
local nProfilesGrpId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE)
local nLayerId
if nAreaType == WIN_AREATYPES.FRAME then
nLayerId = EgtGetFirstNameInGroup( nProfilesGrpId, WIN_FRAME)
elseif nAreaType == WIN_AREATYPES.SASH then
nLayerId = EgtGetFirstNameInGroup( nProfilesGrpId, WIN_SASH)
elseif nAreaType == WIN_AREATYPES.FILL then
nLayerId = EgtGetFirstNameInGroup( nProfilesGrpId, WIN_FILL)
end
-- recupero il nome del profilo
local sProfileName = EgtGetInfo( nOutlineId, WIN_PROFILETYPE)
-- controlli per bottomrail
if EgtGetName( nOutlineId) == WIN_BOTTOM then
local nBottomRailTot = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL, 'i') or 0
if nBottomRailTot > 0 then
if bForceBottomRail then
sProfileName = WIN_FILL_RAIL
elseif nBottomRail then
if nBottomRail == nBottomRailTot then
sProfileName = WIN_FILL_RAIL
else
sProfileName = WIN_RAIL
end
end
end
end
-- restituisco il profilo
return EgtGetFirstNameInGroup( nLayerId, sProfileName)
end
---------------------------------------------------------------------
-- funzione che data una curva di outline restituisce l'id del suo profilo reale ( preso dal pezzo)
local function GetOutlineProfileId( nOutlineId, bForceBottomRail, nBottomRail)
-- recupero il pezzo associato all'outline
local nPartId
if EgtGetName( nOutlineId) == WIN_BOTTOM then
-- controlli per bottomrail
local nBottomRailTot = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL, 'i') or 0
if nBottomRailTot > 0 then
local vBottomRailParts = EgtGetInfo( nOutlineId, WIN_REF_BOTTOMRAIL_PART, 'vi')
if bForceBottomRail then
-- devo recuperare l'ultimo bottomrail
nPartId = vBottomRailParts[#vBottomRailParts]
elseif nBottomRail then
-- devo recuperare il bottomrail indicato
nPartId = vBottomRailParts[nBottomRail]
end
end
-- controllo per soglia : non avendo un pezzo associato, devo restituire il profilo teorico
local bThreshold = EgtGetInfo( nOutlineId, WIN_THRESHOLD, 'b')
if bThreshold then
local nProfileGrpId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE)
local nFrameProfileGrpId = EgtGetFirstNameInGroup( nProfileGrpId, WIN_FRAME)
local sThreshold = EgtGetInfo( nOutlineId, WIN_PROFILETYPE)
return EgtGetFirstNameInGroup( nFrameProfileGrpId, sThreshold)
end
end
if not nPartId then
nPartId = EgtGetInfo( nOutlineId, WIN_REF_PART, 'i')
end
-- recupero il profilo
local nProfileGrpId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nMainProfileId = EgtGetFirstNameInGroup( nProfileGrpId, WIN_PRF_MAIN)
return nMainProfileId
end
---------------------------------------------------------------------
-- funzione che restituisce l'outline non virtuale associato alla curva ( potrebbe anche essere la curva stessa)
local function GetNonVirtualOutline( nOutlineId)
local nSouOutlineId = nOutlineId
local nAreaType = EgtGetInfo( EgtGetParent( EgtGetParent( nSouOutlineId)), WIN_AREATYPE, 'i')
while nAreaType ~= WIN_AREATYPES.FRAME and nAreaType ~= WIN_AREATYPES.SASH and EgtGetName( abs( nSouOutlineId)) ~= WIN_SPLIT do
nSouOutlineId = EgtGetInfo( abs( nSouOutlineId), WIN_SOU_OUTLINE, 'i')
local nAreaId = EgtGetParent( EgtGetParent( abs( nSouOutlineId)))
nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
end
return nSouOutlineId
end
---------------------------------------------------------------------
-- funzione che recupera il pezzo associato ad un outline
local function FindAssociatedPart( nOutlineId, bUseBottomRail)
-- ricavo la curva non virtuale associata ( ovvero la curva da cui deriva che ha un pezzo associato)
local nCrvId = abs( GetNonVirtualOutline( nOutlineId))
local nPartId = EgtGetInfo( nCrvId, WIN_REF_PART, 'i')
-- se serve bottomrail verifico se presente
if bUseBottomRail then
local vBottomRailParts = EgtGetInfo( nCrvId, WIN_REF_BOTTOMRAIL_PART, 'vi')
if vBottomRailParts then
nPartId = vBottomRailParts[#vBottomRailParts]
end
end
return nPartId
end
---------------------------------------------------------------------
-- funzione che calcola il box di un profilo ( guardando la sua curva Ref) rispetto al suo frame
local function GetProfileLocalBox( nProfileId)
-- recupero il frame del profilo
local nFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frFrame = EgtFR( nFrameId, GDB_ID.ROOT)
-- recupero il Ref del profilo e ne calcolo il box
local nRefId = EgtGetFirstNameInGroup( nProfileId, WIN_REF)
local b3Box = EgtGetBBoxRef( nRefId, GDB_BB.STANDARD, frFrame)
return b3Box
end
---------------------------------------------------------------------
-- funzione che restituisce il tipo di controprofilo dell'outline adiacente
local function GetProfileCtrIn( nPrevOutlineId, nOutlineId, nPrevProfileId, bStart)
local sCtrIn = WIN_CTRIN
local nPrfChange = EgtGetInfo( abs( nPrevOutlineId), WIN_PRF_CHANGE, 'i') or 0
local nSide = EgtIf( nPrevOutlineId < 0, 1, 2)
-- 1) se è inglesina interna
if EgtGetName( nOutlineId) == WIN_SPLIT and EgtGetInfo( nOutlineId, WIN_MUNTINFILL_SIDE, 'i') == WIN_MUNTINFILL_SIDES.IN then
-- deve finire contro il fermavetro ( dal lato corretto nel caso di split) oppure contro il bordo interno se finisce contro altra inglesina
if EgtGetName( abs( nPrevOutlineId)) == WIN_SPLIT then
if EgtGetInfo( abs( nPrevOutlineId), WIN_SPLITTYPE, 'i') ~= WIN_SPLITTYPES.MUNTIN_FILL then
sCtrIn = WIN_CTRIN .. WIN_STRIP
end
else
sCtrIn = WIN_CTRIN .. WIN_STRIP
end
-- 2) se finisce contro cambio profilo devo capire se va tagliato il controprofilo sash o fill
elseif nPrfChange & nSide > 0 then
local nPrfChangeCurr = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'i') or WIN_PRF_CHANGE_TYPES.NULL
if ( bStart and nPrfChangeCurr & WIN_PRF_CHANGE_TYPES.START > 0) or ( not bStart and nPrfChangeCurr & WIN_PRF_CHANGE_TYPES.END > 0) then
-- se il cambio profilo è stato determinato dall'outline allora devo tagliarlo con la parte sash
sCtrIn = WIN_SASH .. WIN_CTRIN
else
-- per capire contro quale parte finisce posso guardare i figli dell'outline. Se l'outline non ha cambio profilo posso considerare un figlio qualsiasi,
-- altrimenti devo considerare un figlio sull'estremo in analisi per essere sicuri di individuare la tipologia corretta
local nType
if nPrfChangeCurr == WIN_PRF_CHANGE_TYPES.NULL then
local vChildren = EgtGetInfo( nOutlineId, WIN_CHILD_OUTLINE, 'vi')
if not vChildren then
-- l'unico caso senza figli è inglesina, quindi sicuramente finisce contro la parte fill
nType = WIN_AREATYPES.FILL
else
local nAreaId = EgtGetParent( EgtGetParent( abs( vChildren[1])))
nType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
end
else
if EgtGetName( nOutlineId) == WIN_SPLIT then
-- il figlio sull'estremo è salvato in una info
local sKey = EgtIf( bStart, WIN_MIXED_START_CHILDREN, WIN_MIXED_END_CHILDREN) .. '1'
local nChildrenType = EgtGetInfo( nOutlineId, sKey, 'i')
nType = EgtIf( nChildrenType == WIN_CHILDREN_TYPES.SASH, WIN_AREATYPES.SASH, WIN_AREATYPES.FILL)
else
-- per trovare il figlio nell'estremo corretto controllo quale figlio ha l'area in comune con un figlio di PrevOutline
local vChildren = EgtGetInfo( nOutlineId, WIN_CHILD_OUTLINE, 'vi')
local vChildrenPrev = EgtGetInfo( abs( nPrevOutlineId), WIN_CHILD_OUTLINE, 'vi')
for i = 1, #vChildren do
if nType then
break
end
local nRefArea = EgtGetParent( EgtGetParent( abs( vChildren[i])))
for j = 1, #vChildrenPrev do
local nArea = EgtGetParent( EgtGetParent( abs( vChildrenPrev[j])))
if nArea == nRefArea then
nType = EgtGetInfo( nArea, WIN_AREATYPE, 'i')
break
end
end
end
end
end
if nType == WIN_AREATYPES.SASH then
sCtrIn = WIN_SASH .. WIN_CTRIN
else
sCtrIn = WIN_FILL .. WIN_CTRIN
end
end
end
-- se finisce contro split recupero il controprofilo dal lato corretto ( destro (1) o sinistro (2))
if EgtGetName( abs( nPrevOutlineId)) == WIN_SPLIT then
sCtrIn = sCtrIn .. tostring( nSide)
end
return sCtrIn
end
---------------------------------------------------------------------
-- funzione che costruisce una superficie estrudendo il nSectionId lungo l'outline
local function CreateProfileSurfById( nOutlineId, nProfileId, nSectionId, dExtraLen, nLayerId)
-- creo guida con estensione in tangenza
local nGuideId = EgtCopy( nOutlineId, nLayerId)
if EgtGetType( nGuideId) == GDB_TY.CRV_LINE then
EgtExtendCurveStartByLen( nGuideId, dExtraLen)
EgtExtendCurveEndByLen( nGuideId, dExtraLen)
else
nGuideId = EgtCurveCompo( nLayerId, nGuideId)
EgtAddCurveCompoLineTg( nGuideId, dExtraLen)
EgtAddCurveCompoLineTg( nGuideId, dExtraLen, false)
end
-- correzione nel caso di bottomrail
local sProfileType = EgtGetInfo( nProfileId, WIN_PROFILETYPE)
if sProfileType == WIN_RAIL or sProfileType == WIN_FILL_RAIL then
local dOffs = EgtGetInfo( nProfileId, WIN_RAILOFFS, 'd')
EgtOffsetCurve( nGuideId, - dOffs)
end
-- recupero il profilo da estrudere
local nSectionRefId = EgtCopyGlob( nSectionId, nLayerId)
-- posiziono la sezione di estrusione sulla guida :
-- recupero frame del profilo
local nProfileFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frProfile = EgtFR( nProfileFrameId, GDB_ID.ROOT)
frProfile:invert()
-- calcolo il frame di destinazione sulla guida
local frDest = Frame3d( EgtSP( nGuideId), - EgtSV( nGuideId), GDB_RT.GLOB)
-- posiziono con i riferimenti
EgtTransform( nSectionRefId, frProfile, GDB_RT.GLOB)
EgtTransform( nSectionRefId, frDest, GDB_RT.GLOB)
-- creo la superfice di estrusione
local nStmId = EgtSurfTmSwept( nLayerId, nSectionRefId, nGuideId, false, WIN_SURF_APPROX)
EgtErase( nGuideId)
EgtErase( nSectionRefId)
return nStmId
end
---------------------------------------------------------------------
-- come CreateProfileSurfById ma riceve il nome della sezione da estrudere
local function CreateProfileSurf( nOutlineId, nProfileId, sSectionName, dExtraLen, nLayerId)
-- recupero l'id della sezione da estrudere
local nSectionId = EgtGetFirstNameInGroup( nProfileId, sSectionName)
if not nSectionId then return end
return CreateProfileSurfById( nOutlineId, nProfileId, nSectionId, dExtraLen, nLayerId)
end
----------------------------------------------------------------------------------
------------------------------ CALCOLO DEI PROFILI ------------------------------
----------------------------------------------------------------------------------
-- funzione che verifica la tipologia dei figli di una curva analizzando i base outlines
local function GetBaseChildrenType( nCrvId)
local vStack = EgtGetInfo( nCrvId, WIN_CHILD, 'vi') or {}
local i = 1
local vFillChildren = {}
local vSashChildren = {}
while vStack[i] do
-- verifico se la sua area è di tipo sash o fill
local nAreaId = EgtGetParent( EgtGetParent( abs( vStack[i])))
local nType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nType == WIN_AREATYPES.FILL then
table.insert( vFillChildren, vStack[i])
elseif nType == WIN_AREATYPES.SASH then
table.insert( vSashChildren, vStack[i])
else
-- aggiungo i suoi figli tra gli elementi da analizzare
local vChildren = EgtGetInfo( abs( vStack[i]), WIN_CHILD, 'vi') or {}
EgtJoinTables( vStack, vChildren)
end
-- aggiorno il contatore
i = i + 1
end
local nChildrenType
if #vFillChildren > 0 and #vSashChildren > 0 then
nChildrenType = WIN_CHILDREN_TYPES.MIXED -- cambio profilo
elseif #vFillChildren > 0 then
nChildrenType = WIN_CHILDREN_TYPES.FILL
elseif #vSashChildren > 0 then
nChildrenType = WIN_CHILDREN_TYPES.SASH
else
nChildrenType = WIN_CHILDREN_TYPES.NULL
end
EgtSetInfo( nCrvId, WIN_CHILDREN_TYPE, nChildrenType)
EgtSetInfo( nCrvId, WIN_SASH_CHILDREN, vSashChildren)
EgtSetInfo( nCrvId, WIN_FILL_CHILDREN, vFillChildren)
return nChildrenType
end
---------------------------------------------------------------------
-- funzione che identifica il tipo di split ( mullion, mixed, ...)
local function GetSplitType( nSplitId, nAreaId)
local nSplitType = EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i')
-- la tipologia è salvata nell'area solo se si tratta di un french split, negli altri casi va calcolata
if not nSplitType then
-- controllo se è dentro telaio, anta o vetro
local nParentAreaId = nAreaId
local nParentAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL
while nParentAreaId and ( nParentAreaType == WIN_AREATYPES.NULL or nParentAreaType == WIN_AREATYPES.SPLIT) do
nParentAreaId = EgtGetParent( nParentAreaId)
nParentAreaType = EgtGetInfo( nParentAreaId or GDB_ID.NULL, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL
end
-- se dentro anta
if nParentAreaType == WIN_AREATYPES.SASH then
nSplitType = WIN_SPLITTYPES.MUNTIN_SASH
-- se dentro vetro è inglesina incollata
elseif nParentAreaType == WIN_AREATYPES.FILL then
nSplitType = WIN_SPLITTYPES.MUNTIN_FILL
-- se dentro telaio verifico la tipologia dei figli
elseif nParentAreaType == WIN_AREATYPES.FRAME then
local nChildrenType = GetBaseChildrenType( nSplitId)
if nChildrenType == WIN_CHILDREN_TYPES.MIXED then
nSplitType = WIN_SPLITTYPES.MIXED
elseif nChildrenType == WIN_CHILDREN_TYPES.FILL then
nSplitType = WIN_SPLITTYPES.MUNTIN_FRAME
else -- sash o non definiti
nSplitType = WIN_SPLITTYPES.MULLION
end
end
if not nSplitType then
nSplitType = WIN_SPLITTYPES.NULL
end
end
-- salvo la tipologia come info sulla curva
EgtSetInfo( nSplitId, WIN_SPLITTYPE, nSplitType)
return nSplitType
end
---------------------------------------------------------------------
local function FindAdjacentSashType( nSplitId, nCurrType)
-- i figli della curva nSouId sono base outlines e non posso sapere a quali outlines corrispondono quindi per capire se sto guardando il figlio
-- corretto controllo se il tipo di anta è lo stesso del corrente oppure no
local vSplitChildren = EgtGetInfo( nSplitId, WIN_CHILD, 'vi')
local nAdjSashType = EgtGetInfo( EgtGetParent( EgtGetParent( abs( vSplitChildren[1]))), WIN_SASHTYPE, 'i')
if nAdjSashType == nCurrType then
-- se il tipo è lo stesso allora devo guardare l'altro figlio dello split
nAdjSashType = EgtGetInfo( EgtGetParent( EgtGetParent( abs( vSplitChildren[2]))), WIN_SASHTYPE, 'i')
end
return nAdjSashType
end
---------------------------------------------------------------------
-- funzione che calcola i profili delle ante sulle curve di outline ( non di base outline)
local function CalcSashProfiles( vOutlines, nAreaId)
local nSashType = EgtGetInfo( nAreaId, WIN_SASHTYPE, 'i') or WIN_SASHTYPES.NULL
local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0
-- imposto profili sash
for i = 1, #vOutlines do
local nOutlineId = vOutlines[i]
local sName = EgtGetName( nOutlineId)
-- se non è definita tipologia
if nSashType == WIN_SASHTYPES.NULL then
if sName == WIN_BOTTOM then
if nBottomRail == 0 then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRAME_BOTTOM)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_RAIL_BOTTOM)
end
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRAME_TOP)
end
else
-- verifico se deriva da una curva di split french ( e quindi deve avere profilo speciale e.g. battente/ricevente)
local nSouId = abs( EgtGetInfo( nOutlineId, WIN_SOU_OUTLINE, 'i'))
local nSplitType = EgtGetInfo( nSouId, WIN_SPLITTYPE, 'i')
if nSplitType == WIN_SPLITTYPES.FRENCH then
EgtSetInfo( nOutlineId, WIN_CRV_ON_FRENCH_SPLIT, true)
-- a) battente/ricevente
if nSashType == WIN_SASHTYPES.ACTIVE then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH_ACTIVE)
elseif nSashType == WIN_SASHTYPES.INACTIVE then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH_INACTIVE)
elseif nSashType == WIN_SASHTYPES.ACTIVE_OUT or nSashType == WIN_SASHTYPES.INACTIVE_OUT then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRENCH_OUT)
elseif nSashType == WIN_SASHTYPES.ACTIVE_IN then
-- scelgo il profilo in base al tipo dell'anta adiacente
local nAdjSashType = FindAdjacentSashType( nSouId, WIN_SASHTYPES.ACTIVE_IN)
if nAdjSashType == WIN_SASHTYPES.ACTIVE_OUT then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRENCH_IN)
else -- adiacente è inactive
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH_ACTIVE)
end
elseif nSashType == WIN_SASHTYPES.INACTIVE_IN then
-- scelgo il profilo in base al tipo dell'anta adiacente
local nAdjSashType = FindAdjacentSashType( nSouId, WIN_SASHTYPES.INACTIVE_IN)
if nAdjSashType == WIN_SASHTYPES.INACTIVE_OUT then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRENCH_IN)
else -- adiacente è active
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH_INACTIVE)
end
-- b) alzante scorrevole
elseif nSashType == WIN_SASHTYPES.SLIDE_MOVABLE then
local nAdjSashType = FindAdjacentSashType( nSouId, WIN_SASHTYPES.SLIDE_MOVABLE)
if nAdjSashType == WIN_SASHTYPES.SLIDE_MOVABLE then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_ACTIVE_IN)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_ACTIVE)
end
elseif nSashType == WIN_SASHTYPES.SLIDE_FIXED then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_INACTIVE)
elseif nSashType == WIN_SASHTYPES.SLIDE_MOVABLE_BACK then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_INACTIVE)
end
else
-- b) alzante scorrevole
if nSashType == WIN_SASHTYPES.SLIDE_MOVABLE then
if sName == WIN_BOTTOM then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLE_BOTTOM)
elseif sName == WIN_TOP then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLE_TOP)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLE_SIDE)
end
elseif nSashType == WIN_SASHTYPES.SLIDE_FIXED then
if sName == WIN_BOTTOM then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_FIXED_BOTTOM)
elseif sName == WIN_TOP then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_FIXED_TOP)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_FIXED_SIDE)
end
elseif nSashType == WIN_SASHTYPES.SLIDE_MOVABLE_BACK then
if sName == WIN_BOTTOM then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLEBACK_BOTTOM)
elseif sName == WIN_TOP then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLEBACK_TOP)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLEBACK_SIDE)
end
-- a) standard
else
if sName == WIN_BOTTOM then
-- verifico se bottomrail
if nBottomRail == 0 then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRAME_BOTTOM)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_RAIL_BOTTOM)
end
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRAME_TOP)
end
end
end
end
end
end
---------------------------------------------------------------------
-- funzione che cicla ricorsivamente su aree e sottoaree per impostare i tipi di profilo
local function CalculateAreaProfileType( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
-- FRAME
if nAreaType == WIN_AREATYPES.FRAME then
-- gestione soglia
local sThreshold = EgtGetInfo( nAreaId, WIN_THRESHOLD_PROFILE) or WIN_BOTTOM
local bThreshold = ( sThreshold == WIN_THRESHOLD)
-- assegno il profilo alle curve di outline
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_AREAOUTLINE)
local nOutlineId = EgtGetFirstInGroup( nOutlineLayerId)
while nOutlineId do
local sName = EgtGetName( nOutlineId)
-- verifico se soglia
if sName == WIN_BOTTOM then
EgtSetInfo( nOutlineId, WIN_THRESHOLD, bThreshold)
end
-- recupero il tipo dei figli
local nChildrenType = GetBaseChildrenType( nOutlineId)
-- a) se riempimento o non definiti
if nChildrenType == WIN_CHILDREN_TYPES.FILL or nChildrenType == WIN_CHILDREN_TYPES.NULL then
if sName == WIN_BOTTOM then
-- verifico presenza bottomrail
local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0
if nBottomRail == 0 then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FIXED .. '_' .. sThreshold)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_RAIL .. '_' .. sThreshold)
end
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FIXED_TOP)
end
-- b) se anta
elseif nChildrenType == WIN_CHILDREN_TYPES.SASH then
-- verifico tipologia di anta contro cui poggia
local vSashChildren = EgtGetInfo( nOutlineId, WIN_SASH_CHILDREN, 'vi')
local nSashArea = EgtGetParent( EgtGetParent( vSashChildren[1]))
local nSashType = EgtGetInfo( nSashArea, WIN_SASHTYPE, 'i') or WIN_SASHTYPES.NULL
-- b1) alzante scorrevole
if nSashType == WIN_SASHTYPES.SLIDE_MOVABLE or nSashType == WIN_SASHTYPES.SLIDE_FIXED or nSashType == WIN_SASHTYPES.SLIDE_MOVABLE_BACK then
EgtSetInfo( nAreaId, WIN_SLIDE_WINDOW, true)
if sName == WIN_BOTTOM then
EgtRemoveInfo( nAreaId, WIN_BOTTOMRAIL)
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE .. '_' .. sThreshold)
-- se le ante contro cui poggia sono tutte mobili devo aggiornare il profilo
if nSashType == WIN_SASHTYPES.SLIDE_MOVABLE_BACK then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLEBACK .. '_' .. sThreshold)
elseif nSashType == WIN_SASHTYPES.SLIDE_MOVABLE then
for i = 2, #vSashChildren do
local nSashArea = EgtGetParent( EgtGetParent( vSashChildren[i]))
local nSashType = EgtGetInfo( nSashArea, WIN_SASHTYPE, 'i') or WIN_SASHTYPES.NULL
if nSashType == WIN_SASHTYPES.SLIDE_MOVABLE_BACK then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLEBACK .. '_' .. sThreshold)
break
elseif nSashType == WIN_SASHTYPES.SLIDE_FIXED then
break
end
end
end
elseif sName == WIN_TOP then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_TOP)
else
if nSashType == WIN_SASHTYPES.SLIDE_MOVABLE then
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_MOVABLE)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SLIDE_FIXED)
end
end
-- b2) standard
else
if sName == WIN_BOTTOM then
EgtRemoveInfo( nAreaId, WIN_BOTTOMRAIL)
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH .. '_' .. sThreshold)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH_TOP)
end
end
-- c) se cambio profilo
elseif nChildrenType == WIN_CHILDREN_TYPES.MIXED then
EgtSetInfo( nAreaId, WIN_MIXED_WINDOW, true)
if sName == WIN_BOTTOM then
EgtRemoveInfo( nAreaId, WIN_BOTTOMRAIL)
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_MIXED_BOTTOM)
else
EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_MIXED_TOP)
end
end
nOutlineId = EgtGetNext( nOutlineId)
end
-- SPLIT
elseif nAreaType == WIN_AREATYPES.SPLIT then
local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT)
local vSplitIds = EgtGetAllInGroup( nSplitLayerId)
for i = 1, #vSplitIds do
-- ricavo il tipo di split
local nSplitType = GetSplitType( vSplitIds[i], nAreaId)
if nSplitType == WIN_SPLITTYPES.MULLION then
-- verifico direzione per assengare il profilo
local vtMedia = ( ( EgtEV( vSplitIds[i]) - EgtSV( vSplitIds[i])) / 2)
if not vtMedia:normalize() then
vtMedia = EgtSV( vSplitIds[i])
end
if abs( vtMedia:getX()) > abs( vtMedia:getY()) then
EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_SASH_HORIZONTAL)
else
EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_SASH_VERTICAL)
end
elseif nSplitType == WIN_SPLITTYPES.MUNTIN_SASH then
EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_SASH_SPLIT)
elseif nSplitType == WIN_SPLITTYPES.MUNTIN_FRAME then
EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_FRAME_SPLIT)
elseif nSplitType == WIN_SPLITTYPES.MUNTIN_FILL then
-- se solo interne o entrambe assegno il profilo in ( l'out verrà aggiunto successivamente durante il calcolo del suo outline), se solo out assegno direttamente
-- il profilo corretto
local sProfile = WIN_FILL_SPLIT_IN
local nType = EgtGetInfo( nAreaId, WIN_MUNTINFILL_SIDE, 'i')
if nType == WIN_MUNTINFILL_SIDES.OUT then
sProfile = WIN_FILL_SPLIT_OUT
end
local bSlide = EgtGetInfo( EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*'), WIN_SLIDE_WINDOW, 'b') or false
if bSlide then
sProfile = WIN_SLIDE .. '_' .. sProfile
end
EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, sProfile)
elseif nSplitType == WIN_SPLITTYPES.MIXED then
EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_MIXED_SPLIT)
end
-- se split di tipo french non ha profilo assegnato perchè non ha un pezzo associato
end
-- NULL
elseif nAreaType == WIN_AREATYPES.NULL then
-- le aree null sono aree virtuali quindi non hanno pezzi ( e dunque profili) associati
-- SASH
elseif nAreaType == WIN_AREATYPES.SASH then
-- i profili verranno calcolati direttamente sulle curve di outline perchè non è detto che corrispondano alle curve di base outline
end
-- calcolo i profili per le eventuali sottoaree
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
CalculateAreaProfileType( nChildAreaId)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
----------------------------------------------------------------------------------
----------------------------- PROFILI PEZZO -------------------------------------
----------------------------------------------------------------------------------
-- funzione che calcola l'offset da applicare alla curva di outline bottom per ottenere la curva di outline del bottomrail richiesto
local function CalcRailOffset( nOutlineId, nProfileId, nBottomRail)
-- recupero la dimensioni dei pezzi bottom e bottomrails
local dDimBottom = EgtGetInfo( nOutlineId, WIN_PART_DIM, 'd')
local vDimBottomRails = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL .. WIN_PART_DIM, 'vd')
local dOverlap = EgtGetInfo( nProfileId, WIN_OVERLAP, 'd')
local dRailOffs = dDimBottom
for i = 1, nBottomRail - 1 do
dRailOffs = dRailOffs + vDimBottomRails[i]
end
dRailOffs = dRailOffs - nBottomRail * dOverlap
return dRailOffs
end
----------------------------------------------------------------------------------
-- funzione che nel caso di profilo mixed split conserva solamente le curve veramente necessarie per le tipologie di figli
local function CreateMixedSplitProfile( nOutlineId, nProfileId)
-- sistemo i profili dx (1) e sx (2) : se da un lato è presente una sola tipologia di figli allora :
-- a) elimino le curve legate all'altra tipologia e la curva common legata al cambio profilo
-- b) rinomino le curve della tipologia presente
-- In questo modo si può gestire quel lato come in uno split non mixed. Se invece da un lato sono presenti entrambe le tipologie di figli allora non servono modifiche
local vSashProfiles = { WIN_SASH .. WIN_IN, WIN_SASH .. WIN_CTRIN, WIN_OFST .. WIN_SASH .. WIN_CTRIN}
local vFillProfiles = { WIN_FILL .. WIN_IN, WIN_FILL .. WIN_CTRIN, WIN_OFST .. WIN_FILL .. WIN_CTRIN, WIN_STRIP, WIN_CTRIN .. WIN_STRIP, WIN_OFST .. WIN_CTRIN .. WIN_STRIP}
local nNewNames = { WIN_IN, WIN_CTRIN, WIN_OFST .. WIN_CTRIN, WIN_STRIP, WIN_CTRIN .. WIN_STRIP, WIN_OFST .. WIN_CTRIN .. WIN_STRIP}
local nPrfChange = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'i')
for i = 1, 2 do
-- verifico se lato con cambio profilo
if nPrfChange & i == 0 then
-- recupero la tipologia di figli da quel lato
local nChildrenType = EgtGetInfo( nOutlineId, WIN_MIXED_START_CHILDREN .. tostring( i), 'i')
local vToBeRenamed = {}
local vToBeErased = {}
if nChildrenType == WIN_CHILDREN_TYPES.SASH then
vToBeRenamed = vSashProfiles
vToBeErased = vFillProfiles
elseif nChildrenType == WIN_CHILDREN_TYPES.FILL then
vToBeRenamed = vFillProfiles
vToBeErased = vSashProfiles
end
-- a) cancello
if #vToBeErased > 0 then
for j = 1, #vToBeErased do
local nId = EgtGetFirstNameInGroup( nProfileId, vToBeErased[j] .. tostring( i)) or GDB_ID.NULL
local nSimplId = EgtGetFirstNameInGroup( nProfileId, WIN_SIMPLIFIED .. vToBeErased[j] .. tostring( i)) or GDB_ID.NULL
EgtErase( { nId, nSimplId})
end
local nId = EgtGetFirstNameInGroup( nProfileId, WIN_MIXED_COMMON .. WIN_IN .. tostring( i)) or GDB_ID.NULL
local nSimplId = EgtGetFirstNameInGroup( nProfileId, WIN_SIMPLIFIED .. WIN_MIXED_COMMON .. WIN_IN .. tostring( i)) or GDB_ID.NULL
EgtErase( { nId, nSimplId})
end
-- b) rinomino
for j = 1, #vToBeRenamed do
local nId = EgtGetFirstNameInGroup( nProfileId, vToBeRenamed[j] .. tostring( i)) or GDB_ID.NULL
EgtSetName( nId, nNewNames[j] .. tostring( i))
local nSimplId = EgtGetFirstNameInGroup( nProfileId, WIN_SIMPLIFIED .. vToBeRenamed[j] .. tostring( i)) or GDB_ID.NULL
EgtSetName( nSimplId, WIN_SIMPLIFIED .. nNewNames[j] .. tostring( i))
end
end
end
end
---------------------------------------------------------------------
-- funzione che crea il profilo della dimensione corretta
local function AdjustProfileDimension( nOutlineId, nProfileId, dDimOld, dDim)
local bSplit = ( EgtGetName( nOutlineId) == WIN_SPLIT)
local bPrfChange = ( EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'i') == WIN_PRF_CHANGE_TYPES.IN)
local bMixedSplit = ( bSplit and EgtGetInfo( nOutlineId, WIN_SPLITTYPE, 'i') == WIN_SPLITTYPES.MIXED)
local dDeltaDim = dDim - dDimOld
local nFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frSection = EgtFR( nFrameId, GDB_RT.GLOB)
local vtMove = - frSection:getVersX()
-- traslo le curve "interne"
local vCurves = { WIN_IN, WIN_CTRIN, WIN_OFST .. WIN_CTRIN, WIN_STRIP, WIN_CTRIN .. WIN_STRIP, WIN_OFST .. WIN_CTRIN .. WIN_STRIP}
if bPrfChange then
vCurves = { WIN_SASH .. WIN_IN, WIN_FILL .. WIN_IN, WIN_SASH .. WIN_CTRIN, WIN_FILL .. WIN_CTRIN, WIN_OFST .. WIN_SASH .. WIN_CTRIN, WIN_OFST .. WIN_FILL .. WIN_CTRIN,
WIN_MIXED_COMMON .. WIN_IN, WIN_STRIP, WIN_CTRIN .. WIN_STRIP, WIN_OFST .. WIN_CTRIN .. WIN_STRIP}
end
if bSplit then
for i = 1, #vCurves do
vCurves[i] = vCurves[i] .. '2'
end
end
for i = 1, #vCurves do
local nCrvId = EgtGetFirstNameInGroup( nProfileId, vCurves[i]) or GDB_ID.NULL
EgtMove( nCrvId, dDeltaDim * vtMove, GDB_RT.GLOB)
local nSimplifiedCrvId = EgtGetFirstNameInGroup( nProfileId, WIN_SIMPLIFIED .. vCurves[i]) or GDB_ID.NULL
EgtMove( nSimplifiedCrvId, dDeltaDim * vtMove, GDB_RT.GLOB)
end
-- traslo i dowels
local vDowels = EgtGetNameInGroup( nProfileId, WIN_DOWEL .. '*')
EgtMove( vDowels, 0.5 * dDeltaDim * vtMove)
-- ricostruisco la sezione ( i=1) e la sezione semplificata ( i=2) tranne nel caso di split mixed ( perchè la sezione non è definita)
if not bMixedSplit then
for i = 1, 2 do
-- prefisso al nome delle curve per sezione standard o semplificata
local sSimplPrefix = EgtIf( i == 1, '', WIN_SIMPLIFIED)
-- prefisso al nome delle curve per gestire parte sash o fill ( cambio profilo)
local vsPartPrefix = EgtIf( bPrfChange, { WIN_SASH, WIN_FILL}, {''})
-- nome dei semiprofili da combinare per creare la sezione
local vsProfiles = EgtIf( bSplit, { WIN_IN .. '1', WIN_IN .. '2'}, { WIN_IN, WIN_OUT})
for j = 1, #vsPartPrefix do
local nSectionId = EgtGetFirstNameInGroup( nProfileId, sSimplPrefix .. vsPartPrefix[j] .. WIN_SECTION)
EgtErase( nSectionId)
local vSemiProfileNames = { sSimplPrefix .. vsPartPrefix[j] .. vsProfiles[1], sSimplPrefix .. vsProfiles[2]}
local vSemiProfiles = { EgtGetFirstNameInGroup( nProfileId, vSemiProfileNames[1]), EgtGetFirstNameInGroup( nProfileId, vSemiProfileNames[2])}
nSectionId = EgtCurveCompo( nProfileId, vSemiProfiles[1], false)
EgtAddCurveCompoLine( nSectionId, EgtSP( vSemiProfiles[2]))
EgtAddCurveCompoCurve( nSectionId, vSemiProfiles[2], false)
EgtCloseCurveCompo( nSectionId)
EgtSetName( nSectionId, sSimplPrefix .. vsPartPrefix[j] .. WIN_SECTION)
end
end
end
-- ricostruisco il box
local nRef = EgtGetFirstNameInGroup( nProfileId, WIN_REF)
local b3Profile = EgtGetBBoxRef( nRef, GDB_BB.STANDARD, frSection)
EgtErase( nRef)
nRef = EgtRectangle2P( nProfileId, b3Profile:getMin() - X_AX() * dDeltaDim, b3Profile:getMax())
EgtTransform( nRef, EgtFR( nFrameId))
EgtSetName( nRef, WIN_REF)
if EgtGetName( nOutlineId) == WIN_SPLIT then
-- sposto il frame per lasciarlo posizionato come prima rispetto al box ( sono state spostate solo le curve interne)
local dMove = b3Profile:getMax():getX() / dDimOld * dDim - b3Profile:getMax():getX()
EgtMove( nFrameId, dMove * vtMove)
end
end
---------------------------------------------------------------------
local function CreatePartProfile( nPartId, nOutlineId, dDim, nBottomRail)
-- gruppo per i profili
local nProfileLayerId = EgtGroup( nPartId)
EgtSetName( nProfileLayerId, WIN_PROFILE)
EgtSetStatus( nProfileLayerId, GDB_ST.OFF)
-- recupero il profilo teorico
local nOrigProfileId = GetOutlineTheoricProfileId( nOutlineId, false, nBottomRail)
-- creo copia
local nProfileId = EgtCopy( nOrigProfileId, nProfileLayerId)
local sProfileType = EgtGetName( nProfileId)
EgtSetInfo( nProfileId, WIN_PROFILETYPE, sProfileType)
EgtSetName( nProfileId, WIN_PRF_MAIN)
-- se bottomrail salvo info per scostamento dall'outline
if nBottomRail then
local dRailOffs = CalcRailOffset( nOutlineId, nProfileId, nBottomRail)
EgtSetInfo( nProfileId, WIN_RAILOFFS, dRailOffs)
end
-- se split mixed aggiusto le curve del profilo in base alla reale tipologia di figli
if sProfileType == WIN_MIXED_SPLIT then
CreateMixedSplitProfile( nOutlineId, nProfileId)
end
-- verifico se vanno modificate le dimensioni del profilo
local dDimStd = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
if abs( dDimStd - dDim) > GEO.EPS_SMALL then
AdjustProfileDimension( nOutlineId, nProfileId, dDimStd, dDim)
end
-- recupero le info di pinzaggio dal profilo di estrusione
CopyInfo( nPartId, nProfileId, WIN_PRC_OFFY_1, 0)
CopyInfo( nPartId, nProfileId, WIN_PRC_OFFZ_1, 0)
CopyInfo( nPartId, nProfileId, WIN_PRC_OFFY_2, 0)
CopyInfo( nPartId, nProfileId, WIN_PRC_OFFZ_2, 0)
CopyInfo( nPartId, nProfileId, WIN_PRC_CLAMPV_1, 0)
CopyInfo( nPartId, nProfileId, WIN_PRC_CLAMPV_2, 0)
end
---------------------------------------------------------------------
-- funzione che recupera i profili start ed end di un pezzo
local function CalcStartEndProfiles( nPartId, nOutlineId, vPrevOutlineId, vNextOutlineId)
-- recupero il gruppo per i profili
local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
-- recupero profili start/end e ne creo copia
for i = 1, #vPrevOutlineId do
-- se il tipo corrente è split il pezzo va tagliato con eventuale bottomrail, altrimenti con il bottom
local nOrigStartProfileId = GetOutlineProfileId( abs( vPrevOutlineId[i]), EgtGetName( nOutlineId) == WIN_SPLIT)
local nStartProfileId = EgtCopy( nOrigStartProfileId, nProfileLayerId)
EgtSetName( nStartProfileId, WIN_PRF_START)
end
for i = 1, #vNextOutlineId do
local nOrigEndProfileId = GetOutlineProfileId( abs( vNextOutlineId[i]), EgtGetName( nOutlineId) == WIN_SPLIT)
local nEndProfileId = EgtCopy( nOrigEndProfileId, nProfileLayerId)
EgtSetName( nEndProfileId, WIN_PRF_END)
end
return nProfileLayerId
end
----------------------------------------------------------------------------------
------------------------------ CALCOLO OUTLINE ---------------------------------
----------------------------------------------------------------------------------
------------------------------ NULL ------------------------------
---------------------------------------------------------------------
local function GetBorderRegions( nSplitId, nCompo, nAreaId)
-- taglio il bordo in due in corrispondenza dello split
local nCrv1 = EgtCopyGlob( nCompo, nAreaId)
local nCrv2 = EgtCopyGlob( nCompo, nAreaId)
local dPar1 = EgtCurveParamAtPoint( nCompo, EgtSP( nSplitId), 100 * GEO.EPS_SMALL)
local dPar2 = EgtCurveParamAtPoint( nCompo, EgtEP( nSplitId), 100 * GEO.EPS_SMALL)
EgtTrimCurveStartEndAtParam( nCrv1, dPar2, dPar1)
EgtTrimCurveStartEndAtParam( nCrv2, dPar1, dPar2)
-- aggiungo la curva di split al bordo per chiuderlo orientandola opportunamente
local nSplitId1 = EgtCopyGlob( nSplitId, nAreaId)
EgtAddCurveCompoCurve( nCrv1, nSplitId1)
local _, dParE1 = EgtCurveDomain( nCrv1)
EgtCurveCompoSetTempProp( nCrv1, dParE1 - 1, nSplitId)
local nSplitId2 = EgtCopyGlob( nSplitId, nAreaId)
EgtInvertCurve( nSplitId2)
EgtAddCurveCompoCurve( nCrv2, nSplitId2)
local _, dParE2 = EgtCurveDomain( nCrv2)
EgtCurveCompoSetTempProp( nCrv2, dParE2 - 1, - nSplitId)
return nCrv1, nCrv2
end
---------------------------------------------------------------------
local function AssignSplitName( nCrvId)
-- sceglie il nome della curva di split in base al suo orientamento
-- TODO forme non lineari o con orientamento diverso dagli assi principali
local vtS = EgtSV( nCrvId)
if AreSameVectorApprox( vtS, X_AX()) then
EgtSetName( nCrvId, WIN_BOTTOM)
elseif AreOppositeVectorApprox( vtS, X_AX()) then
EgtSetName( nCrvId, WIN_TOP)
elseif AreSameVectorApprox( vtS, Y_AX()) then
EgtSetName( nCrvId, WIN_RIGHT)
elseif AreOppositeVectorApprox( vtS, Y_AX()) then
EgtSetName( nCrvId, WIN_LEFT)
end
end
---------------------------------------------------------------------
local function CalculateNullOutline( nCompoOutline, vSplitIds, vChildAreas)
local nGrpTmp = EgtGroup( GDB_ID.ROOT)
-- calcolo i bordi delle sottoregioni null tagliando il bordo complessivo dell'area di split con gli split
local vBorders = {}
local nCompoRef = nCompoOutline
for i = 1, #vSplitIds do
-- calcolo i bordi delle due regioni definite dallo split
local nCrv1, nCrv2 = GetBorderRegions( vSplitIds[i], nCompoRef, nGrpTmp)
table.insert( vBorders, nCrv1)
-- il secondo bordo è quello da suddividere con lo split successivo ( se esiste)
nCompoRef = nCrv2
if i == #vSplitIds then
table.insert( vBorders, nCrv2)
end
end
-- creo gli outline delle sottoaree a partire dai bordi calcolati
for i = 1, #vChildAreas do
if vBorders[i] then
local nOutlineLayerId = EgtGroup( vChildAreas[i])
EgtSetName( nOutlineLayerId, WIN_OUTLINE)
EgtSetStatus( nOutlineLayerId, GDB_ST.OFF)
EgtRelocateGlob( vBorders[i], nOutlineLayerId)
-- dalla curva di bordo ricavo le sottocurve che compongono l'outline
local vSouCrvs = EgtCurveCompoGetTempProp( vBorders[i])
local nFirst, nCnt = EgtExplodeCurveCompo( vBorders[i])
-- assegno nome e info a tutte le curve a partire dalla curva da cui derviano ( salvata nella temp prop della curva)
for j = 0, nCnt - 1 do
local nCrvId = nFirst + j
EgtSetInfo( nCrvId, WIN_SOU_OUTLINE, vSouCrvs[j+1])
if vSouCrvs[j+1] < 0 then
AddInfo( abs( vSouCrvs[j+1]), WIN_CHILD_VIRTUAL_OUTLINE, -nCrvId)
else
AddInfo( vSouCrvs[j+1], WIN_CHILD_VIRTUAL_OUTLINE, nCrvId)
end
-- assengo il nome : se deriva da split lo scelgo in base all'orientamento, se deriva da outline lo copio
if EgtGetName( abs( vSouCrvs[j+1])) == WIN_SPLIT then
AssignSplitName( nCrvId)
else
EgtSetName( nCrvId, EgtGetName( abs( vSouCrvs[j+1])))
end
end
-- riordino le curve per avere la bottom come prima
for j = 0, nCnt - 1 do
if EgtGetName( nFirst + j) ~= WIN_BOTTOM then
EgtRelocate( nFirst + j, nOutlineLayerId)
else
break
end
end
else
-- se non c'è bordo l'area non è valida e va eliminata
EgtErase( vChildAreas[i])
end
end
EgtErase( nGrpTmp)
end
------------------------------ SPLIT ------------------------------
---------------------------------------------------------------------
-- funzione che adatta la curva di split al bordo
local function TrimSplitWithOutline( nSplitId, nOutlineCompo, vOutlineIds)
-- estendo agli estremi ( TO DO : gestire caso di split non lineare)
EgtExtendCurveStartByLen( nSplitId, 1000)
EgtExtendCurveEndByLen( nSplitId, 1000)
local ptS = EgtIP( nSplitId, nOutlineCompo, EgtSP( nSplitId))
local ptE = EgtIP( nSplitId, nOutlineCompo, EgtEP( nSplitId))
-- se non trovo punti di intersezione lo split è fuori dall'outline e quindi va eliminato
if not ptS and not ptE then
return false
end
local dParS = EgtCurveParamAtPoint( nSplitId, ptS)
local dParE = EgtCurveParamAtPoint( nSplitId, ptE)
EgtTrimCurveStartEndAtParam( nSplitId, dParS, dParE)
-- recupero le curve con cui avviene l'intersezione e le salvo come info
local dParCrvS = EgtCurveParamAtPoint( nOutlineCompo, ptS)
local nCrv = vOutlineIds[ floor( dParCrvS) + 1]
EgtSetInfo( nSplitId, WIN_SPLIT_STARTINTERS, nCrv)
local dParCrvE = EgtCurveParamAtPoint( nOutlineCompo, ptE)
nCrv = vOutlineIds[ floor( dParCrvE) + 1]
EgtSetInfo( nSplitId, WIN_SPLIT_ENDINTERS, nCrv)
return true
end
---------------------------------------------------------------------
local function CalcSplitDimensions( nAreaId, dDim)
local vMeasureTypes = EgtGetInfo( nAreaId, WIN_MEASURE_TYPE, 'vi')
local vMeasureValues = EgtGetInfo( nAreaId, WIN_MEASURE_VALUE, 'vd')
local vDimensions = {}
-- calcolo le dimensioni di tutti gli split assoluti e percentuali e calcolo i valori di riferimento per eventuali split proporzionali
local nPropTot = 0
local dPropDim = dDim
local bProportional = false
for i = 1, #vMeasureTypes do
if vMeasureTypes[i] == WIN_MEASURE.ABSOLUTE then
vDimensions[i] = vMeasureValues[i]
dPropDim = dPropDim - vDimensions[i]
elseif vMeasureTypes[i] == WIN_MEASURE.PERCENTAGE then
vDimensions[i] = dDim * vMeasureValues[i] / 100
dPropDim = dPropDim - vDimensions[i]
elseif vMeasureTypes[i] == WIN_MEASURE.PROPORTIONAL then
nPropTot = nPropTot + vMeasureValues[i]
bProportional = true
end
end
-- calcolo le dimensioni degli split proporzionali
if bProportional then
if dPropDim < GEO.EPS_SMALL then
return {}
end
for i = 1, #vMeasureTypes do
if vMeasureTypes[i] == WIN_MEASURE.PROPORTIONAL then
vDimensions[i] = dPropDim * vMeasureValues[i] / nPropTot
end
end
end
return vDimensions
end
---------------------------------------------------------------------
local function GetSplitAreaBorderCurves( nSplitDir, nOutlineLayerId)
local vCrvs = {}
-- se split verticale servono le curve di sinistra e di destra, che sono rispettivamente quella prima e quella dopo il bottom
-- non ricerco la left/right per casi dove non sono definite ( e.g. triangolo)
if nSplitDir == WIN_SPLITORIENTATION.VERTICAL then
vCrvs[1] = EgtGetLastInGroup( nOutlineLayerId)
vCrvs[2] = EgtGetNext( EgtGetFirstNameInGroup( nOutlineLayerId, WIN_BOTTOM))
-- se split orizzontale servono le curve inferiore e superiore
elseif nSplitDir == WIN_SPLITORIENTATION.HORIZONTAL then
vCrvs[1] = EgtGetFirstNameInGroup( nOutlineLayerId, WIN_BOTTOM)
vCrvs[2] = EgtGetFirstNameInGroup( nOutlineLayerId, WIN_TOP)
end
return vCrvs
end
---------------------------------------------------------------------
local function CalcStandardSplitContributions( nSplitDir, nOutlineLayerId, vSplitIds)
-- nel caso di split standard la dimensione è sempre luce
local tPartsDim = {}
-- 1) contributo dei pezzi che delimitano la regione degli split
local vDim = {}
local vCrvs = GetSplitAreaBorderCurves( nSplitDir, nOutlineLayerId)
for i = 1, 2 do
-- recupero il pezzo contro cui poggia
local nSouId = GetNonVirtualOutline( vCrvs[i])
-- recupero il profilo ( eventualmente di bottomrail)
local nProfileId = GetOutlineTheoricProfileId( abs( nSouId), true)
local dRealDim = EgtGetInfo( abs( nSouId), WIN_PART_DIM, 'd')
-- se bottomrail calcolo scostamento
local dRailOffs = 0
if EgtGetName( nProfileId) == WIN_FILL_RAIL then
local nBottomRail = EgtGetInfo( abs( nSouId), WIN_BOTTOMRAIL, 'i')
dRailOffs = CalcRailOffset( abs( nSouId), nProfileId, nBottomRail)
local vBottomRailDims = EgtGetInfo( abs( nSouId), WIN_BOTTOMRAIL .. WIN_PART_DIM, 'vd')
dRealDim = vBottomRailDims[#vBottomRailDims]
end
local b3Profile = GetProfileLocalBox( nProfileId)
-- calcolo il contributo
if nSouId < 0 then
vDim[i] = b3Profile:getMax():getX()
else
vDim[i] = abs( b3Profile:getMin():getX())
end
vDim[i] = vDim[i] * dRealDim / b3Profile:getDimX() + dRailOffs
end
tPartsDim[1] = { 0, vDim[1]}
-- 2) contributo degli split
for i = 1, #vSplitIds do
local nProfileId = GetOutlineTheoricProfileId( vSplitIds[i])
local b3Profile = GetProfileLocalBox( nProfileId)
local dRealDim = EgtGetInfo( vSplitIds[i], WIN_PART_DIM, 'd')
local vCurrSplitDim = {}
vCurrSplitDim[1] = abs( b3Profile:getMin():getX()) * dRealDim / b3Profile:getDimX()
vCurrSplitDim[2] = b3Profile:getMax():getX() * dRealDim / b3Profile:getDimX()
table.insert( tPartsDim, vCurrSplitDim)
end
table.insert( tPartsDim, { vDim[2], 0})
return tPartsDim
end
---------------------------------------------------------------------
local function CalcFrenchSplitContributions( nOutlineLayerId, nBaseOutlineLayerId, vSplitIds, bDaylight)
-- nel caso di french split ( gruppo di ante) la dimensione può essere di tipo luce o esterno anta
local tPartsDim = {}
local nProfileGrp = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE)
local nSashProfileGrp = EgtGetFirstNameInGroup( nProfileGrp, WIN_SASH)
-- 1) contributo dei pezzi che delimitano la regione degli split
local vDim = {}
local vCrvs = GetSplitAreaBorderCurves( WIN_SPLITORIENTATION.VERTICAL, nOutlineLayerId)
local vBaseCrvs = GetSplitAreaBorderCurves( WIN_SPLITORIENTATION.VERTICAL, nBaseOutlineLayerId)
for i = 1, 2 do
-- a) contributo del telaio
local nSouId = GetNonVirtualOutline( vCrvs[i])
local nProfileId = GetOutlineTheoricProfileId( abs( nSouId))
local b3Profile = GetProfileLocalBox( nProfileId)
if nSouId < 0 then
vDim[i] = abs( b3Profile:getMax():getX())
else
vDim[i] = abs( b3Profile:getMin():getX())
end
local dRealDim = EgtGetInfo( abs( nSouId), WIN_PART_DIM, 'd')
local dSashOverlap = EgtGetInfo( nProfileId, WIN_SASH_TOP_OVERLAP, 'd')
vDim[i] = vDim[i] * dRealDim / b3Profile:getDimX() - dSashOverlap
-- b) se luce devo considerare anche il contributo dell'anta
if bDaylight then
-- anta non è ancora calcolata quindi devo calcolare la sua dimensione ricavandola dal base outline
local nSashBaseOutline = EgtGetInfo( vBaseCrvs[i], WIN_CHILD, 'i')
local vDimensions = EgtGetInfo( EgtGetParent( EgtGetParent( nSashBaseOutline)), WIN_PART_DIM, 'vd')
local dDim
if not vDimensions then
local nFrameId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*')
local bSlide = EgtGetInfo( nFrameId, WIN_SLIDE_WINDOW, 'b')
local sProfileName = WIN_FRAME_TOP
if bSlide then
sProfileName = WIN_SLIDE_MOVABLE_SIDE -- la dimensione standard dovrebbe essere la stessa indipendentemente dalla tipologia di anta slide
end
local nProfileId = EgtGetFirstNameInGroup( nSashProfileGrp, sProfileName)
dDim = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
else
local nIdx = EgtIf( i == 1, #vDimensions, 2)
dDim = vDimensions[nIdx]
end
vDim[i] = vDim[i] + dDim
end
end
tPartsDim[1] = { 0, vDim[1]}
-- 2) contributo degli split
for i = 1, #vSplitIds do
local vCurrSplitDim = { 0, 0}
-- ricavo dai base outlines le ante che poggeranno sullo split
local vSashChildren = EgtGetInfo( vSplitIds[i], WIN_CHILD, 'vi')
local vSashTypes = {}
vSashTypes[1] = EgtGetInfo( EgtGetParent( EgtGetParent( abs( vSashChildren[1]))), WIN_SASHTYPE, 'i')
vSashTypes[2] = EgtGetInfo( EgtGetParent( EgtGetParent( abs( vSashChildren[2]))), WIN_SASHTYPE, 'i')
for j = 1, 2 do
-- recupero il profilo teorico
local sSashProfile
local nOther = EgtIf( j == 1, 2, 1)
if vSashTypes[j] == WIN_SASHTYPES.ACTIVE then
sSashProfile = WIN_SASH_ACTIVE
elseif vSashTypes[j] == WIN_SASHTYPES.INACTIVE then
sSashProfile = WIN_SASH_INACTIVE
elseif vSashTypes[j] == WIN_SASHTYPES.ACTIVE_OUT or vSashTypes[j] == WIN_SASHTYPES.INACTIVE_OUT then
sSashProfile = WIN_FRENCH_OUT
elseif vSashTypes[j] == WIN_SASHTYPES.ACTIVE_IN then
if vSashTypes[nOther] == WIN_SASHTYPES.ACTIVE_OUT then
sSashProfile = WIN_FRENCH_IN
else
sSashProfile = WIN_SASH_ACTIVE
end
elseif vSashTypes[j] == WIN_SASHTYPES.INACTIVE_IN then
if vSashTypes[nOther] == WIN_SASHTYPES.INACTIVE_OUT then
sSashProfile = WIN_FRENCH_IN
else -- adiacente è active
sSashProfile = WIN_SASH_INACTIVE
end
elseif vSashTypes[j] == WIN_SASHTYPES.SLIDE_MOVABLE then
if vSashTypes[nOther] == WIN_SASHTYPES.SLIDE_MOVABLE then
sSashProfile = WIN_SLIDE_ACTIVE_IN
else
sSashProfile = WIN_SLIDE_ACTIVE
end
elseif vSashTypes[j] == WIN_SASHTYPES.SLIDE_FIXED then
sSashProfile = WIN_SLIDE_INACTIVE
elseif vSashTypes[j] == WIN_SASHTYPES.SLIDE_MOVABLE_BACK then
sSashProfile = WIN_SLIDE_INACTIVE
end
local nProfileId = EgtGetFirstNameInGroup( nSashProfileGrp, sSashProfile)
local b3Profile = GetProfileLocalBox( nProfileId)
if bDaylight then
local dDim
local vDimensions = EgtGetInfo( EgtGetParent( EgtGetParent( abs( vSashChildren[j]))), WIN_PART_DIM, 'vd')
if not vDimensions then
dDim = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
else
-- il primo figlio è quello di sx, il secondo figlio è quello di dx
local nIdx = EgtIf( j == 1, 2, #vDimensions)
dDim = vDimensions[nIdx]
end
vCurrSplitDim[j] = dDim - b3Profile:getMax():getX()
else
vCurrSplitDim[j] = - b3Profile:getMax():getX()
end
end
table.insert( tPartsDim, vCurrSplitDim)
end
table.insert( tPartsDim, { vDim[2], 0})
return tPartsDim
end
---------------------------------------------------------------------
-- funzione che calcola gli offset da applicare ai base splits per posizionarli correttamente
local function CalcSplitPositionOffsets( nAreaId, nAreaInfoId, vSplitIds, nSplitType)
local nSplitDir = EgtGetInfo( nAreaInfoId, WIN_SPLIT_DIR, 'i')
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local nBaseOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_AREAOUTLINE)
-- calcolo i contributi dei vari pezzi presenti
local tPartsDim
if nSplitType == WIN_SPLITTYPES.FRENCH then
local bDaylight = EgtGetInfo( nAreaInfoId, WIN_DAYLIGHT_MEASURE, 'b') or false
tPartsDim = CalcFrenchSplitContributions( nOutlineLayerId, nBaseOutlineLayerId, vSplitIds, bDaylight)
else
tPartsDim = CalcStandardSplitContributions( nSplitDir, nOutlineLayerId, vSplitIds)
end
-- ricavo la vera dimensione disponibile
local b3Box = EgtGetBBoxGlob( nOutlineLayerId, GDB_BB.STANDARD)
local dRealDim = EgtIf( nSplitDir == WIN_SPLITORIENTATION.VERTICAL, b3Box:getDimX(), b3Box:getDimY())
for i = 1, #tPartsDim do
dRealDim = dRealDim - tPartsDim[i][1] - tPartsDim[i][2]
end
-- calcolo le dimensioni assolute di tutte le sottoaree
local vSplitDimensions = CalcSplitDimensions( nAreaInfoId, dRealDim)
-- le posizioni salvate negli split sono calcolate rispetto al box del base outline, le posizioni appena calcolate sono rispetto al box dell'outline
-- quindi calcolo la correzione da applicare
local b3BoxBase = EgtGetBBoxGlob( nBaseOutlineLayerId, GDB_BB.STANDARD)
local dCorrection = EgtIf( nSplitDir == WIN_SPLITORIENTATION.VERTICAL, ( b3Box:getMin():getX() - b3BoxBase:getMin():getX()), ( b3Box:getMin():getY() - b3BoxBase:getMin():getY()))
tPartsDim[1][2] = tPartsDim[1][2] + dCorrection
-- calcolo gli offset
local vOffs = {}
local dPrevPos = 0
for i = 1, #vSplitIds do
local dNewPos = dPrevPos + tPartsDim[i][2] + vSplitDimensions[i] + tPartsDim[i+1][1]
local dOldPos = EgtGetInfo( vSplitIds[i], WIN_SPLIT_POSITION, 'd')
vOffs[i] = dNewPos - dOldPos
dPrevPos = dNewPos
end
return vOffs
end
---------------------------------------------------------------------
local function CalculateSplitOutline( nAreaId, vSplitIds)
-- recupero l'outline e creo composita del bordo
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlineIds = EgtGetAllInGroup( nOutlineLayerId)
local nOutlineCompo = EgtCurveCompo( nAreaId, vOutlineIds, false)
for i = 1, #vOutlineIds do
EgtCurveCompoSetTempProp( nOutlineCompo, i - 1, vOutlineIds[i])
end
local nSplitType = EgtGetInfo( vSplitIds[1], WIN_SPLITTYPE, 'i')
-- assegno le dimensioni
if nSplitType ~= WIN_SPLITTYPES.FRENCH then
local vSplitDim = EgtGetInfo( nAreaId, WIN_PART_DIM, 'vd') or {}
for i = 1, #vSplitIds do
if not vSplitDim[i] then
-- se dimensione non è impostata recupero quella standard del profilo
local nProfileId = GetOutlineTheoricProfileId( vSplitIds[i])
vSplitDim[i] = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
end
EgtSetInfo( vSplitIds[i], WIN_PART_DIM, vSplitDim[i])
end
end
-- posiziono correttamente gli split e li taglio con l'outline
local vOffs = CalcSplitPositionOffsets( nAreaId, nAreaId, vSplitIds, nSplitType)
for i = 1, #vSplitIds do
EgtOffsetCurve( vSplitIds[i], vOffs[i])
TrimSplitWithOutline( vSplitIds[i], nOutlineCompo, vOutlineIds)
end
-- creo l'outline delle aree figlie di tipo null
if nSplitType ~= WIN_SPLITTYPES.FRENCH then
local vChildAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
CalculateNullOutline( nOutlineCompo, vSplitIds, vChildAreas)
end
EgtErase( nOutlineCompo)
end
---------------------------------------------------------------------
local function CalculateGridSplitOutline( nAreaId, vSplitIds)
local vAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
local vVirtualAreas = EgtGetNameInGroup( nAreaId, WIN_VIRTUAL_AREA)
-- raggruppo gli split e le aree per ordine
local tabGrid = {}
for i = 1, #vSplitIds do
local nOrder = EgtGetInfo( vSplitIds[i], WIN_GRIDSPLIT_ORDER, 'i')
if tabGrid[nOrder] then
table.insert( tabGrid[nOrder], vSplitIds[i])
else
tabGrid[nOrder] = { vSplitIds[i]}
end
end
local tabAreas = {}
for i = 1, #vAreas do
local nOrder = EgtGetInfo( vAreas[i], WIN_GRIDSPLIT_ORDER, 'i')
if tabAreas[nOrder] then
table.insert( tabAreas[nOrder], vAreas[i])
else
tabAreas[nOrder] = { vAreas[i]}
end
end
-- assegno le dimensioni
local vDimMain = EgtGetInfo( nAreaId, WIN_PART_DIM, 'vd') or {}
local vDimOther = EgtGetInfo( vVirtualAreas[1], WIN_PART_DIM, 'vd') or {}
for i = 0, #tabGrid do
for j = 1, #tabGrid[i] do
local dDim = EgtIf( i == 0, vDimMain[j], vDimOther[j])
if not dDim then
-- se dimensione non è impostata recupero quella standard del profilo
local nProfileId = GetOutlineTheoricProfileId( tabGrid[i][j])
dDim = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
end
EgtSetInfo( tabGrid[i][j], WIN_PART_DIM, dDim)
end
end
-- calcolo gli offset
local vOffsMain = CalcSplitPositionOffsets( nAreaId, nAreaId, tabGrid[0])
local vOffsSecondary = CalcSplitPositionOffsets( nAreaId, vVirtualAreas[1], tabGrid[1])
for i = 0, #tabGrid do
-- recupero l'area di riferimento che racchiude gli split ( i.e. l'area dello split per split principali, area virtuale i-esima per split secondari) e ne costruisco il bordo
local nRefAreaId = EgtIf( i == 0, nAreaId, vVirtualAreas[i])
local nOutlineLayerId = EgtGetFirstNameInGroup( nRefAreaId, WIN_OUTLINE)
local vOutlineIds = EgtGetAllInGroup( nOutlineLayerId)
local nOutlineCompo = EgtCurveCompo( nAreaId, vOutlineIds, false)
for i = 1, #vOutlineIds do
EgtCurveCompoSetTempProp( nOutlineCompo, i - 1, vOutlineIds[i])
end
-- posiziono correttamente e taglio con outline
local vOffs = EgtIf( i == 0, vOffsMain, vOffsSecondary)
for j = 1, #tabGrid[i] do
EgtOffsetCurve( tabGrid[i][j], vOffs[j])
if not TrimSplitWithOutline( tabGrid[i][j], nOutlineCompo, vOutlineIds) then
-- se split fuoriesce dalla sottoarea lo elimino
EgtErase( tabGrid[i][j])
tabGrid[i][j] = nil
end
end
-- creo gli outline delle aree figlie ( i.e. aree virtuali per split principale, sottoaree di ordine i-esimo per split secondari di ordine i-esimo)
CalculateNullOutline( nOutlineCompo, tabGrid[i], EgtIf( i == 0, vVirtualAreas, tabAreas[i]))
EgtErase( nOutlineCompo)
end
end
------------------------------ SASH -------------------------------
---------------------------------------------------------------------
-- funzione che disegna l'apertura dell'anta
local function DrawOpening( nAreaId)
local nOpeningType = EgtGetInfo( nAreaId, WIN_OPENING_TYPE, 'i')
if nOpeningType == WIN_OPENING_TYPES.NULL then
return
end
-- creo gruppo per aperture
local nOpeningLayId = EgtGroup( nAreaId)
EgtSetName( nOpeningLayId, WIN_SASH_OPENING)
-- verifico se anta ricevente per impostare tratteggio
local nFactor = 7
local nPattern = 0xAAAA
local nType = EgtGetInfo( nAreaId, WIN_SASHTYPE, 'i')
local bStippled = ( nType == WIN_SASHTYPES.INACTIVE or nType == WIN_SASHTYPES.INACTIVE_IN or nType == WIN_SASHTYPES.INACTIVE_OUT)
-- calcolo la curva di riferimento per il disegno dell'apertura
local nOutlineLayId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlines = EgtGetAllInGroup( nOutlineLayId)
-- TODO gestire caso di triangolo
if #vOutlines == 3 then
return
end
local vCrvs = {}
for i = 1, #vOutlines do
local nCrv = EgtCopyGlob( vOutlines[i], nOpeningLayId)
table.insert( vCrvs, nCrv)
local nProfileId = GetOutlineTheoricProfileId( vOutlines[i], true)
local dRealDim = EgtGetInfo( vOutlines[i], WIN_PART_DIM, 'd')
local dRailOffs = 0
if EgtGetName( nProfileId) == WIN_FILL_RAIL then
local nBottomRail = EgtGetInfo( vOutlines[i], WIN_BOTTOMRAIL, 'i')
dRailOffs = CalcRailOffset( vOutlines[i], nProfileId, nBottomRail)
local vBottomRailDims = EgtGetInfo( vOutlines[i], WIN_BOTTOMRAIL .. WIN_PART_DIM, 'vd')
dRealDim = vBottomRailDims[#vBottomRailDims]
end
local b3Profile = GetProfileLocalBox( nProfileId)
local dOffs = b3Profile:getMin():getX() * dRealDim / b3Profile:getDimX() - dRailOffs
EgtOffsetCurve( nCrv, dOffs)
end
vCrvs = TrimOrderedCurves( vCrvs, true)
local nGuideId = EgtCurveCompo( nOpeningLayId, vCrvs)
local _, dParE = EgtCurveDomain( nGuideId)
-- ribalta
if nOpeningType == WIN_OPENING_TYPES.TILTONLY_TOP or nOpeningType == WIN_OPENING_TYPES.TILTTURN_LEFT or nOpeningType == WIN_OPENING_TYPES.TILTTURN_RIGHT then
-- ricavo il punto sul top
local ptMid = EgtUP( nGuideId, 2.5)
if not EgtCurveIsARectangle( nGuideId) then
-- per maggiore simmetria ricavo il punto sul top in corrispondenza del punto medio del bottom
local ptTest = EgtUP( nGuideId, 0.5)
local nLineTest = EgtLinePVL( nOpeningLayId, ptTest + Y_AX(), Y_AX(), 10000)
ptMid = EgtIP( nGuideId, nLineTest, ORIG())
EgtErase( nLineTest)
end
EgtCurveCompoFromPoints( nOpeningLayId, { EgtSP( nGuideId), ptMid, EgtUP( nGuideId, 1)})
elseif nOpeningType == WIN_OPENING_TYPES.TILTONLY_BOTTOM then
-- ricavo il punto sul bottom
local ptMid = EgtUP( nGuideId, 0.5)
EgtCurveCompoFromPoints( nOpeningLayId, { EgtUP( nGuideId, 2), ptMid, EgtUP( nGuideId, dParE - 1)})
end
-- altre tipologie
if nOpeningType == WIN_OPENING_TYPES.TILTTURN_LEFT or nOpeningType == WIN_OPENING_TYPES.TURNONLY_LEFT then
-- battente sx
local dLenRight = EgtCurveCompoLength( nGuideId, 1)
local dLenLeft = EgtCurveCompoLength( nGuideId, dParE - 1)
local dParMid = 1.5
-- se lato sinistro è il più corto, prendo sul destro il corrispondente del suo punto medio
if dLenLeft < dLenRight - GEO.EPS_SMALL then
dParMid = EgtCurveParamAtLength( nGuideId, EgtCurveCompoLength( nGuideId, 0) + dLenLeft * 0.5)
end
local nCrv = EgtCurveCompoFromPoints( nOpeningLayId, { EgtSP( nGuideId), EgtUP( nGuideId, dParMid), EgtUP( nGuideId, dParE - 1)})
-- tratteggio
if bStippled then
EgtSetStipple( nCrv, nFactor, nPattern)
end
elseif nOpeningType == WIN_OPENING_TYPES.TILTTURN_RIGHT or nOpeningType == WIN_OPENING_TYPES.TURNONLY_RIGHT then
-- battente dx
local dLenRight = EgtCurveCompoLength( nGuideId, 1)
local dLenLeft = EgtCurveCompoLength( nGuideId, dParE - 1)
local dParMid = dParE - 0.5
-- se lato destro è il più corto, prendo sul sinistro il corrispondente del suo punto medio
if dLenRight < dLenLeft - GEO.EPS_SMALL then
dParMid = EgtCurveParamAtLength( nGuideId, EgtCurveLength( nGuideId) - dLenRight * 0.5)
end
local nCrv = EgtCurveCompoFromPoints( nOpeningLayId, { EgtUP( nGuideId, 1), EgtUP( nGuideId, dParMid), EgtUP( nGuideId, 2)})
-- tratteggio
if bStippled then
EgtSetStipple( nCrv, nFactor, nPattern)
end
elseif nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_LEFT or nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_RIGHT or
nOpeningType == WIN_OPENING_TYPES.LIFTSLIDE_LEFT or nOpeningType == WIN_OPENING_TYPES.LIFTSLIDE_RIGHT then
-- scorrevole e alzante scorrevole ( solo forma rettangolare)
local bRight = ( nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_RIGHT or nOpeningType == WIN_OPENING_TYPES.LIFTSLIDE_RIGHT)
local dLen0 = EgtCurveCompoLength( nGuideId, 0)
local dLen1 = EgtCurveCompoLength( nGuideId, 1)
local dCoeff = 0.15
local ptS = EgtUP( nGuideId, 1.5) - dCoeff * dLen0 * X_AX()
local ptE = EgtUP( nGuideId, dParE - 0.5) + dCoeff * dLen0 * X_AX()
if bRight then
ptS, ptE = ptE, ptS
end
local nCompo = EgtCurveCompoFromPoints( nOpeningLayId, { ptS, ptE})
if nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_LEFT or nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_RIGHT then
EgtAddCurveCompoLine( nCompo, ptS - dCoeff * dLen1 * Y_AX(), false)
end
local dAng = EgtIf( bRight, 135, 45)
EgtLinePDL( nOpeningLayId, ptE, dAng, dCoeff * dLen0)
EgtLinePDL( nOpeningLayId, ptE, - dAng, dCoeff * dLen0)
elseif nOpeningType == WIN_OPENING_TYPES.FIXED then
-- nessun disegno
elseif nOpeningType == WIN_OPENING_TYPES.PIVOT then
-- bilico rettangolare
local nCompo = EgtCurveCompoFromPoints( nOpeningLayId, { EgtUP( nGuideId, 0.5), EgtUP( nGuideId, 1.5), EgtUP( nGuideId, 2.5), EgtUP( nGuideId, 3.5)})
EgtCloseCurveCompo( nCompo)
-- TODO oblò
end
EgtErase( nGuideId)
end
---------------------------------------------------------------------
-- funzione che identifica la forma dell'anta/gruppo di ante
local function IdentifySashShape( nAreaId, nOutlineLayerId)
local vOutlines = EgtGetAllInGroup( nOutlineLayerId)
local nCompoId = EgtCurveCompo( nOutlineLayerId, vOutlines, false)
-- verifico se trapezio
local bTrap, ptOrig, vtB1, vtE1, vtB2 = EgtCurveIsATrapezoid( nCompoId)
if bTrap then
-- verifico se rettangolo controllando se lati sono paralleli
local vtE2 = vtB1 + vtE1 - vtB2
if AreSameOrOppositeVectorApprox( vtE1, vtE2) then
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.RECT)
else
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.TRAP)
end
else
-- verifico se cerchio
local bCircle = EgtCurveIsACircle( nCompoId)
if bCircle then
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.CIRCLE)
-- verifico se forma con arco
elseif #vOutlines == 4 and EgtGetType( vOutlines[3]) == GDB_TY.CRV_ARC then
local dAngCenter = EgtArcAngCenter( vOutlines[3])
if abs( dAngCenter - 180) < GEO.EPS_SMALL then
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.ROUND_ARC)
else
if abs( EgtCurveLength( vOutlines[2]) - EgtCurveLength( vOutlines[4])) < GEO.EPS_SMALL then
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.SEGMENTAL_ARC)
else
-- verifico se metà di arco a tutto sesto o ribassato
if AreSameVectorApprox( EgtEV( vOutlines[2]), EgtSV( vOutlines[3])) or AreSameVectorApprox( EgtEV( vOutlines[3]), EgtSV( vOutlines[4])) then
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.SEMI_ROUND_ARC)
else
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.SEMI_SEGMENTAL_ARC)
end
end
end
else
EgtSetInfo( nAreaId, WIN_SASH_SHAPE, WIN_SASH_SHAPES.GENERIC)
end
end
EgtErase( nCompoId)
end
---------------------------------------------------------------------
local function CalculateSashOutline( nAreaId, nAreaLayerId, nOutlineLayerId)
-- calcolo l'outline corrispondente al telaio
local nFrameArea = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*')
local nFrameOutlineLayer = EgtGetFirstNameInGroup( nFrameArea, WIN_OUTLINE)
local vFrameOutlines = EgtGetAllInGroup( nFrameOutlineLayer)
local vFrameOffs = {}
-- calcolo gli offset da applicare ad ogni curva
for i = 1, #vFrameOutlines do
-- recupero il suo profilo per calcolare l'offset
local nProfileId = GetOutlineTheoricProfileId( vFrameOutlines[i])
local sKey = EgtIf( EgtGetName( vFrameOutlines[i]) == WIN_BOTTOM, WIN_SASH_BOTTOM_OVERLAP, WIN_SASH_TOP_OVERLAP)
local dOverlap = EgtGetInfo( nProfileId, sKey, 'd')
if dOverlap then
local b3Profile = GetProfileLocalBox( nProfileId)
local dRealDim = EgtGetInfo( vFrameOutlines[i], WIN_PART_DIM, 'd')
vFrameOffs[i] = b3Profile:getMin():getX() * dRealDim / b3Profile:getDimX() + dOverlap
end
end
-- costruisco l'outline
for i = 1, #vFrameOutlines do
local nOutlineId = EgtCopyGlob( vFrameOutlines[i], nOutlineLayerId)
EgtSetInfo( nOutlineId, WIN_SOU_OUTLINE, vFrameOutlines[i])
-- rimuovo info che non voglio trasferire sull'anta
EgtRemoveInfo( nOutlineId, WIN_PRF_CHANGE)
EgtRemoveInfo( nOutlineId, WIN_THRESHOLD)
EgtRemoveInfo( nOutlineId, WIN_PART_DIM)
-- applico l'offset
if vFrameOffs[i] then
EgtOffsetCurve( nOutlineId, vFrameOffs[i])
else
-- se non ha offset definito è un pezzo che verrà tagliato da uno split ma, affinchè la forma del telaio sia coerente, se è in tangenza con uno dei suoi vicini
-- devo applicare lo stesso offset
local nPrevIdx = EgtIf( i == 1, #vFrameOutlines, i-1)
local nNextIdx = EgtIf( i == #vFrameOutlines, 1, i+1)
if AreSameVectorApprox( EgtSV( vFrameOutlines[i]), EgtEV( vFrameOutlines[nPrevIdx])) then
while not vFrameOffs[nPrevIdx] do
nPrevIdx = EgtIf( nPrevIdx == 1, #vFrameOutlines, nPrevIdx-1)
end
EgtOffsetCurve( nOutlineId, vFrameOffs[nPrevIdx])
vFrameOffs[i] = vFrameOffs[nPrevIdx]
elseif AreSameVectorApprox( EgtEV( vFrameOutlines[i]), EgtSV( vFrameOutlines[nNextIdx])) then
while not vFrameOffs[nNextIdx] do
nNextIdx = EgtIf( nNextIdx == #vFrameOutlines, 1, nNextIdx+1)
end
EgtOffsetCurve( nOutlineId, vFrameOffs[nNextIdx])
vFrameOffs[i] = vFrameOffs[nNextIdx]
end
end
end
-- accorcio gli offset
local vCrvs = TrimOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), true)
-- 2) taglio con eventuali split
local vSplitIds = {}
local tabSplitCrvName = {} -- associa allo split il nome della curva di outline che da esso deriva
local nParentId = EgtGetParent( nAreaId)
while nParentId ~= nFrameArea do
local nParentType = EgtGetInfo( nParentId, WIN_AREATYPE, 'i')
if nParentType == WIN_AREATYPES.NULL then
local nNullOutlineLay = EgtGetFirstNameInGroup( nParentId, WIN_OUTLINE)
local vNullOutlines = EgtGetAllInGroup( nNullOutlineLay)
for i = 1, #vNullOutlines do
local nSou = EgtGetInfo( vNullOutlines[i], WIN_SOU_OUTLINE, 'i')
if EgtGetName( EgtGetParent( EgtGetParent( abs( nSou)))) == WIN_VIRTUAL_AREA then
nSou = EgtGetInfo( abs( nSou), WIN_SOU_OUTLINE, 'i')
end
if EgtGetName( abs( nSou)) == WIN_SPLIT then
table.insert( vSplitIds, nSou)
tabSplitCrvName[abs( nSou)] = EgtGetName( vNullOutlines[i])
end
end
elseif nParentType == WIN_AREATYPES.SPLIT and EgtGetInfo( nParentId, WIN_SPLITTYPE, 'i') == WIN_SPLITTYPES.FRENCH then
-- recupero l'indice dell'anta french dal suo nome
local sAreaName = EgtGetName( nAreaId)
local sAreaIdx = string.sub( sAreaName, string.len( WIN_AREA) + 1, string.len( WIN_AREA) + 1)
local nAreaIdx = tonumber( sAreaIdx)
local nSplitLayerId = EgtGetFirstNameInGroup( nParentId, WIN_SPLIT)
local vFrenchSplits = EgtGetAllInGroup( nSplitLayerId)
-- in base al numero di anta french recupero i french split che la definiscono con il corretto orientamento
if nAreaIdx > 1 then
table.insert( vSplitIds, - vFrenchSplits[nAreaIdx - 1])
end
if nAreaIdx < #vFrenchSplits + 1 then
table.insert( vSplitIds, vFrenchSplits[nAreaIdx])
end
end
nParentId = EgtGetParent( nParentId)
end
if #vSplitIds == 0 then
-- salvo associazioni sou/child sugli outlines
for i = 1, #vCrvs do
local nSouOutlineId = EgtGetInfo( vCrvs[i], WIN_SOU_OUTLINE, 'i')
AddInfo( nSouOutlineId, WIN_CHILD_OUTLINE, vCrvs[i])
end
else
-- li ordino per id crescente in modo da effettuare i tagli nell'ordine corretto
table.sort( vSplitIds, function ( a, b) return abs( a) < abs( b) end)
-- creo bordo complessivo dell'outline, salvando le info di SouOutline come temp prop della curva per non perderle
local vSouOutlines = {}
for i = 1, #vCrvs do
vSouOutlines[i] = EgtGetInfo( vCrvs[i], WIN_SOU_OUTLINE, 'i')
end
local nCompo = EgtCurveCompo( nOutlineLayerId, vCrvs)
for i = 0, #vCrvs - 1 do
EgtCurveCompoSetTempProp( nCompo, i, vSouOutlines[i+1])
end
-- taglio con split
for i = 1, #vSplitIds do
-- a) creo la curva di outline corrispondente allo split
local nOutlineId = EgtCopy( abs( vSplitIds[i]), nOutlineLayerId)
-- rimuovo info che non voglio trasferire
EgtRemoveInfo( nOutlineId, WIN_PRF_CHANGE)
-- verifico orientamento
if vSplitIds[i] < 0 then
EgtInvertCurve( nOutlineId)
end
-- calcolo gli offset
local nProfileId = GetOutlineTheoricProfileId( abs( vSplitIds[i]))
if nProfileId then
local b3Profile = GetProfileLocalBox( nProfileId)
local sKey = EgtIf( tabSplitCrvName[abs( vSplitIds[i])] == WIN_BOTTOM, WIN_SASH_BOTTOM_OVERLAP, WIN_SASH_TOP_OVERLAP)
local dOverlap = EgtGetInfo( nProfileId, sKey, 'd')
local dRealDim = EgtGetInfo( abs( vSplitIds[i]), WIN_PART_DIM, 'd')
local dFillPerpOffset = abs( b3Profile:getMin():getX()) * dRealDim / b3Profile:getDimX() - dOverlap
EgtOffsetCurve( nOutlineId, - dFillPerpOffset)
else
-- è french split quindi non ha offset
end
-- b) aggiorno la curva complessiva di outline con la curva appena calcolata
EgtExtendCurveStartByLen( nOutlineId, 1000)
EgtExtendCurveEndByLen( nOutlineId, 1000)
local ptS = EgtIP( nOutlineId, nCompo, EgtSP( nOutlineId))
local ptE = EgtIP( nOutlineId, nCompo, EgtEP( nOutlineId))
local dBorderParS = EgtCurveParamAtPoint( nCompo, ptS)
local dBorderParE = EgtCurveParamAtPoint( nCompo, ptE)
EgtTrimCurveStartEndAtParam( nCompo, dBorderParE, dBorderParS)
local dSplitParS = EgtCurveParamAtPoint( nOutlineId, ptS)
local dSplitParE = EgtCurveParamAtPoint( nOutlineId, ptE)
EgtTrimCurveStartEndAtParam( nOutlineId, dSplitParS, dSplitParE)
EgtAddCurveCompoCurve( nCompo, nOutlineId)
local _, dParEnd = EgtCurveDomain( nCompo)
EgtCurveCompoSetTempProp( nCompo, dParEnd - 1, vSplitIds[i])
end
-- spezzo la curva di outline nelle sue sottocurve e riassegno le info
local vTempProps = EgtCurveCompoGetTempProp( nCompo)
local nCrv, nCnt = EgtExplodeCurveCompo( nCompo)
for i = 0, nCnt - 1 do
local nOutlineId = nCrv + i
-- assegno le info sou/child
EgtSetInfo( nOutlineId, WIN_SOU_OUTLINE, vTempProps[i+1])
if vTempProps[i+1] > 0 then
AddInfo( vTempProps[i+1], WIN_CHILD_OUTLINE, nOutlineId)
else
AddInfo( abs( vTempProps[i+1]), WIN_CHILD_OUTLINE, - nOutlineId)
end
-- sistemo il nome
if EgtGetName( abs( vTempProps[i+1])) == WIN_SPLIT then
-- se deriva da split il nome è salvato nella tabella, se non lo fosse si tratta di un french split e lo calcolo al momento
local sName = tabSplitCrvName[abs( vTempProps[i+1])]
if sName then
EgtSetName( nOutlineId, sName)
else
AssignSplitName( nOutlineId)
end
else
EgtSetName( nOutlineId, EgtGetName( abs( vTempProps[i+1])))
end
end
-- riordino in modo da avere il bottom come prima curva
for i = 0, nCnt - 1 do
if EgtGetName( nCrv + i) ~= WIN_BOTTOM then
EgtRelocateGlob( nCrv + i, nOutlineLayerId, GDB_IN.LAST_SON)
else
break
end
end
end
-- calcolo i profili
local vOutlineCrvs = EgtGetAllInGroup( nOutlineLayerId)
CalcSashProfiles( vOutlineCrvs, nAreaId)
-- spostamento in z : recupero la quota da un profilo dell'anta
local nProfileLayerId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE)
local nSashProfileLayerId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_SASH)
local sSashProfile = EgtGetInfo( vOutlineCrvs[1], WIN_PROFILETYPE)
local nSashProfileId = EgtGetFirstNameInGroup( nSashProfileLayerId, sSashProfile)
local dSashZOffset = EgtGetInfo( nSashProfileId, WIN_DELTA, 'd')
EgtMove( vOutlineCrvs, Z_AX() * dSashZOffset)
return vOutlineCrvs
end
---------------------------------------------------------------------
local function VerifySashOutlines( vOutlines, nAreaId)
-- controlla se i pezzi di un'anta sono validi e se necessitano di gestione speciale nel calcolo dei prev e dei next. Vi sono due tipologie di pezzi che richiedono gestione speciale :
-- a) extra : il pezzo non serve, il suo contributo si limita al trim dei suoi pezzi vicini con il suo bordo out
-- b) special : il pezzo è necessario ma non sufficiente per il trim dei suoi pezzi vicini, che vanno tagliati non solo con il pezzo stesso ma anche tra di loro
-- per distinguere i pezzi extra da special controllo se i semiprofili interni dei pezzi vicini si incontrano in un punto sensato per cui il pezzo risulta superfluo oppure no
local nGrpTmp1 = EgtGroup( nAreaId)
local nGrpTmp2 = EgtGroup( nAreaId)
-- recupero i bordi interni ed esterni dei semiprofili in
local vInSemiProfile = {}
local vOutSemiProfile = {}
for i = 1, #vOutlines do
-- recupero il semiprofilo in
local nProfileId = GetOutlineTheoricProfileId( vOutlines[i])
local nSectionFrId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frSectionFrame = EgtFR( nSectionFrId, GDB_ID.ROOT)
local nInId = EgtGetFirstNameInGroup( nProfileId, WIN_IN)
local b3In = EgtGetBBoxRef( nInId, GDB_BB.STANDARD, frSectionFrame)
local dDimStd = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
local dRealDim = EgtGetInfo( vOutlines[i], WIN_PART_DIM, 'd')
vInSemiProfile[i] = EgtCopyGlob( vOutlines[i], nGrpTmp1)
EgtSetInfo( vInSemiProfile[i], 'SouIdx', i)
-- se non è possibile calcolare l'interno ( e.g. arco con raggio inferiore alla sua dimensione) il pezzo è sicuramente extra ma considero comunque le sue curve nel fare i conti
-- per non sfalsare gli indici
if not EgtOffsetCurve( vInSemiProfile[i], b3In:getMin():getX() * dRealDim / dDimStd) then
EgtSetInfo( vOutlines[i], WIN_EXTRA_CRV, true)
end
vOutSemiProfile[i] = EgtCopyGlob( vOutlines[i], nGrpTmp2)
EgtOffsetCurve( vOutSemiProfile[i], b3In:getMax():getX() * dRealDim / dDimStd)
EgtSetInfo( vOutSemiProfile[i], 'SouIdx', i)
end
local _, vExtraIn = TrimOrderedCurves( vInSemiProfile, false)
-- se nessun bordo più interno scompare allora tutti i pezzi sono standard
if #vExtraIn == 0 then
EgtErase( nGrpTmp1)
EgtErase( nGrpTmp2)
return
end
local _, vExtraOut = TrimOrderedCurves( vOutSemiProfile, false)
-- se il bordo esterno del suo profilo in scompare i suoi vicini si incontrano in modo sensato quindi il pezzo è sicuramente superfluo
for i = 1, #vExtraOut do
local nIdx = EgtGetInfo( vExtraOut[i], 'SouIdx', 'i')
EgtSetInfo( vOutlines[nIdx], WIN_EXTRA_CRV, true)
end
-- analizzo i tratti con gestione speciale consecutivi insieme
local nOldId
local vExtraInGrps = {}
for i = 1, #vExtraIn do
local nIdx = EgtGetInfo( vExtraIn[i], 'SouIdx', 'i')
if not EgtGetInfo( vOutlines[nIdx], WIN_EXTRA_CRV, 'b') then
if not nOldId or EgtGetNext( nOldId) ~= vExtraIn[i] then
table.insert( vExtraInGrps, { vExtraIn[i]})
else
table.insert( vExtraInGrps[#vExtraInGrps], vExtraIn[i])
end
nOldId = vExtraIn[i]
end
end
for i = 1, #vExtraInGrps do
-- calcolo il punto di incontro dei semiprofili interni dei due pezzi vicini validi
local nIdx1 = EgtGetInfo( vExtraInGrps[i][1], 'SouIdx', 'i')
local nPrevIdx = EgtIf( nIdx1 == 1, #vOutlines, nIdx1-1)
while EgtGetInfo( vOutlines[nPrevIdx], WIN_EXTRA_CRV, 'b') do
nPrevIdx = EgtIf( nPrevIdx == 1, #vOutlines, nPrevIdx-1)
end
local nIdx2 = EgtGetInfo( vExtraInGrps[i][#vExtraInGrps[i]], 'SouIdx', 'i')
local nNextIdx = EgtIf( nIdx2 == #vOutlines, 1, nIdx2+1)
while EgtGetInfo( vOutlines[nNextIdx], WIN_EXTRA_CRV, 'b') do
nNextIdx = EgtIf( nNextIdx == #vOutlines, 1, nNextIdx+1)
end
local nPrevOut = vOutSemiProfile[nPrevIdx]
local nNextOut = vOutSemiProfile[nNextIdx]
local ptInters = FindIntersectionPoint( nPrevOut, nNextOut, EgtEP( nPrevOut))
-- ricavo le curva che delimita la regione valida per l'intersezione dei semiprofili dei pezzi vicini
local vCurrOutlines = {}
for j = 1, #vExtraInGrps[i] do
local nIdx = EgtGetInfo( vExtraInGrps[i][j], 'SouIdx', 'i')
vCurrOutlines[j] = vOutlines[nIdx]
end
local nCompoOutline = EgtCurveCompo( nGrpTmp1, vCurrOutlines, false)
local nProfileId = GetOutlineTheoricProfileId( vCurrOutlines[1])
local dDimStd = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
local dRealDim = EgtGetInfo( vCurrOutlines[1], WIN_PART_DIM, 'd')
local nSectionFrId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frSectionFrame = EgtFR( nSectionFrId, GDB_ID.ROOT)
local nCPId = EgtGetFirstNameInGroup( nProfileId, WIN_OUT)
local b3CP = EgtGetBBoxRef( nCPId, GDB_BB.STANDARD, frSectionFrame)
local nRefCrv = EgtOffsetCurveAdv( nCompoOutline, b3CP:getMin():getX() * dRealDim / dDimStd)
local _, _, nSide = EgtPointCurveDistSide( ptInters, nRefCrv, Z_AX())
for j = 1, #vCurrOutlines do
-- se il punto di intersezione cade nella regione valida il pezzo è extra altrimenti è special
if nSide == -1 then
EgtSetInfo( vCurrOutlines[j], WIN_EXTRA_CRV, true)
else
EgtSetInfo( vCurrOutlines[j], WIN_SPECIAL_CRV, true)
end
end
end
EgtErase( nGrpTmp1)
EgtErase( nGrpTmp2)
end
------------------------------ FILL -------------------------------
---------------------------------------------------------------------
local function CalculateFillOutline( nAreaId, nOutlineLayerId)
-- recupero area parent di tipo telaio/anta che la contiene
local nParentArea = EgtGetParent( nAreaId)
local nAreaType = EgtGetInfo( nParentArea, WIN_AREATYPE, 'i')
while nAreaType ~= WIN_AREATYPES.FRAME and nAreaType ~= WIN_AREATYPES.SASH do
nParentArea = EgtGetParent( nParentArea)
nAreaType = EgtGetInfo( nParentArea, WIN_AREATYPE, 'i')
end
-- 1) calcolo l'area complessiva di fill definita dal suo parent
local nParentOutlineLayer = EgtGetFirstNameInGroup( nParentArea, WIN_OUTLINE)
local dDeltaZ = 0
local vParentOutlines = EgtGetAllInGroup( nParentOutlineLayer)
local vParentOffs = {}
-- calcolo gli offset
for i = 1, #vParentOutlines do
-- recupero il suo profilo per calcolare l'offset perpendicolare
local nParentProfileId = GetOutlineTheoricProfileId( vParentOutlines[i], true)
local dOverlap = EgtGetInfo( nParentProfileId, WIN_FILLOVERLAP, 'd')
if dOverlap then
local dRealDim = EgtGetInfo( vParentOutlines[i], WIN_PART_DIM, 'd')
-- verifico se contributo per bottomrail
local dRailOffs = 0
if EgtGetName( nParentProfileId) == WIN_FILL_RAIL then
local nBottomRail = EgtGetInfo( vParentOutlines[i], WIN_BOTTOMRAIL, 'i')
dRailOffs = CalcRailOffset( vParentOutlines[i], nParentProfileId, nBottomRail)
local vBottomRailDims = EgtGetInfo( vParentOutlines[i], WIN_BOTTOMRAIL .. WIN_PART_DIM, 'vd')
dRealDim = vBottomRailDims[#vBottomRailDims]
end
local b3FrameProfile = GetProfileLocalBox( nParentProfileId)
local dDimRef = b3FrameProfile:getMin():getX() * dRealDim / b3FrameProfile:getDimX()
vParentOffs[i] = abs( dDimRef) - dOverlap + dRailOffs
-- movimento in z
if dDeltaZ < GEO.EPS_SMALL then
dDeltaZ = EgtGetInfo( nParentProfileId, WIN_FILLDELTA, 'd')
end
end
end
-- creo le curve di outlines
for i = 1, #vParentOutlines do
-- copio la curva di outline del parent
local nOutlineId = EgtCopy( vParentOutlines[i], nOutlineLayerId)
EgtSetInfo( nOutlineId, WIN_SOU_OUTLINE, vParentOutlines[i])
-- applico offset
if vParentOffs[i] then
EgtOffsetCurve( nOutlineId, - vParentOffs[i])
else
-- se non ha offset definito è un pezzo che verrà tagliato da uno split ma, affinchè la forma del telaio sia coerente, devo applicare lo stesso offset a curve
-- che sono in tangenza
local nPrevIdx = EgtIf( i == 1, #vParentOutlines, i-1)
local nNextIdx = EgtIf( i == #vParentOutlines, 1, i+1)
if AreSameVectorApprox( EgtSV( vParentOutlines[i]), EgtEV( vParentOutlines[nPrevIdx])) then
while not vParentOffs[nPrevIdx] do
nPrevIdx = EgtIf( nPrevIdx == 1, #vParentOutlines, nPrevIdx-1)
end
EgtOffsetCurve( nOutlineId, - vParentOffs[nPrevIdx])
vParentOffs[i] = vParentOffs[nPrevIdx]
elseif AreSameVectorApprox( EgtEV( vParentOutlines[i]), EgtSV( vParentOutlines[nNextIdx])) then
while not vParentOffs[nNextIdx] do
nNextIdx = EgtIf( nNextIdx == #vParentOutlines, 1, nNextIdx+1)
end
EgtOffsetCurve( nOutlineId, - vParentOffs[nNextIdx])
vParentOffs[i] = vParentOffs[nNextIdx]
end
end
end
-- accorcio gli offset
local vCrvs = TrimOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), true)
-- applico spostamento verticale
EgtMove( vCrvs, Z_AX() * dDeltaZ)
-- 2) taglio con split
local nParentType = EgtGetInfo( EgtGetParent( nAreaId), WIN_AREATYPE, 'i')
if nParentType ~= WIN_AREATYPES.NULL then
-- salvo associazioni sou/child
for i = 1, #vCrvs do
local nSouOutlineId = EgtGetInfo( vCrvs[i], WIN_SOU_OUTLINE, 'i')
AddInfo( nSouOutlineId, WIN_CHILD_OUTLINE, vCrvs[i])
end
return
end
-- creo bordo complessivo dell'outline, salvando le info come temp prop della curva per non perderle
local vSouOutlines = {}
for i = 1, #vCrvs do
vSouOutlines[i] = EgtGetInfo( vCrvs[i], WIN_SOU_OUTLINE, 'i')
end
local nCompo = EgtCurveCompo( nOutlineLayerId, vCrvs)
for i = 0, #vCrvs - 1 do
EgtCurveCompoSetTempProp( nCompo, i, vSouOutlines[i+1])
end
-- recupero gli split che definiscono l'area fill cercando gli split in tutte le aree parent di tipo null
local vSplitIds = {}
local nParentId = EgtGetParent( nAreaId)
while nParentId ~= nParentArea do
local nParentType = EgtGetInfo( nParentId, WIN_AREATYPE, 'i')
if nParentType == WIN_AREATYPES.NULL then
local nNullOutlineLay = EgtGetFirstNameInGroup( nParentId, WIN_OUTLINE)
local vNullOutlines = EgtGetAllInGroup( nNullOutlineLay)
for i = 1, #vNullOutlines do
local nSou = EgtGetInfo( vNullOutlines[i], WIN_SOU_OUTLINE, 'i')
if EgtGetName( EgtGetParent( EgtGetParent( abs( nSou)))) == WIN_VIRTUAL_AREA then
nSou = EgtGetInfo( abs( nSou), WIN_SOU_OUTLINE, 'i')
end
if EgtGetName( abs( nSou)) == WIN_SPLIT then
table.insert( vSplitIds, nSou)
end
end
end
nParentId = EgtGetParent( nParentId)
end
-- li ordino per id crescente in modo da effettuare i tagli nell'ordine corretto
table.sort( vSplitIds, function ( a, b) return abs( a) < abs( b) end)
for i = 1, #vSplitIds do
-- creo la curva di outline corrispondente allo split
local nOutlineId = EgtCopy( abs( vSplitIds[i]), nOutlineLayerId)
if vSplitIds[i] < 0 then
EgtInvertCurve( nOutlineId)
end
-- calcolo gli offset
local nProfileId = GetOutlineTheoricProfileId( abs( vSplitIds[i]), true)
local b3Profile = GetProfileLocalBox( nProfileId)
local dOverlap = EgtGetInfo( nProfileId, WIN_FILLOVERLAP, 'd')
local dDimRef = EgtIf( vSplitIds[i] < 0, b3Profile:getMax():getX(), b3Profile:getMin():getX())
local dRealDim = EgtGetInfo( abs( vSplitIds[i]), WIN_PART_DIM, 'd')
local dOffs = abs( dDimRef) * dRealDim / b3Profile:getDimX() - dOverlap
EgtOffsetCurve( nOutlineId, - dOffs)
-- movimento in z
local dFillZOffset = EgtGetInfo( nProfileId, WIN_FILLDELTA, 'd')
EgtMove( nOutlineId, Z_AX() * dFillZOffset)
-- aggiorno la curva complessiva di outline con la curva appena calcolata
local ptS = EgtIP( nOutlineId, nCompo, EgtSP( nOutlineId))
local ptE = EgtIP( nOutlineId, nCompo, EgtEP( nOutlineId))
local dBorderParS = EgtCurveParamAtPoint( nCompo, ptS)
local dBorderParE = EgtCurveParamAtPoint( nCompo, ptE)
EgtTrimCurveStartEndAtParam( nCompo, dBorderParE, dBorderParS)
local dSplitParS = EgtCurveParamAtPoint( nOutlineId, ptS)
local dSplitParE = EgtCurveParamAtPoint( nOutlineId, ptE)
EgtTrimCurveStartEndAtParam( nOutlineId, dSplitParS, dSplitParE)
EgtAddCurveCompoCurve( nCompo, nOutlineId)
local _, dParEnd = EgtCurveDomain( nCompo)
EgtCurveCompoSetTempProp( nCompo, dParEnd - 1, vSplitIds[i])
end
-- spezzo la curva di outline nelle sue sottocurve e riassegno le info
local vTempProps = EgtCurveCompoGetTempProp( nCompo)
local nCrv, nCnt = EgtExplodeCurveCompo( nCompo)
for i = 0, nCnt - 1 do
EgtSetInfo( nCrv + i, WIN_SOU_OUTLINE, vTempProps[i+1])
if vTempProps[i+1] > 0 then
AddInfo( vTempProps[i+1], WIN_CHILD_OUTLINE, nCrv + i)
else
AddInfo( abs( vTempProps[i+1]), WIN_CHILD_OUTLINE, - ( nCrv + i))
end
end
end
-------------------- AGGIORNAMENTO TIPOLOGIE ----------------------
---------------------------------------------------------------------
-- funzione ricorsiva che aggiorna le tipologie di split guardando le curve di outlines ( e non quelle di base outlines come fatto in CalcProfileType)
local function UpdateSplitTypes( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH or nAreaType == WIN_AREATYPES.FILL then
return
elseif nAreaType == WIN_AREATYPES.SPLIT then
if EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i') ~= WIN_SPLITTYPES.FRENCH then
local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT)
local vSplits = EgtGetAllInGroup( nSplitLayerId)
for i = 1, #vSplits do
-- identifico la tipologia di figli dal lato destro (1) e sinistro (2)
local tabChildren = {{}, {}}
local vSashNbr = { 0, 0}
local vFillNbr = { 0, 0}
local vBaseChildren = EgtGetInfo( vSplits[i], WIN_CHILD_VIRTUAL_OUTLINE, 'vi')
-- ordino i figli letti dalle info in modo tale che quello di destra ( che ha segno negativo) sia il primo e quello di sinistra ( che ha segno positivo) sia il secondo
if vBaseChildren[1] > vBaseChildren[2] then
vBaseChildren[1], vBaseChildren[2] = vBaseChildren[2], vBaseChildren[1]
end
for k = 1, 2 do
local vCurrChildren = { vBaseChildren[k]}
local j = 1
while vCurrChildren[j] do
local vNewChildren = EgtGetInfo( abs( vCurrChildren[j]), WIN_CHILD_VIRTUAL_OUTLINE, 'vi')
if vNewChildren then
EgtJoinTables( vCurrChildren, vNewChildren)
else
-- se non ha ulteriori figli allora è l'area null finale che deve essere studiata
local nNullAreaId = EgtGetParent( EgtGetParent( abs( vCurrChildren[j])))
local nAreaId = EgtGetFirstNameInGroup( nNullAreaId, WIN_AREA .. '*')
local nAreaType
if nAreaId then
nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
vSashNbr[k] = vSashNbr[k] + 1
elseif nAreaType == WIN_AREATYPES.FILL then
vFillNbr[k] = vFillNbr[k] + 1
end
end
table.insert( tabChildren[k], { nId = abs( vCurrChildren[j]), nType = nAreaType})
end
j = j + 1
end
end
-- ricavo la nuova tipologia di split ed eventualmente aggiorno il profilo se fosse diverso da quello calcolato dai base outlines
local nOldType = EgtGetInfo( vSplits[i], WIN_SPLITTYPE, 'i')
-- se figli sono solo ante è montante
if vFillNbr[1] == 0 and vFillNbr[2] == 0 then
if nOldType ~= WIN_SPLITTYPES.MULLION then
EgtSetInfo( vSplits[i], WIN_SPLITTYPE, WIN_SPLITTYPES.MULLION)
if AreSameOrOppositeVectorApprox( EgtSV( vSplits[i]), X_AX()) then
EgtSetInfo( vSplits[i], WIN_PROFILETYPE, WIN_SASH_HORIZONTAL)
else
EgtSetInfo( vSplits[i], WIN_PROFILETYPE, WIN_SASH_VERTICAL)
end
end
-- se figli sono solo vetri fissi è muntin interno al telaio
elseif vSashNbr[1] == 0 and vSashNbr[2] == 0 then
if nOldType ~= WIN_SPLITTYPES.MUNTIN_FRAME then
EgtSetInfo( vSplits[i], WIN_SPLITTYPE, WIN_SPLITTYPES.MUNTIN_FRAME)
EgtSetInfo( vSplits[i], WIN_PROFILETYPE, WIN_FRAME_SPLIT)
end
-- se figli di entrambe le tipologie è mixed e verifico quali sono le parti dello split coinvolte dal cambio profilo
else
local nPrfChange = 0
-- ricavo le tipologie di figli su start ed end a destra
local nStart1, nEnd1
if vSashNbr[1] > 0 and vFillNbr[1] == 0 then
nStart1 = WIN_CHILDREN_TYPES.SASH
nEnd1 = WIN_CHILDREN_TYPES.SASH
elseif vSashNbr[1] == 0 and vFillNbr[1] > 0 then
nStart1 = WIN_CHILDREN_TYPES.FILL
nEnd1 = WIN_CHILDREN_TYPES.FILL
else
nPrfChange = nPrfChange + WIN_PRF_CHANGE_TYPES.OUT -- ha cambio profilo sul lato esterno
for j = 1, #tabChildren[1] do
if AreSamePointApprox( EgtSP( vSplits[i]), EgtEP( tabChildren[1][j].nId)) then
nStart1 = EgtIf( tabChildren[1][j].nType == WIN_AREATYPES.SASH, WIN_CHILDREN_TYPES.SASH, WIN_CHILDREN_TYPES.FILL)
end
if AreSamePointApprox( EgtEP( vSplits[i]), EgtSP( tabChildren[1][j].nId)) then
nEnd1 = EgtIf( tabChildren[1][j].nType == WIN_AREATYPES.SASH, WIN_CHILDREN_TYPES.SASH, WIN_CHILDREN_TYPES.FILL)
end
end
end
-- ricavo le tipologie di figli su start ed end a sinistra
local nStart2, nEnd2
if vSashNbr[2] > 0 and vFillNbr[2] == 0 then
nStart2 = WIN_CHILDREN_TYPES.SASH
nEnd2 = WIN_CHILDREN_TYPES.SASH
elseif vSashNbr[2] == 0 and vFillNbr[2] > 0 then
nStart2 = WIN_CHILDREN_TYPES.FILL
nEnd2 = WIN_CHILDREN_TYPES.FILL
else
nPrfChange = nPrfChange + WIN_PRF_CHANGE_TYPES.IN -- ha cambio profilo su lato interno
for j = 1, #tabChildren[2] do
if AreSamePointApprox( EgtSP( vSplits[i]), EgtSP( tabChildren[2][j].nId)) then
nStart2 = EgtIf( tabChildren[2][j].nType == WIN_AREATYPES.SASH, WIN_CHILDREN_TYPES.SASH, WIN_CHILDREN_TYPES.FILL)
end
if AreSamePointApprox( EgtEP( vSplits[i]), EgtEP( tabChildren[2][j].nId)) then
nEnd2 = EgtIf( tabChildren[2][j].nType == WIN_AREATYPES.SASH, WIN_CHILDREN_TYPES.SASH, WIN_CHILDREN_TYPES.FILL)
end
end
end
-- se le tipologie di figli sugli estremi sono diverse tra destra e sinistra allora l'estremo è coinvolto dal cambio profilo
if nStart1 ~= nStart2 then
nPrfChange = nPrfChange + WIN_PRF_CHANGE_TYPES.START
end
if nEnd1 ~= nEnd2 then
nPrfChange = nPrfChange + WIN_PRF_CHANGE_TYPES.END
end
EgtSetInfo( vSplits[i], WIN_SPLITTYPE, WIN_SPLITTYPES.MIXED)
EgtSetInfo( vSplits[i], WIN_PRF_CHANGE, nPrfChange)
EgtSetInfo( vSplits[i], WIN_MIXED_START_CHILDREN .. '1', nStart1)
EgtSetInfo( vSplits[i], WIN_MIXED_START_CHILDREN .. '2', nStart2)
EgtSetInfo( vSplits[i], WIN_MIXED_END_CHILDREN .. '1', nEnd1)
EgtSetInfo( vSplits[i], WIN_MIXED_END_CHILDREN .. '2', nEnd2)
end
end
end
end
-- analizzo le sottoaree
local vChildren = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
for i = 1, #vChildren do
UpdateSplitTypes( vChildren[i])
end
end
---------------------------------------------------------------------
local function VerifyOutlinesInterferenceWithMixedSplit( nAreaId, vOutlines)
local vInterference = {}
local vToBeTested = {}
for i = 1, #vOutlines do
vInterference[i] = false
vToBeTested[i] = false
end
local nGrpTmp = EgtGroup( nAreaId)
EgtSetStatus( nGrpTmp, GDB_ST.OFF)
-- ricavo i profili mixed teorici
local nProfileGrp = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE)
local nFrameProfileGrp = EgtGetFirstNameInGroup( nProfileGrp, WIN_FRAME)
local nBottomProfileId = EgtGetFirstNameInGroup( nFrameProfileGrp, WIN_MIXED_BOTTOM)
local b3Bottom = GetProfileLocalBox( nBottomProfileId)
local nTopProfileId = EgtGetFirstNameInGroup( nFrameProfileGrp, WIN_MIXED_TOP)
local b3Top = GetProfileLocalBox( nTopProfileId)
local nSplitProfileId = EgtGetFirstNameInGroup( nFrameProfileGrp, WIN_MIXED_SPLIT)
local b3Split = GetProfileLocalBox( nSplitProfileId)
-- calcolo i box delle curve di outlines
local tabBox = {}
for i = 1, #vOutlines do
local nProfileId = EgtIf( i == 1, nBottomProfileId, nTopProfileId)
local b3Profile = EgtIf( i == 1, b3Bottom, b3Top)
local b3Box, frRef = CreateTestBoxFromOutline( vOutlines[i], nProfileId, b3Profile)
tabBox[i] = { frRef = frRef, b3Box = b3Box}
end
-- recupero tutti gli split con cambio profilo sugli estremi che arrivano sul telaio
local tabSplits = {}
local vChildAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
local i = 1
while vChildAreas[i] do
local nAreaType = EgtGetInfo( vChildAreas[i], WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH or nAreaType == WIN_AREATYPES.FILL then
-- la ricerca a cascata si interrompe
else
if nAreaType == WIN_AREATYPES.SPLIT then
local nSplitLayerId = EgtGetFirstNameInGroup( vChildAreas[i], WIN_SPLIT)
local vSplits = EgtGetAllInGroup( nSplitLayerId)
for j = 1, #vSplits do
local nPrfChange = EgtGetInfo( vSplits[j], WIN_PRF_CHANGE, 'i') or WIN_PRF_CHANGE_TYPES.NULL
if nPrfChange & WIN_PRF_CHANGE_TYPES.START > 0 then
local nBaseStart = EgtGetInfo( vSplits[j], WIN_SPLIT_STARTINTERS, 'i')
local nStart = GetNonVirtualOutline( nBaseStart)
if EgtGetName( abs( nStart)) ~= WIN_SPLIT then
-- controllo con quanti outlines fa interferenza controllando l'overlap dei box
local nRefCrv = EgtCopyGlob( vSplits[j], nGrpTmp)
EgtTrimCurveEndAtLen( nRefCrv, 0.5 * EgtCurveLength( nRefCrv))
local b3Box, frRef = CreateTestBoxFromOutline( nRefCrv, nSplitProfileId, b3Split)
local vTest = {} -- indici degli outlines con cui fa interferenza
for k = 1, #tabBox do
if Overlaps( tabBox[k].b3Box, tabBox[k].frRef, b3Box, frRef) then
table.insert( vTest, k)
end
end
if #vTest == 1 then
-- se fa intereferenza con una sola curva non servono ulteriori controlli, l'interferenza è confermata
vInterference[vTest[1]] = true
AddInfo( vOutlines[vTest[1]], WIN_CHILD_PRFCHANGE_SPLIT, vSplits[j])
EgtSetInfo( vSplits[j], WIN_PREV_OUTLINES, vOutlines[vTest[1]])
EgtSetInfo( vSplits[j], WIN_STARTJOINT, WIN_PART_JNT.SHORT)
elseif #vTest > 1 then
-- se fa interferenza con più curve allora dovrò controllare quali sono le vere interferenze controllando i profili
table.insert( tabSplits, { nId = vSplits[j], bStart = true, vTest = vTest})
for k = 1, #vTest do
vToBeTested[vTest[k]] = true
end
end
end
end
if nPrfChange & WIN_PRF_CHANGE_TYPES.END > 0 then
local nBaseEnd = EgtGetInfo( vSplits[j], WIN_SPLIT_ENDINTERS, 'i')
local nEnd = GetNonVirtualOutline( nBaseEnd)
if EgtGetName( abs( nEnd)) ~= WIN_SPLIT then
local nRefCrv = EgtCopyGlob( vSplits[j], nGrpTmp)
EgtTrimCurveStartAtLen( nRefCrv, 0.5 * EgtCurveLength( nRefCrv))
local b3Box, frRef = CreateTestBoxFromOutline( nRefCrv, nSplitProfileId, b3Split)
local vTest = {}
for k = 1, #tabBox do
if Overlaps( tabBox[k].b3Box, tabBox[k].frRef, b3Box, frRef) then
table.insert( vTest, k)
end
end
if #vTest == 1 then
vInterference[vTest[1]] = true
AddInfo( vOutlines[vTest[1]], WIN_CHILD_PRFCHANGE_SPLIT, vSplits[j])
EgtSetInfo( vSplits[j], WIN_NEXT_OUTLINES, vOutlines[vTest[1]])
EgtSetInfo( vSplits[j], WIN_ENDJOINT, WIN_PART_JNT.SHORT)
elseif #vTest > 1 then
table.insert( tabSplits, { nId = vSplits[j], bStart = false, vTest = vTest})
for k = 1, #vTest do
vToBeTested[vTest[k]] = true
end
end
end
end
end
end
-- analizzo le sottaree
local vCurrChildAreas = EgtGetNameInGroup( vChildAreas[i], WIN_AREA .. '*')
EgtJoinTables( vChildAreas, vCurrChildAreas)
end
i = i + 1
end
-- per ogni curva di outline che deve essere testata costruisco la superficie in con il controprofilo sash ( perchè è quella che verrà usata per tagliare lo split)
local vTestSurfs = {}
for i = 1, #vOutlines do
if vToBeTested[i] then
local nProfileId = EgtIf( i == 1, nBottomProfileId, nTopProfileId)
local nGuideId = EgtCopyGlob( vOutlines[i], nGrpTmp)
local dDimStd = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
local dDimReal = EgtGetInfo( vOutlines[i], WIN_PART_DIM, 'd')
if abs( dDimReal - dDimStd) > GEO.EPS_SMALL then
local dOffs = dDimReal / dDimStd
EgtOffsetCurve( nGuideId, - dOffs)
end
vTestSurfs[i] = CreateProfileSurf( nGuideId, nProfileId, WIN_SASH .. WIN_CTRIN, 100, nGrpTmp)
end
end
-- taglio le superfici con bisettrice ( perchè se entrambi i pezzi hanno cambio profilo la giunzione viene forzata a angled)
for i = 1, #vOutlines do
local nPrevIdx = EgtIf( i == 1, #vOutlines, i - 1)
if vTestSurfs[i] or vTestSurfs[nPrevIdx] then
if EgtGetType( vOutlines[i]) == GDB_TY.CRV_LINE and EgtGetType( vOutlines[nPrevIdx]) == GDB_TY.CRV_LINE then
local vtDir = 0.5 * ( EgtSV( vOutlines[i]) - EgtEV( vOutlines[nPrevIdx]))
if vtDir:isZero() then
vtDir = - EgtSV( vOutlines[i])
else
vtDir:rotate( Z_AX(), 90)
end
if vTestSurfs[i] then
EgtCutSurfTmPlane( vTestSurfs[i], EgtSP( vOutlines[i]), vtDir, false)
end
if vTestSurfs[nPrevIdx] then
EgtCutSurfTmPlane( vTestSurfs[nPrevIdx], EgtSP( vOutlines[i]), - vtDir, false)
end
else
-- calcolo bisettore
local nBisector = CalcParabolicBisector( vOutlines[nPrevIdx], vOutlines[i], 100, nGrpTmp, false, false)
local nBisectorSurf = EgtSurfTmByRegionExtrusion( nGrpTmp, nBisector, - 100 * Z_AX())
if vTestSurfs[i] then
EgtSurfTmCut( vTestSurfs[i], nBisectorSurf, true, false)
end
if vTestSurfs[nPrevIdx] then
EgtSurfTmCut( vTestSurfs[nPrevIdx], nBisectorSurf, false, false)
end
end
end
end
-- verifico le intereferernze
for i = 1, #tabSplits do
-- costruisco il profilo dello split sull'estremo considerato in base alla tipologia di figli
local nChildrenType1 = EgtGetInfo( tabSplits[i].nId, EgtIf( tabSplits[i].bStart, WIN_MIXED_START_CHILDREN, WIN_MIXED_END_CHILDREN) .. '1', 'i')
local sSemiProfileName1 = EgtIf( nChildrenType1 == WIN_CHILDREN_TYPES.SASH, WIN_SASH, WIN_FILL) .. WIN_IN .. '1'
local nSemiProfile1 = EgtGetFirstNameInGroup( nSplitProfileId, sSemiProfileName1)
local nChildrenType2 = EgtGetInfo( tabSplits[i].nId, EgtIf( tabSplits[i].bStart, WIN_MIXED_START_CHILDREN, WIN_MIXED_END_CHILDREN) .. '2', 'i')
local sSemiProfileName2 = EgtIf( nChildrenType2 == WIN_CHILDREN_TYPES.SASH, WIN_SASH, WIN_FILL) .. WIN_IN .. '2'
local nSemiProfile2 = EgtGetFirstNameInGroup( nSplitProfileId, sSemiProfileName2)
local dDimStd = EgtGetInfo( nSplitProfileId, WIN_DIM_STD, 'd')
local dDimReal = EgtGetInfo( tabSplits[i].nId, WIN_PART_DIM, 'd')
if abs( dDimReal - dDimStd) > GEO.EPS_SMALL then
local nSectionFrame = EgtGetFirstNameInGroup( nSplitProfileId, WIN_SECTIONFRAME)
local frProfile = EgtFR( nSectionFrame, GDB_ID.ROOT)
EgtMove( nSemiProfile1, b3Split:getMax():getX() * dDimReal / dDimStd * frProfile:getVersX(), GDB_RT.GLOB)
EgtMove( nSemiProfile1, b3Split:getMin():getX() * dDimReal / dDimStd * frProfile:getVersX(), GDB_RT.GLOB)
end
local nSection = EgtCurveCompo( nGrpTmp, nSemiProfile1, false)
EgtAddCurveCompoLine( nSection, EgtSP( nSemiProfile2, GDB_ID.ROOT), GDB_RT.GLOB)
EgtAddCurveCompoCurve( nSection, nSemiProfile2, false)
EgtCloseCurveCompo( nSection)
-- costruisco il solido di split
local nSplitSolid = CreateProfileSurfById( tabSplits[i].nId, nSplitProfileId, nSection, 400, nGrpTmp)
EgtCutSurfTmPlane( nSplitSolid, EgtMP( tabSplits[i].nId), EgtIf( tabSplits[i].bStart, 1, -1) * EgtSV( tabSplits[i].nId))
-- testo con quali superfici degli outlines fa interferenza
for j = 1, #( tabSplits[i].vTest) do
local nIdx = tabSplits[i].vTest[j]
local nId, _, nCrvCnt = EgtSurfTmSurfTmInters( nSplitSolid, vTestSurfs[nIdx], nGrpTmp)
if nId and nCrvCnt > 0 then
vInterference[nIdx] = true
AddInfo( vOutlines[nIdx], WIN_CHILD_PRFCHANGE_SPLIT, tabSplits[i].nId)
AddInfo( tabSplits[i].nId, EgtIf( tabSplits[i].bStart, WIN_PREV_OUTLINES, WIN_NEXT_OUTLINES), vOutlines[nIdx])
AddInfo( tabSplits[i].nId, EgtIf( tabSplits[i].bStart, WIN_STARTJOINT, WIN_ENDJOINT), WIN_PART_JNT.SHORT)
end
end
end
EgtErase( nGrpTmp)
return vInterference
end
---------------------------------------------------------------------
-- funzione che aggiorna i profili del telaio guardando le curve di outlines ( e non quelle di base outlines come fatto in CalcProfileType)
local function UpdateFrameTypes( nAreaId)
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlines = EgtGetAllInGroup( nOutlineLayerId)
-- per ogni outline verifico se fa interferenza con uno split con cambio profilo sull'estremo
local vInterference = VerifyOutlinesInterferenceWithMixedSplit( nAreaId, vOutlines)
for i = 1, #vOutlines do
local nOldType = EgtGetInfo( vOutlines[i], WIN_CHILDREN_TYPE, 'i')
if vInterference[i] then
-- se fa interferenza con uno split con cambio profilo sull'estremo deve avere un profilo mixed
EgtSetInfo( vOutlines[i], WIN_PRF_CHANGE, WIN_PRF_CHANGE_TYPES.IN)
-- verifico se devo aggiornare il profilo
if nOldType ~= WIN_CHILDREN_TYPES.MIXED then
if EgtGetName( vOutlines[i]) == WIN_BOTTOM then
EgtSetInfo( vOutlines[i], WIN_PROFILETYPE, WIN_MIXED_BOTTOM)
else
EgtSetInfo( vOutlines[i], WIN_PROFILETYPE, WIN_MIXED_TOP)
end
end
else
-- se non fa interferenza con cambio profilo devo controllare la tipologia dei figli.
-- Se non era stato classificato come mixed allora basta trovare la tipologia di un figlio qualunque, se invece era mixed allora ha entrambe le tipologie di figli,
-- devo considerare quella della curva più lunga ( euristicamente se non è più mixed vuol dire che il cambio profilo avviene vicino al suo estremo quindi
-- uno dei due figli è molto più corto dell'altro)
local dFillLen = 0
local dSashLen = 0
local vChildren = EgtGetInfo( vOutlines[i], WIN_CHILD_VIRTUAL_OUTLINE, 'vi')
local j = 1
while vChildren[j] do
-- verifico se ho cascata di children
local vNewChildren = EgtGetInfo( abs( vChildren[j]), WIN_CHILD_VIRTUAL_OUTLINE, 'vi')
if vNewChildren then
EgtJoinTables( vChildren, vNewChildren)
else
-- recupero la tipologia di figli dell'area null
local nNullAreaId = EgtGetParent( EgtGetParent( abs( vChildren[j])))
local nAreaId = EgtGetFirstNameInGroup( nNullAreaId, WIN_AREA .. '*')
if nAreaId then
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
dSashLen = dSashLen + EgtCurveLength( abs( vChildren[j]))
else
dFillLen = dFillLen + EgtCurveLength( abs( vChildren[j]))
end
end
end
j = j + 1
end
local nChildrenType = EgtIf( dSashLen > dFillLen, WIN_CHILDREN_TYPES.SASH, WIN_CHILDREN_TYPES.FILL)
-- verifico se devo aggiornare il profilo
if nChildrenType ~= nOldType then
if nChildrenType == WIN_CHILDREN_TYPES.FILL then
if EgtGetName( vOutlines[i]) == WIN_BOTTOM then
-- verifico presenza bottomrail
local nBottomRail = EgtGetInfo( vOutlines[i], WIN_BOTTOMRAIL, 'i') or 0
local sThreshold = EgtGetInfo( EgtetParent( EgtGetParent( vOutlines[i])), WIN_THRESHOLD_PROFILE) or WIN_BOTTOM
if nBottomRail == 0 then
EgtSetInfo( vOutlines[i], WIN_PROFILETYPE, WIN_FIXED .. '_' .. sThreshold)
else
EgtSetInfo( vOutlines[i], WIN_PROFILETYPE, WIN_RAIL .. '_' .. sThreshold)
end
else
EgtSetInfo( vOutlines[i], WIN_PROFILETYPE, WIN_FIXED_TOP)
end
else -- sash
if EgtGetName( vOutlines[i]) == WIN_BOTTOM then
local sThreshold = EgtGetInfo( nAreaId, WIN_THRESHOLD_PROFILE) or WIN_BOTTOM
EgtSetInfo( vOutlines[i], WIN_PROFILETYPE, WIN_SASH .. '_' .. sThreshold)
else
EgtSetInfo( vOutlines[i], WIN_PROFILETYPE, WIN_SASH_TOP)
end
end
end
end
end
end
---------------------------------------------------------------------
--------------------------------------------------------------------
local function CalcOutlineDimensions( vOutlines, nAreaId)
local vPartsDim = EgtGetInfo( nAreaId, WIN_PART_DIM, 'vd') or {}
local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0
for i = 1, #vOutlines do
if not vPartsDim[i] or EgtGetInfo( vOutlines[i], WIN_THRESHOLD, 'b') then
-- se dimensione non è impostata oppure soglia recupero quella standard del profilo
local nProfileId = GetOutlineTheoricProfileId( vOutlines[i], false)
vPartsDim[i] = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
end
EgtSetInfo( vOutlines[i], WIN_PART_DIM, vPartsDim[i])
-- dimensioni dei bottomrails
if nBottomRail and EgtGetName( vOutlines[i]) == WIN_BOTTOM then
EgtSetInfo( vOutlines[i], WIN_BOTTOMRAIL, nBottomRail)
local vBottomRailDim = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL .. WIN_PART_DIM, 'vd') or {}
if #vBottomRailDim ~= nBottomRail then
for j = 1, nBottomRail do
if not vBottomRailDim[j] then
local nProfileId = GetOutlineTheoricProfileId( vOutlines[i], false, j)
vBottomRailDim[j] = EgtGetInfo( nProfileId, WIN_DIM_STD, 'd')
end
end
end
EgtSetInfo( vOutlines[i], WIN_BOTTOMRAIL .. WIN_PART_DIM, vBottomRailDim)
end
end
end
---------------------------------------------------------------------
-- funzione che calcola l'outline dal base outline e i pezzi associati
local function CalculateOutlineFromAreaOutline( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
-- se area null il suo outline è già stato calcolato dalla sua area split parent
if nAreaType == WIN_AREATYPES.NULL then
return
end
-- creo gruppo per outline
local nOutlineLayerId = EgtGroup( nAreaId)
EgtSetName( nOutlineLayerId, WIN_OUTLINE)
EgtSetStatus( nOutlineLayerId, GDB_ST.OFF)
-- FRAME
if nAreaType == WIN_AREATYPES.FRAME then
-- l'outline è la copia del base outline
local nBaseOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_AREAOUTLINE)
local vBaseOutlineIds = EgtGetAllInGroup( nBaseOutlineLayerId)
local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0
local vOutlines = {}
for i = 1, #vBaseOutlineIds do
vOutlines[i] = EgtCopyGlob( vBaseOutlineIds[i], nOutlineLayerId)
if i == 1 and nBottomRail > 0 then
EgtSetInfo( vOutlines[i], WIN_BOTTOMRAIL, nBottomRail)
end
end
CalcOutlineDimensions( vOutlines, nAreaId)
-- SPLIT
elseif nAreaType == WIN_AREATYPES.SPLIT then
-- l'outline è copia del parent outline
local nParentId = EgtGetParent( nAreaId)
if EgtGetInfo( nParentId, WIN_AREATYPE, 'i') == WIN_AREATYPES.FILL then
-- se inglesina il parent è un vetro. Il pezzo però non va tagliato con il vetro ma con l'elemento che contiene il vetro, quindi considero come outline quello del parent del vetro
nParentId = EgtGetParent( nParentId)
end
local nParentOutlineId = EgtGetFirstNameInGroup( nParentId, WIN_OUTLINE)
local vParentOutlines = EgtGetAllInGroup( nParentOutlineId)
for i = 1, #vParentOutlines do
local nOutlineId = EgtCopyGlob( vParentOutlines[i], nOutlineLayerId)
EgtSetInfo( nOutlineId, WIN_SOU_OUTLINE, vParentOutlines[i])
AddInfo( vParentOutlines[i], WIN_CHILD_VIRTUAL_OUTLINE, nOutlineId)
end
-- copio il layer di base split
local nBaseSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT)
local nSplitLayerId = EgtCopy( nBaseSplitLayerId, nAreaId)
EgtSetName( nSplitLayerId, WIN_SPLIT)
EgtSetStatus( nSplitLayerId, GDB_ST.OFF)
local vBaseSplitIds = EgtGetAllInGroup( nBaseSplitLayerId)
local vSplitIds = EgtGetAllInGroup( nSplitLayerId)
-- aggiusto la quota degli split per allinearli all'outline
local dZMove = ( EgtSP( vParentOutlines[1]) - EgtSP( vSplitIds[1])) * Z_AX()
EgtMove( vSplitIds, dZMove * Z_AX())
-- aggiusto gli outlines e calcolo l'outline delle sottoaree null generate
local bGrid = EgtGetInfo( nAreaId, WIN_GRID_SPLIT, 'b') or false
if bGrid then
CalculateGridSplitOutline( nAreaId, vSplitIds)
else
CalculateSplitOutline( nAreaId, vSplitIds)
end
local nSplitType = EgtGetInfo( vSplitIds[1], WIN_SPLITTYPE, 'i')
if nSplitType == WIN_SPLITTYPES.FRENCH then
IdentifySashShape( nAreaId, nOutlineLayerId)
end
-- se inglesina su entrambi i lati creo copia degli outline per le inglesine esterne
if nSplitType == WIN_SPLITTYPES.MUNTIN_FILL then
local nMuntinType = EgtGetInfo( nAreaId, WIN_MUNTINFILL_SIDE, 'i')
if nMuntinType == WIN_MUNTINFILL_SIDES.BOTH then
local bSlide = EgtGetInfo( EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*'), WIN_SLIDE_WINDOW, 'b') or false
for i = 1, #vSplitIds do
local nId = EgtCopyGlob( vSplitIds[i], nSplitLayerId)
EgtSetInfo( vSplitIds[i], WIN_REF_MUNTIN, nId)
EgtSetInfo( vSplitIds[i], WIN_MUNTINFILL_SIDE, WIN_MUNTINFILL_SIDES.IN)
EgtSetInfo( nId, WIN_PROFILETYPE, EgtIf( bSlide, WIN_SLIDE .. '_', '') .. WIN_FILL_SPLIT_OUT)
EgtSetInfo( nId, WIN_MUNTINFILL_SIDE, WIN_MUNTINFILL_SIDES.OUT)
end
else
for i = 1, #vSplitIds do
EgtSetInfo( vSplitIds[i], WIN_MUNTINFILL_SIDE, nMuntinType)
end
end
end
-- SASH
elseif nAreaType == WIN_AREATYPES.SASH then
local nBaseOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_AREAOUTLINE)
local vOutlines = CalculateSashOutline( nAreaId, nBaseOutlineLayerId, nOutlineLayerId)
CalcOutlineDimensions( vOutlines, nAreaId)
-- ne verifico validità
VerifySashOutlines( vOutlines, nAreaId)
-- identifico la forma
IdentifySashShape( nAreaId, nOutlineLayerId)
-- disegno apertura
DrawOpening( nAreaId)
-- FILL
elseif nAreaType == WIN_AREATYPES.FILL then
CalculateFillOutline( nAreaId, nOutlineLayerId)
end
end
---------------------------------------------------------------------
local function CalculateFrameAreasOutlines( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
-- se area di telaio o split calcolo l'outline
if nAreaType == WIN_AREATYPES.FRAME or nAreaType == WIN_AREATYPES.SPLIT then
CalculateOutlineFromAreaOutline( nAreaId)
-- se area anta o fill devo interrompere la ricerca
elseif nAreaType == WIN_AREATYPES.SASH or nAreaType == WIN_AREATYPES.FILL then
return
end
local vChildrenAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
for i = 1, #vChildrenAreas do
CalculateFrameAreasOutlines( vChildrenAreas[i])
end
end
---------------------------------------------------------------------
local function CalculateResidualAreaOutlines( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH or nAreaType == WIN_AREATYPES.FILL then
CalculateOutlineFromAreaOutline( nAreaId)
elseif nAreaType == WIN_AREATYPES.SPLIT then
-- devo calcolarla solo se non è già stato fatto ( quindi non è uno split che dipende dal telaio)
local nOutlineLayer = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
if not nOutlineLayer then
CalculateOutlineFromAreaOutline( nAreaId)
end
end
local vChildAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
for i = 1, #vChildAreas do
CalculateResidualAreaOutlines( vChildAreas[i])
end
end
---------------------------------------------------------------------
local function CalculateAreaOutline( nAreaId)
-- calcolo l'outline del telaio e di tutti gli split ad esso riferiti
CalculateFrameAreasOutlines( nAreaId)
-- se cambio profilo lo spostamento degli split per le misure luce/esterno anta potrebbe aver modificato la tipologia dei figli delle curve del telaio e di altri split,
-- quindi la aggiorno in base agli outlines appena calcolati ( e non più rispetto ai base outlines)
local bChangeProfile = EgtGetInfo( nAreaId, WIN_MIXED_WINDOW, 'b')
if bChangeProfile then
UpdateSplitTypes( nAreaId)
UpdateFrameTypes( nAreaId)
end
-- calcolo gli outlines delle ante, dei vetri e degli split in essi contenuti
CalculateResidualAreaOutlines( nAreaId)
end
---------------------------------------------------------------------
-- funzione che cicla ricorsivamente su aree e sottoaree per assegnare i profili all'area
local function SetAreaProfiles( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.FRAME or nAreaType == WIN_AREATYPES.SASH then
-- recupero i profili dalle curve di outline
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlines = EgtGetAllInGroup( nOutlineLayerId)
local sAreaName = EgtIf( nAreaType == WIN_AREATYPES.FRAME, WIN_FRAME, WIN_SASH)
local vProfiles = {}
for i = 1, #vOutlines do
vProfiles[i] = sAreaName .. '_' .. EgtGetInfo( vOutlines[i], WIN_PROFILETYPE)
end
EgtSetInfo( nAreaId, WIN_AREA_PROFILES, vProfiles)
elseif nAreaType == WIN_AREATYPES.SPLIT then
local nSplitType = EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i')
if nSplitType ~= WIN_SPLITTYPES.FRENCH then
-- recupero area parent per capire se dentro telaio, anta o vetro
local nParentAreaId = EgtGetParent( nAreaId)
local nParentAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i')
while nParentAreaType == WIN_AREATYPES.SPLIT or nParentAreaType == WIN_AREATYPES.NULL do
nParentAreaId = EgtGetParent( nParentAreaId)
nParentAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i')
end
local sAreaName
if nParentAreaType == WIN_AREATYPES.FRAME then
sAreaName = WIN_FRAME
elseif nParentAreaType == WIN_AREATYPES.SASH then
sAreaName = WIN_SASH
else
sAreaName = WIN_FILL
end
local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT)
local vSplitIds = EgtGetAllInGroup( nSplitLayerId)
local bGridSplit = EgtGetInfo( nAreaId, WIN_GRID_SPLIT, 'b') or false
if bGridSplit then
-- recupero i profili distinguendoli per ordine di split
local tabProfiles = {}
for i = 1, #vSplitIds do
if not EgtExistsInfo( vSplitIds[i], WIN_REF_MUNTIN) then
local nOrder = EgtGetInfo( vSplitIds[i], WIN_GRIDSPLIT_ORDER, 'i')
local sProfile = sAreaName .. '_' .. EgtGetInfo( vSplitIds[i], WIN_PROFILETYPE)
if tabProfiles[nOrder+1] then
table.insert( tabProfiles[nOrder+1], sProfile)
else
tabProfiles[nOrder+1] = { sProfile}
end
end
end
-- salvo in info separate
for i = 1, #tabProfiles do
EgtSetInfo( nAreaId, WIN_AREA_PROFILES .. tostring( i-1), tabProfiles[i])
end
else
-- recupero tutti i profili degli split
-- se ha info WIN_REF_MUNTIN significa che split è inglesina sia interna che esterna, non ha senso considerarla due volte anche se sono due outlines distinti perchè
-- lo split che la definisce è uno solo
local vProfiles = {}
for i = 1, #vSplitIds do
if not EgtExistsInfo( vSplitIds[i], WIN_REF_MUNTIN) then
table.insert( vProfiles, sAreaName .. '_' .. EgtGetInfo( vSplitIds[i], WIN_PROFILETYPE))
end
end
EgtSetInfo( nAreaId, WIN_AREA_PROFILES, vProfiles)
end
end
end
-- analizzo le sottoaree
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
SetAreaProfiles( nChildAreaId)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
----------------------------------------------------------------------------------
------------------------------ CALCOLO JOINTS ----------------------------------
----------------------------------------------------------------------------------
-- funzione che dato il tipo di giunzione e di pezzo ( orizzontale o verticale) restituisce se è corto, lungo o angolato
local function CalcPartJoint( nJointType, bHorizontal)
if nJointType == WIN_JNT.ANGLED then
return WIN_PART_JNT.ANGLED
elseif nJointType == WIN_JNT.FULL_H then
if bHorizontal then
return WIN_PART_JNT.FULL
else
return WIN_PART_JNT.SHORT
end
elseif nJointType == WIN_JNT.FULL_V then
if bHorizontal then
return WIN_PART_JNT.SHORT
else
return WIN_PART_JNT.FULL
end
end
end
---------------------------------------------------------------------
local function CalcOutlineStartJoint( nOutlineId, nPrevOutlineId, vJoints)
local nStartJoint
if EgtGetName( nOutlineId) == WIN_BOTTOM then
nStartJoint = CalcPartJoint( vJoints[1], true)
elseif EgtGetName( nOutlineId) == WIN_RIGHT then
nStartJoint = CalcPartJoint( vJoints[2], false)
elseif EgtGetName( nOutlineId) == WIN_TOP then
nStartJoint = CalcPartJoint( vJoints[3], true)
-- correzione per caso a triangolo : se l'outline vicino è di tipo bottom, il corrente deve essere trattato come un pezzo verticale
if EgtGetName( nPrevOutlineId) == WIN_BOTTOM then
nStartJoint = CalcPartJoint( vJoints[2], false)
end
elseif EgtGetName( nOutlineId) == WIN_LEFT then
nStartJoint = CalcPartJoint( vJoints[4] or vJoints[3], false) -- ( vJoints[3] per gestire caso a triangolo)
end
-- eventuali correzioni :
-- a) forzatura a bisettrice se elementi in tangenza ( entro 6°) o dello stesso tipo
if nStartJoint ~= WIN_PART_JNT.ANGLED then
if EgtEV( nPrevOutlineId) * EgtSV( nOutlineId) > s_dAngledCos or EgtGetName( nOutlineId) == EgtGetName( nPrevOutlineId) then
nStartJoint = WIN_PART_JNT.ANGLED
end
end
-- b) forzatura a short se incontro con soglia
if EgtGetInfo( nPrevOutlineId, WIN_THRESHOLD, 'b') then
nStartJoint = WIN_PART_JNT.SHORT
end
-- c) forzatura ad angled se cambio profilo sul punto di incontro
local nProfileChange = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'i')
local nProfileChangeP = EgtGetInfo( nPrevOutlineId, WIN_PRF_CHANGE, 'i')
if nProfileChange == WIN_PRF_CHANGE_TYPES.IN and nProfileChangeP == WIN_PRF_CHANGE_TYPES.IN then
-- per vedere se il cambio profilo è sul punto di incontro verifico se hanno uno split con cambio profilo sull'estremo in comune
local vSplits1 = EgtGetInfo( nOutlineId, WIN_CHILD_PRFCHANGE_SPLIT, 'vi')
local vSplits2 = EgtGetInfo( nPrevOutlineId, WIN_CHILD_PRFCHANGE_SPLIT, 'vi')
for i = 1, #vSplits1 do
for j = 1, #vSplits2 do
if vSplits1[i] == vSplits2[j] then
return WIN_PART_JNT.ANGLED
end
end
end
end
return nStartJoint
end
---------------------------------------------------------------------
local function CalcOutlineEndJoint( nOutlineId, nNextOutlineId, vJoints)
local nEndJoint
if EgtGetName( nOutlineId) == WIN_BOTTOM then
nEndJoint = CalcPartJoint( vJoints[2], true)
elseif EgtGetName( nOutlineId) == WIN_RIGHT then
nEndJoint = CalcPartJoint( vJoints[3], false)
elseif EgtGetName( nOutlineId) == WIN_TOP then
nEndJoint = CalcPartJoint( vJoints[4] or vJoints[3], true) -- ( vJoints[3] per gestire caso a triangolo)
-- correzione per caso a triangolo : se l'outline vicino è di tipo bottom, il corrente deve essere trattato come un pezzo verticale
if EgtGetName( nNextOutlineId) == WIN_BOTTOM then
nEndJoint = CalcPartJoint( vJoints[1], false)
end
elseif EgtGetName( nOutlineId) == WIN_LEFT then
nEndJoint = CalcPartJoint( vJoints[1], false)
end
-- eventuali correzioni :
-- a) forzatura a bisettrice se elementi in tangenza ( entro 6°) o dello stesso tipo
if nEndJoint ~= WIN_PART_JNT.ANGLED then
if EgtEV( nOutlineId) * EgtSV( nNextOutlineId) > s_dAngledCos or EgtGetName( nOutlineId) == EgtGetName( nNextOutlineId) then
nEndJoint = WIN_PART_JNT.ANGLED
end
end
-- b) forzatura a short se incontro con soglia
if EgtGetInfo( nNextOutlineId, WIN_THRESHOLD, 'b') then
nEndJoint = WIN_PART_JNT.SHORT
end
-- c) forzatura ad angled se cambio profilo sul punto di incontro
local nProfileChange = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'i')
local nProfileChangeN = EgtGetInfo( nNextOutlineId, WIN_PRF_CHANGE, 'i')
if nProfileChange == WIN_PRF_CHANGE_TYPES.IN and nProfileChangeN == WIN_PRF_CHANGE_TYPES.IN then
-- per vedere se il cambio profilo è sul punto di incontro verifico se hanno uno split con cambio profilo sull'estremo in comune
local vSplits1 = EgtGetInfo( nOutlineId, WIN_CHILD_PRFCHANGE_SPLIT, 'vi')
local vSplits2 = EgtGetInfo( nNextOutlineId, WIN_CHILD_PRFCHANGE_SPLIT, 'vi')
for i = 1, #vSplits1 do
for j = 1, #vSplits2 do
if vSplits1[i] == vSplits2[j] then
return WIN_PART_JNT.ANGLED
end
end
end
end
return nEndJoint
end
---------------------------------------------------------------------
local function GetOutlineJoints( vOutlineIds, nAreaId)
local vJoints = EgtGetInfo( nAreaId, WIN_JOINTS, 'vi')
for i = 1, #vOutlineIds do
local nPrevIdx = EgtIf( i == 1, #vOutlineIds, i - 1)
local nNextIdx = EgtIf( i == #vOutlineIds, 1, i + 1)
local nStartJoint = CalcOutlineStartJoint( vOutlineIds[i], vOutlineIds[nPrevIdx], vJoints)
local nEndJoint = CalcOutlineEndJoint( vOutlineIds[i], vOutlineIds[nNextIdx], vJoints)
EgtSetInfo( vOutlineIds[i], WIN_STARTJOINT, nStartJoint)
EgtSetInfo( vOutlineIds[i], WIN_ENDJOINT, nEndJoint)
end
end
----------------------------------------------------------------------------------
------------------------------ CREAZIONE PEZZI ---------------------------------
----------------------------------------------------------------------------------
-- funzione che stabilisce il nome del pezzo
local function CalcPartName( nAreaId, nAreaType)
local sName = ''
if nAreaType == WIN_AREATYPES.FRAME then
sName = WIN_FRAME
EgtSetInfo( nAreaId, WIN_AREA_NAME, sName)
elseif nAreaType == WIN_AREATYPES.SASH then
s_nSashNbr = s_nSashNbr + 1
sName = WIN_SASH .. '_'.. tostring( s_nSashNbr)
EgtSetInfo( nAreaId, WIN_AREA_NAME, sName)
else
-- per split o riempimento devo ricavare il nome del parent che lo contiene
local nParentId = EgtGetParent( nAreaId)
local nParentType = EgtGetInfo( nParentId, WIN_AREATYPE, 'i')
while nParentType == WIN_AREATYPES.SPLIT or nParentType == WIN_AREATYPES.NULL do
nParentId = EgtGetParent( nParentId)
nParentType = EgtGetInfo( nParentId, WIN_AREATYPE, 'i')
end
sName = EgtGetInfo( nParentId, WIN_AREA_NAME)
if nAreaType == WIN_AREATYPES.FILL then
sName = sName .. '_' .. WIN_FILL
EgtSetInfo( nAreaId, WIN_AREA_NAME, sName)
end
end
return sName
end
---------------------------------------------------------------------
local function CreateOutlinePart( nOutlineId, sName, dDim, nBottomRail)
-- se soglia ignoro
local bThreshold = EgtGetInfo( nOutlineId or GDB_ID.NULL, WIN_THRESHOLD, 'b') or false
if bThreshold then
return
end
-- creo pezzo
local nPartId = EgtGroup( GDB_ID.ROOT)
-- creo riferimenti tra pezzo e outline
EgtSetInfo( nPartId, WIN_REF_OUTLINE, nOutlineId)
if nBottomRail then
-- aggiorno i riferimenti del bottomrail
AddInfo( nOutlineId, WIN_REF_BOTTOMRAIL_PART, nPartId)
EgtSetInfo( nPartId, WIN_PART_TYPE, WIN_PART_TYPES.BOTTOMRAIL)
EgtSetInfo( nPartId, WIN_BOTTOMRAIL, nBottomRail)
else
EgtSetInfo( nOutlineId, WIN_REF_PART, nPartId)
EgtSetInfo( nPartId, WIN_PART_TYPE, WIN_PART_TYPES.STD)
end
-- imposto nome
local sOutlineName = EgtIf( nBottomRail, WIN_BOTTOMRAIL .. '_' .. tostring( nBottomRail), EgtGetName( nOutlineId))
local sPartName = sName .. '_' .. sOutlineName
EgtSetName( nPartId, sPartName)
-- imposto colore
if sOutlineName == WIN_BOTTOM or sOutlineName == WIN_TOP or nBottomRail then
EgtSetColor( nPartId, Color3d( 204, 102, 0))
elseif sOutlineName == WIN_RIGHT or sOutlineName == WIN_LEFT then
EgtSetColor( nPartId, Color3d( 251, 128, 4))
else
EgtSetColor( nPartId, Color3d( 255, 159, 57))
end
-- creo il profilo associato al pezzo con la dimensione opportuna
CreatePartProfile( nPartId, nOutlineId, dDim, nBottomRail)
return nPartId
end
---------------------------------------------------------------------
local function CreatePartsFromOutlines( vOutlines, nAreaId, sName)
-- calcolo le giunzioni
GetOutlineJoints( vOutlines, nAreaId)
-- creo i pezzi per ogni curva
for i = 1, #vOutlines do
local dDim = EgtGetInfo( vOutlines[i], WIN_PART_DIM, 'd')
CreateOutlinePart( vOutlines[i], sName, dDim)
if EgtGetName( vOutlines[i]) == WIN_BOTTOM then
local nBottomRail = EgtGetInfo( vOutlines[i], WIN_BOTTOMRAIL, 'i') or 0
if nBottomRail > 0 then
local vBottomRailDim = EgtGetInfo( vOutlines[i], WIN_BOTTOMRAIL .. WIN_PART_DIM, 'vd')
for j = 1, nBottomRail do
CreateOutlinePart( vOutlines[i], sName, vBottomRailDim[j], j)
end
end
end
end
end
---------------------------------------------------------------------
local function CreateFillPartFromArea( nAreaId, sName)
local nPartId = EgtGroup( GDB_ID.ROOT)
-- inserisco riferimento alla sua area
EgtSetInfo( nPartId, WIN_AREA, nAreaId)
-- imposto nome del pezzo
EgtSetName( nPartId, sName)
EgtSetInfo( nPartId, WIN_PART_TYPE, WIN_PART_TYPES.FILL)
-- imposto colore e tipologia
local nFillType = EgtGetInfo( nAreaId, WIN_FILLTYPE, 'i')
if nFillType == WIN_FILLTYPES.GLASS then
EgtSetColor( nPartId, Color3d( 71, 161, 255))
EgtSetAlpha( nPartId, 30)
EgtSetInfo( nPartId, WIN_FILLTYPE, WIN_GLASS)
elseif nFillType == WIN_FILLTYPES.WOOD then
EgtSetColor( nPartId, Color3d( 194, 148, 103))
EgtSetInfo( nPartId, WIN_FILLTYPE, WIN_WOOD)
end
return nPartId
end
---------------------------------------------------------------------
-- funzione che crea ricorsivamente i pezzi con i relativi profili
local function CreateAreaParts( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
local sName = CalcPartName( nAreaId, nAreaType)
-- FRAME
if nAreaType == WIN_AREATYPES.FRAME then
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlines = EgtGetAllInGroup( nOutlineLayerId)
CreatePartsFromOutlines( vOutlines, nAreaId, sName)
-- SPLIT
elseif nAreaType == WIN_AREATYPES.SPLIT then
if EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i') ~= WIN_SPLITTYPES.FRENCH then
local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT)
local vSplits = EgtGetAllInGroup( nSplitLayerId)
for i = 1, #vSplits do
local dDim = EgtGetInfo( vSplits[i], WIN_PART_DIM, 'd')
CreateOutlinePart( vSplits[i], sName, dDim)
end
end
-- SASH
elseif nAreaType == WIN_AREATYPES.SASH then
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlines = EgtGetAllInGroup( nOutlineLayerId)
CreatePartsFromOutlines( vOutlines, nAreaId, sName)
-- FILL
elseif nAreaType == WIN_AREATYPES.FILL then
CreateFillPartFromArea( nAreaId, sName)
end
-- analizzo le sottoaree
local vAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
for i = 1, #vAreas do
CreateAreaParts( vAreas[i])
end
end
----------------------------------------------------------------------------------
------------------------ PREV & NEXT OUTLINES ----------------------------------
----------------------------------------------------------------------------------
local function TestSplitTrimOutlines( nOutlineId, nSplitType, nTrimOutline, tabOutlines, nMainProfile, b3Profile, nGrpTmp, bPrevOrNext)
local vTrimOutlines = {}
-- 1) recupero le curve da testare :
-- a) curva individuata dall'intersezione dello split con l'outline
local vTestOutlines = { tabOutlines[nTrimOutline]}
-- b) curve vicine a quella individuata dall'intersezione che interferiscono con lo split ( guardando interferenza grossolana dei box dei pezzi)
-- creo il box della curva di split
local nOutlineCopyId = EgtCopyGlob( nOutlineId, nGrpTmp)
if bPrevOrNext then
EgtTrimCurveEndAtParam( nOutlineCopyId, 0.5)
else
EgtTrimCurveStartAtParam( nOutlineCopyId, 0.5)
end
local b3Split, frSplit = CreateTestBoxFromOutline( nOutlineCopyId, nMainProfile, b3Profile)
-- curve precedenti
local nTestCurve = EgtGetPrev( nTrimOutline) or EgtGetLastInGroup( EgtGetParent( nTrimOutline))
local bInters = true
while bInters and nTestCurve ~= nTrimOutline do
-- verifico interferenza tra i box
if Overlaps( tabOutlines[nTestCurve].b3Box, tabOutlines[nTestCurve].frRef, b3Split, frSplit) then
table.insert( vTestOutlines, 1, tabOutlines[nTestCurve])
nTestCurve = EgtGetPrev( nTestCurve) or EgtGetLastInGroup( EgtGetParent( nTestCurve))
else
bInters = false
end
end
-- curve successive ( solo se non ho già considerato tutto il loop, potrebbe capitare a causa di archi il cui box non è ottimizzato con un frame)
if nTestCurve ~= nTrimOutline then
nTestCurve = EgtGetNext( nTrimOutline) or EgtGetFirstInGroup( EgtGetParent( nTrimOutline))
bInters = true
while bInters and nTestCurve ~= nTrimOutline do
-- verifico interferenza tra i box
if Overlaps( tabOutlines[nTestCurve].b3Box, tabOutlines[nTestCurve].frRef, b3Split, frSplit) then
table.insert( vTestOutlines, tabOutlines[nTestCurve])
nTestCurve = EgtGetNext( nTestCurve) or EgtGetFirstInGroup( EgtGetParent( nTestCurve))
else
bInters = false
end
end
end
if #vTestOutlines == 1 then
return { vTestOutlines[1].nId}
end
-- 2) testo le curve controllando intersezione tra le superfici dei pezzi
-- creo il solido principale
local dExtraLen = b3Profile:getDimX()
local nMainSurf
if nSplitType == WIN_SPLITTYPES.MIXED then
-- nel caso di profilo split mixed non è definita una sezione quindi devo costruirla recuperando i semiprofili in in base alla tipologia di figli sull'estremo
local nSemiProfile1 = EgtGetFirstNameInGroup( nMainProfile, WIN_IN .. '1')
if not nSemiProfile1 then
local nChildrenType1 = EgtGetInfo( nOutlineId, EgtIf( bPrevOrNext, WIN_MIXED_START_CHILDREN, WIN_MIXED_END_CHILDREN) .. '1', 'i')
local sSemiProfileName = EgtIf( nChildrenType1 == WIN_CHILDREN_TYPES.SASH, WIN_SASH, WIN_FILL) .. WIN_IN .. '1'
nSemiProfile1 = EgtGetFirstNameInGroup( nMainProfile, sSemiProfileName)
end
local nSemiProfile2 = EgtGetFirstNameInGroup( nMainProfile, WIN_IN .. '2')
if not nSemiProfile2 then
local nChildrenType2 = EgtGetInfo( nOutlineId, EgtIf( bPrevOrNext, WIN_MIXED_START_CHILDREN, WIN_MIXED_END_CHILDREN) .. '2', 'i')
local sSemiProfileName = EgtIf( nChildrenType2 == WIN_CHILDREN_TYPES.SASH, WIN_SASH, WIN_FILL) .. WIN_IN .. '2'
nSemiProfile2 = EgtGetFirstNameInGroup( nMainProfile, sSemiProfileName)
end
local nSection = EgtCurveCompo( nGrpTmp, nSemiProfile1, false)
EgtAddCurveCompoLine( nSection, EgtSP( nSemiProfile2, GDB_ID.ROOT), GDB_RT.GLOB)
EgtAddCurveCompoCurve( nSection, nSemiProfile2, false)
EgtCloseCurveCompo( nSection)
nMainSurf = CreateProfileSurfById( nOutlineId, nMainProfile, nSection, 4 * dExtraLen, nGrpTmp)
else
nMainSurf = CreateProfileSurf( nOutlineId, nMainProfile, WIN_SECTION, 4 * dExtraLen, nGrpTmp)
end
EgtCutSurfTmPlane( nMainSurf, EgtMP( nOutlineId), EgtIf( bPrevOrNext, 1, -1) * EgtSV( nOutlineId))
-- recupero profili delle curve di test per i conti
local vProfiles = {}
local vsCtrIn = {}
for i = 1, #vTestOutlines do
vProfiles[i] = vTestOutlines[i].nProfile
vsCtrIn[i] = GetProfileCtrIn( vTestOutlines[i].nId, nOutlineId, vProfiles[i], bPrevOrNext)
end
-- testo le curve
for i = 1, #vTestOutlines do
-- creo la superficie di test limitandola con le sue vicine
local nTestSurf = CreateProfileSurf( abs( vTestOutlines[i].nId), vProfiles[i], vsCtrIn[i], 4 * dExtraLen, nGrpTmp)
if i > 1 then
if AreSameVectorApprox( EgtEV( abs( vTestOutlines[i-1].nId)), EgtSV( abs( vTestOutlines[i].nId))) then
EgtCutSurfTmPlane( nTestSurf, EgtEP( abs( vTestOutlines[i-1].nId)), - EgtEV( abs( vTestOutlines[i-1].nId)), false)
else
local nTrimSurf = CreateProfileSurf( abs( vTestOutlines[i-1].nId), vProfiles[i-1], WIN_OFST .. vsCtrIn[i-1], 4 * dExtraLen, nGrpTmp)
EgtSurfTmCut( nTestSurf, nTrimSurf, true, false)
end
end
if i < #vTestOutlines then
if AreSameVectorApprox( EgtEV( abs( vTestOutlines[i].nId)), EgtSV( abs( vTestOutlines[i+1].nId))) then
EgtCutSurfTmPlane( nTestSurf, EgtEP( abs( vTestOutlines[i].nId)), EgtEV( abs( vTestOutlines[i].nId)), false)
else
local nTrimSurf = CreateProfileSurf( abs( vTestOutlines[i+1].nId), vProfiles[i+1], WIN_OFST .. vsCtrIn[i+1], 4 * dExtraLen, nGrpTmp)
EgtSurfTmCut( nTestSurf, nTrimSurf, true, false)
end
end
-- calcolo intersezione con il solido : se c'è intersezione è una vera curva di trim, altrimenti non va considerata
local nId, _, nCrvCnt = EgtSurfTmSurfTmInters( nMainSurf, nTestSurf, nGrpTmp)
if nId and nCrvCnt > 0 then
table.insert( vTrimOutlines, vTestOutlines[i].nId)
end
end
return vTrimOutlines
end
-------------------------------------------------------------------
-- funzione che recupera gli outline precedenti e successivi degli split
local function GetSplitsPrevNextOutline( vSplitIds, vOutlineIds)
local nGrpTmp = EgtGroup( GDB_ID.ROOT)
-- ad ogni outline dell'area di split associo l'outline non virtuale corrispondente ( per rendere più solidi i conti successivi)
local tabOutlines = {}
for i = 1, #vOutlineIds do
local nId = GetNonVirtualOutline( vOutlineIds[i])
-- calcolo il suo box
local nProfileId = GetOutlineProfileId( abs( nId))
local b3Profile = GetProfileLocalBox( nProfileId)
local b3Box, frRef = CreateTestBoxFromOutline( abs( nId), nProfileId, b3Profile)
tabOutlines[vOutlineIds[i]] = { nId = nId, frRef = frRef, b3Box = b3Box, nProfile = nProfileId}
end
-- per ogni split controllo la validità delle curve prev/next trovate dall'intersezione degli outlines e la validità di eventuali curve vicine verificando l'interferenza tra i profili
for i = 1, #vSplitIds do
local nMainProfile = GetOutlineProfileId( vSplitIds[i])
local b3Profile = GetProfileLocalBox( nMainProfile)
local nSplitType = EgtGetInfo( vSplitIds[i], WIN_SPLITTYPE, 'i')
-- prev
if not EgtExistsInfo( vSplitIds[i], WIN_PREV_OUTLINES) then
local nPrevOutlineId = EgtGetInfo( vSplitIds[i], WIN_SPLIT_STARTINTERS, 'i')
local vPrevOutlineIds = TestSplitTrimOutlines( vSplitIds[i], nSplitType, nPrevOutlineId, tabOutlines, nMainProfile, b3Profile, nGrpTmp, true)
EgtSetInfo( vSplitIds[i], WIN_PREV_OUTLINES, vPrevOutlineIds)
-- setto tutte le giunzioni a short
local vStartJoints = {}
for j = 1, #vPrevOutlineIds do
vStartJoints[j] = WIN_PART_JNT.SHORT
end
EgtSetInfo( vSplitIds[i], WIN_STARTJOINT, vStartJoints)
end
-- next
if not EgtExistsInfo( vSplitIds[i], WIN_NEXT_OUTLINES) then
local nNextOutlineId = EgtGetInfo( vSplitIds[i], WIN_SPLIT_ENDINTERS, 'i')
local vNextOutlineIds = TestSplitTrimOutlines( vSplitIds[i], nSplitType, nNextOutlineId, tabOutlines, nMainProfile, b3Profile, nGrpTmp, false)
EgtSetInfo( vSplitIds[i], WIN_NEXT_OUTLINES, vNextOutlineIds)
local vEndJoints = {}
for j = 1, #vNextOutlineIds do
vEndJoints[j] = WIN_PART_JNT.SHORT
end
EgtSetInfo( vSplitIds[i], WIN_ENDJOINT, vEndJoints)
end
end
EgtErase( nGrpTmp)
end
---------------------------------------------------------------------
local function GetSashPrevNextOutlines( nAreaId)
local vJoints = EgtGetInfo( nAreaId, WIN_JOINTS, 'vi')
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlineIds = EgtGetAllInGroup( nOutlineLayerId)
for i = 1, #vOutlineIds do
if EgtGetInfo( vOutlineIds[i], WIN_EXTRA_CRV, 'b') then
-- non ha bisogno di prev/next perchè il pezzo viene ignorato
else
-- a) prev
local nPrevId = EgtGetPrev( vOutlineIds[i]) or EgtGetLastInGroup( nOutlineLayerId)
local bExtra = EgtGetInfo( nPrevId, WIN_EXTRA_CRV, 'b') or false
local bSpecial = EgtGetInfo( nPrevId, WIN_SPECIAL_CRV, 'b') or false
if not bExtra and not bSpecial then
-- se il precedente è un pezzo standard il prev è solamente lui e il joint calcolato è già corretto
EgtSetInfo( vOutlineIds[i], WIN_PREV_OUTLINES, nPrevId)
else
-- recupero tutti i precedenti fino a quando non trovo un elemento standard
local vPrevIds = {}
while bExtra or bSpecial do
table.insert( vPrevIds, 1, nPrevId)
nPrevId = EgtGetPrev( nPrevId) or EgtGetLastInGroup( nOutlineLayerId)
bExtra = EgtGetInfo( nPrevId, WIN_EXTRA_CRV, 'b') or false
bSpecial = EgtGetInfo( nPrevId, WIN_SPECIAL_CRV, 'b') or false
end
table.insert( vPrevIds, 1, nPrevId)
-- calcolo i joints
local vStartJoints = {}
local nOldId = vOutlineIds[i]
local nOldTgId = vOutlineIds[i]
local bTangChain = true -- indica se l'outline e i primi vicini formano una catena di curve in tangenza
local nJoint -- il primo joint non è quello salvato nelle info della curva ma è da calcolare con la prima curva non extra
for j = #vPrevIds, 1, -1 do
if EgtGetInfo( vPrevIds[j], WIN_EXTRA_CRV, 'b') then
-- con i pezzi extra la giunzione è sempre full perchè il pezzo corrente va trimmato con il loro bordo esterno
vStartJoints[j] = WIN_PART_JNT.FULL
else
if not nJoint then
nJoint = CalcOutlineStartJoint( nOldId, vPrevIds[j], vJoints)
end
if AreSameVectorApprox( EgtEV( vPrevIds[j]), EgtSV( nOldTgId)) then
-- curve in tangenza devono avere la stessa giunzione
vStartJoints[j] = nJoint
else
-- se arrivo dalla catena di primi vicini tangenti devo ricalcolare il joint altrimenti va forzato ad angled
if bTangChain then
nJoint = CalcOutlineStartJoint( nOldId, vPrevIds[j], vJoints)
else
nJoint = WIN_PART_JNT.ANGLED
end
bTangChain = false
vStartJoints[j] = nJoint
end
nOldId = vPrevIds[j]
end
-- gli extra vanno ignorati nel calcolo delle giunzioni ma vanno considerati per il calcolo delle tangenze
nOldTgId = vPrevIds[j]
end
EgtSetInfo( vOutlineIds[i], WIN_PREV_OUTLINES, vPrevIds)
EgtSetInfo( vOutlineIds[i], WIN_STARTJOINT, vStartJoints)
end
-- b) next
local nNextId = EgtGetNext( vOutlineIds[i]) or EgtGetFirstInGroup( nOutlineLayerId)
bExtra = EgtGetInfo( nNextId, WIN_EXTRA_CRV, 'b') or false
bSpecial = EgtGetInfo( nNextId, WIN_SPECIAL_CRV, 'b') or false
if not bExtra and not bSpecial then
-- caso standard
EgtSetInfo( vOutlineIds[i], WIN_NEXT_OUTLINES, nNextId)
else
local vNextIds = {}
while bExtra or bSpecial do
table.insert( vNextIds, nNextId)
nNextId = EgtGetNext( nNextId) or EgtGetFirstInGroup( nOutlineLayerId)
bExtra = EgtGetInfo( nNextId, WIN_EXTRA_CRV, 'b') or false
bSpecial = EgtGetInfo( nNextId, WIN_SPECIAL_CRV, 'b')
end
table.insert( vNextIds, nNextId)
-- calcolo i joints
local vEndJoints = {}
local nOldId = vOutlineIds[i]
local nOldTgId = vOutlineIds[i]
local bTangChain = true
local nJoint
for j = 1, #vNextIds do
-- se extra la giunzione deve essere full
if EgtGetInfo( vNextIds[j], WIN_EXTRA_CRV, 'b') then
vEndJoints[j] = WIN_PART_JNT.FULL
else
if not nJoint then
nJoint = CalcOutlineEndJoint( nOldId, vNextIds[j], vJoints)
end
if AreSameVectorApprox( EgtEV( nOldTgId), EgtSV( vNextIds[j])) then
vEndJoints[j] = nJoint
else
if bTangChain then
nJoint = CalcOutlineEndJoint( nOldId, vNextIds[j], vJoints)
else
nJoint = WIN_PART_JNT.ANGLED
end
bTangChain = false
vEndJoints[j] = nJoint
end
nOldId = vNextIds[j]
end
nOldTgId = vNextIds[j]
end
EgtSetInfo( vOutlineIds[i], WIN_NEXT_OUTLINES, vNextIds)
EgtSetInfo( vOutlineIds[i], WIN_ENDJOINT, vEndJoints)
end
end
end
end
---------------------------------------------------------------------
local function GetAreaPrevNextOutlines( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
-- FRAME
if nAreaType == WIN_AREATYPES.FRAME then
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlines = EgtGetAllInGroup( nOutlineLayerId)
for i = 2, #vOutlines - 1 do
EgtSetInfo( vOutlines[i], WIN_PREV_OUTLINES, vOutlines[i-1])
EgtSetInfo( vOutlines[i], WIN_NEXT_OUTLINES, vOutlines[i+1])
end
-- gestione particolare per primo e ultimo
EgtSetInfo( vOutlines[1], WIN_PREV_OUTLINES, vOutlines[#vOutlines])
EgtSetInfo( vOutlines[1], WIN_NEXT_OUTLINES, vOutlines[2])
EgtSetInfo( vOutlines[#vOutlines], WIN_PREV_OUTLINES, vOutlines[#vOutlines - 1])
EgtSetInfo( vOutlines[#vOutlines], WIN_NEXT_OUTLINES, vOutlines[1])
-- SPLIT
elseif nAreaType == WIN_AREATYPES.SPLIT then
if EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i') ~= WIN_SPLITTYPES.FRENCH then
local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT)
local vSplits = EgtGetAllInGroup( nSplitLayerId)
-- se inglesine da entrambi i lati calcolo prev/next solo per quelle interne, quelle esterne verranno sistemate in base a quelle interne di cui sono copia
local bFillMuntin = false
if EgtGetInfo( vSplits[1], WIN_SPLITTYPE, 'i') == WIN_SPLITTYPES.MUNTIN_FILL and EgtGetInfo( nAreaId, WIN_MUNTINFILL_SIDE, 'i') == WIN_MUNTINFILL_SIDES.BOTH then
bFillMuntin = true
local vInSplits = {}
for i = 1, #vSplits do
local nSide = EgtGetInfo( vSplits[i], WIN_MUNTINFILL_SIDE, 'i')
if nSide == WIN_MUNTINFILL_SIDES.OUT then
break
end
vInSplits[i] = vSplits[i]
end
vSplits = vInSplits
end
-- se split a griglia
local bGrid = EgtGetInfo( nAreaId, WIN_GRID_SPLIT, 'b') or false
if bGrid then
local vVirtualAreas = EgtGetNameInGroup( nAreaId, WIN_VIRTUAL_AREA)
-- raggruppo gli split per ordine
local tabGrid = {}
for i = 1, #vSplits do
local nOrder = EgtGetInfo( vSplits[i], WIN_GRIDSPLIT_ORDER, 'i')
if tabGrid[nOrder] then
table.insert( tabGrid[nOrder], vSplits[i])
else
tabGrid[nOrder] = { vSplits[i]}
end
end
for i = 0, #tabGrid do
local nRefAreaId = EgtIf( i == 0, nAreaId, vVirtualAreas[i])
local nOutlineLayerId = EgtGetFirstNameInGroup( nRefAreaId, WIN_OUTLINE)
local vOutlineIds = EgtGetAllInGroup( nOutlineLayerId)
GetSplitsPrevNextOutline( tabGrid[i], vOutlineIds)
end
else
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
GetSplitsPrevNextOutline( vSplits, EgtGetAllInGroup( nOutlineLayerId))
end
-- aggiorno eventuali inglesine out
if bFillMuntin then
for i = 1, #vSplits do
local nOutSplit = EgtGetInfo( vSplits[i], WIN_REF_MUNTIN, 'i')
-- verifico se devo aggiornare i prev/next ( caso di inglesina contro inglesina)
local vPrevOutlines = EgtGetInfo( vSplits[i], WIN_PREV_OUTLINES, 'vi')
for j = 1, #vPrevOutlines do
local nRef = EgtGetInfo( abs( vPrevOutlines[j]), WIN_REF_MUNTIN, 'i')
if nRef then
vPrevOutlines[j] = EgtIf( vPrevOutlines[j] > 0, nRef, - nRef)
end
end
local vNextOutlines = EgtGetInfo( vSplits[i], WIN_NEXT_OUTLINES, 'vi')
for j = 1, #vNextOutlines do
local nRef = EgtGetInfo( abs( vNextOutlines[j]), WIN_REF_MUNTIN, 'i')
if nRef then
vNextOutlines[j] = EgtIf( vNextOutlines[j] > 0, nRef, - nRef)
end
end
EgtSetInfo( nOutSplit, WIN_PREV_OUTLINES, vPrevOutlines)
EgtSetInfo( nOutSplit, WIN_NEXT_OUTLINES, vNextOutlines)
CopyInfo( nOutSplit, vSplits[i], WIN_STARTJOINT)
CopyInfo( nOutSplit, vSplits[i], WIN_ENDJOINT)
end
end
end
-- SASH
elseif nAreaType == WIN_AREATYPES.SASH then
GetSashPrevNextOutlines( nAreaId)
end
-- analizzo le sottaree
local vAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
for i = 1, #vAreas do
GetAreaPrevNextOutlines( vAreas[i])
end
end
----------------------------------------------------------------------------------
-------------------------------- GEO -------------------------------------------
----------------------------------------------------------------------------------
-- funzione simile a CalcIntersectionRegion ma con considerazioni speciali per le curve del geo ( e.g. gestione bisettori, curve doppie)
local function CalcGeoRegion( vCrvs, nGrp)
local nSurfId
local dExtraLen = 10000
-- gruppo temporaneo per i conti
local nGrpTmp = EgtGroup( nGrp)
EgtSetStatus( nGrpTmp, GDB_ST.OFF)
-- a) costruisco i semipiani e identifico le curve con gestione speciale
local vSemiPlanes = {}
local tArcs = {}
local vBisectors = {}
for i = 1, #vCrvs do
-- se linea costruisco il semipiano corrispondente
if EgtGetType( vCrvs[i]) == GDB_TY.CRV_LINE then
local vtDir = EgtSV( vCrvs[i])
local vtOrtho = Vector3d( vtDir)
vtOrtho:rotate( Z_AX(), 90)
local nSemiPlaneId = EgtSurfFrRectangle( nGrpTmp, ORIG(), Point3d( EgtCurveLength( vCrvs[i]) + 2 * dExtraLen, dExtraLen, 0))
local frRect = Frame3d( EgtSP( vCrvs[i]) - vtDir * dExtraLen, vtDir, vtOrtho, Z_AX())
EgtTransform( nSemiPlaneId, frRect)
table.insert( vSemiPlanes, nSemiPlaneId)
-- se arco calcolo estensione verificando se la curva è doppia
elseif EgtGetType( vCrvs[i]) == GDB_TY.CRV_ARC then
local nCrvId = CreateCurveExtension( vCrvs[i], nGrpTmp)
local bFound = false
local nRefOutline = EgtGetInfo( vCrvs[i], WIN_REF_OUTLINE, 'i')
if nRefOutline then
for j = 1, #tArcs do
if tArcs[j].nRefOutline == nRefOutline then
-- taglio le due estensioni e le unisco nel loro punto centrale
local ptM = EgtMP( nRefOutline)
local _, _, dPar1 = EgtPointCurveDist( ptM, tArcs[j].nCrvId)
local _, _, dPar2 = EgtPointCurveDist( ptM, nCrvId)
EgtTrimCurveStartAtParam( nCrvId, dPar2)
EgtTrimCurveEndAtParam( tArcs[j].nCrvId, dPar1)
local nNewExt = EgtCurveCompo( nGrpTmp, nCrvId)
EgtAddCurveCompoLine( nNewExt, EgtSP( tArcs[j].nCrvId))
EgtAddCurveCompoCurve( nNewExt, tArcs[j].nCrvId)
tArcs[j].nCrvId = nNewExt
table.insert( tArcs[j].vOrigId, vCrvs[i])
bFound = true
break
end
end
end
if not bFound then
table.insert( tArcs, { nCrvId = nCrvId, vOrigId = { vCrvs[i]}, nRefOutline = nRefOutline, dRad = EgtArcRadius( vCrvs[i])})
end
-- se composita è bisettore con gestione speciale
else
local nCrvId = EgtCopyGlob( vCrvs[i], nGrpTmp)
table.insert( vBisectors, nCrvId)
end
end
-- b) calcolo la regione definita dai semipiani
for i = 2, #vSemiPlanes do
EgtSurfFrIntersect( vSemiPlanes[1], vSemiPlanes[i])
EgtErase( vSemiPlanes[i])
end
if EgtSurfFrChunkCount( vSemiPlanes[1]) == 0 then
return
end
nSurfId = vSemiPlanes[1]
-- c) se presenti archi, calcolo il loro contributo alla regione
if #tArcs > 0 then
local nCrvBorder = EgtExtractSurfFrChunkLoops( nSurfId, 0, nGrpTmp)
-- riordino per raggio decrescente ( per gestire prima quelle più grandi che potrebbero contenere le altre)
table.sort( tArcs, function ( a, b) return a.dRad > b.dRad end)
for i = 1, #tArcs do
-- limito la curva estesa alla regione
local nSurfTrim = EgtSurfFlatRegion( nGrpTmp, nCrvBorder)
local nCrv, nCnt = EgtTrimCurveWithRegion( tArcs[i].nCrvId, nSurfTrim, true, false)
-- se errore lo ignoro
if not nCrv then
nCnt = 0
end
if nCnt > 0 then
-- unisco tratto iniziale e finale se consecutivi
if nCnt > 1 and AreSamePointApprox( EgtSP( nCrv), EgtEP( nCrv + nCnt - 1)) then
if EgtGetType( nCrv) == GDB_TY.CRV_ARC then
EgtModifyCurveStartPoint( nCrv, EgtSP( nCrv + nCnt - 1))
EgtErase( nCrv + nCnt - 1)
else
EgtAddCurveCompoCurve( nCrv, nCrv + nCnt - 1, true, false)
end
nCnt = nCnt - 1
end
-- spezzo in corrispondenza di eventuali punti tangenti alla regione
local vArcs = EgtTableFill( nCrv, nCnt)
for j = nCrv, nCrv + nCnt - 1 do
local nInters, nPntCnt, nCrvCnt = EgtCurveCurveInters( j, nCrvBorder, nGrpTmp)
if nInters then
if nCnt == 1 then
EgtChangeClosedCurveStartPoint( j, EgtSP( nInters))
end
local nCurrCrv = j
for nPntId = nInters, nInters + nPntCnt - 1 do
local dPar = EgtCurveParamAtPoint( nCurrCrv, EgtSP( nPntId))
local nNewCrv = EgtSplitCurveAtParam( nCurrCrv, dPar)
if nNewCrv then
table.insert( vArcs, nNewCrv)
nCurrCrv = nNewCrv
end
end
end
end
-- modifico il bordo corrente considerando solo i tratti che poggiano sulle curve orginali
for j = 1, #vArcs do
for k = 1, #tArcs[i].vOrigId do
if CheckExtensionOverlap( vArcs[j], tArcs[i].vOrigId[k]) then
local dParS = EgtCurveParamAtPoint( nCrvBorder, EgtSP( vArcs[j]), 100 * GEO.EPS_SMALL)
local dParE = EgtCurveParamAtPoint( nCrvBorder, EgtEP( vArcs[j]), 100 * GEO.EPS_SMALL)
EgtTrimCurveStartEndAtParam( nCrvBorder, dParE, dParS)
EgtAddCurveCompoCurve( nCrvBorder, vArcs[j])
break
end
end
end
end
end
-- ricostruisco la superficie
nSurfId = EgtSurfFlatRegion( nGrpTmp, nCrvBorder)
end
-- d) gestione di eventuali bisettori
if #vBisectors > 0 then
local nCrvBorder = EgtExtractSurfFrChunkLoops( nSurfId, 0, nGrpTmp)
for i = 1, #vBisectors do
local nCrv, nCnt = EgtTrimCurveWithRegion( vBisectors[i], nSurfId, true, false)
if nCrv and nCnt == 1 then
local dParS = EgtCurveParamAtPoint( nCrvBorder, EgtSP( nCrv), 100 * GEO.EPS_SMALL)
local dParE = EgtCurveParamAtPoint( nCrvBorder, EgtEP( nCrv), 100 * GEO.EPS_SMALL)
EgtTrimCurveStartEndAtParam( nCrvBorder, dParE, dParS)
EgtAddCurveCompoCurve( nCrvBorder, nCrv)
end
end
nSurfId = EgtSurfFlatRegion( nGrpTmp, nCrvBorder)
end
EgtRelocateGlob( nSurfId, nGrp)
EgtErase( nGrpTmp)
return nSurfId
end
---------------------------------------------------------------------
local function GetDeltaProfile( nProfileId, sCtrIn, nOutlineId)
local dCPDelta = 0
local nSectionFrId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frSectionFrame = EgtFR( nSectionFrId, GDB_ID.ROOT)
local nCPId = EgtGetFirstNameInGroup( nProfileId, sCtrIn)
local b3CP = EgtGetBBoxRef( nCPId, GDB_BB.STANDARD, frSectionFrame)
if nOutlineId < 0 then
-- se a destra della curva sto considerando i semiprofili 1
dCPDelta = abs( b3CP:getMin():getX())
else
dCPDelta = abs( b3CP:getMax():getX())
end
-- se bottomrail considero anche scostamento dall'outline
local sProfileType = EgtGetInfo( nProfileId, WIN_PROFILETYPE)
if sProfileType == WIN_FILL_RAIL then
local dDelta = EgtGetInfo( nProfileId, WIN_RAILOFFS, 'd')
dCPDelta = dCPDelta + dDelta
end
return dCPDelta
end
---------------------------------------------------------------------
local function CheckSemiprofileIntersection( nGeoId, nPrevGeoId, nNextGeoId)
local nOutlineId = EgtGetInfo( nGeoId, WIN_REF_OUTLINE, 'i')
-- recupero la curva più interna del semiprofilo
local nSemiProfileId = EgtGetInfo( nGeoId, WIN_SEMI_PROFILE, 'i')
local nProfileId = EgtGetParent( nSemiProfileId)
local nFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frFrame = EgtFR( nFrameId, GDB_ID.ROOT)
local b3Box = EgtGetBBoxRef( nSemiProfileId, GDB_BB.STANDARD, frFrame)
local nInnerCrv = EgtCopyGlob( nOutlineId, EgtGetParent( nGeoId))
EgtOffsetCurve( nInnerCrv, b3Box:getMin():getX())
-- verifico se con estensione standard ( ovvero seguendo la circonferenza associata) arriva alle curve vicine del geo
local ptInt1 = FindIntersectionPoint( nInnerCrv, nPrevGeoId, ORIG())
local bTangStart = ( not ptInt1)
local ptInt2 = FindIntersectionPoint( nInnerCrv, nNextGeoId, ORIG())
local bTangEnd = ( not ptInt2)
EgtErase( nInnerCrv)
return bTangStart, bTangEnd
end
---------------------------------------------------------------------
-- funzione che stabilisce il tipo di estensione ( standard seguendo la circonferenza o lineare in tangenza) per curve del geo ad arco in base a condizioni euristiche per evitare giunzioni
-- problematiche
local function ComputeArcExtensions( nOutId, nInId, vLeftIds, vRightIds, vStartJoints, vEndJoints)
-- controllo euristico : verifico se la parte più interna del semiprofilo associato alla curva del geo ( ovvero considero tra i due archi che limitano il semiprofilo quello
-- con raggio minore perchè dovrebbe essere il più problematico) arriva alla curva di geo vicina con estensione standard oppure no
-- se curve in tangenza forza estensione in tangenza
-- se il pezzo corrente è arco devo verificare estensione per in e out
if EgtGetType( nOutId) == GDB_TY.CRV_ARC then
local bTangStart, bTangEnd = CheckSemiprofileIntersection( nOutId, vLeftIds[#vLeftIds], vRightIds[1])
-- verifico se necessaria estensione in tangenza per giunzione angled o per la curva in
if not bTangStart then
bTangStart = ( vStartJoints[#vStartJoints] == WIN_PART_JNT.ANGLED or not FindIntersectionPoint( nInId, vLeftIds[1], ORIG()))
end
EgtSetInfo( nOutId, WIN_TANG_START, bTangStart)
EgtSetInfo( nInId, WIN_TANG_END, bTangStart)
if not bTangEnd then
bTangEnd = ( vEndJoints[1] == WIN_PART_JNT.ANGLED or not FindIntersectionPoint( nInId, vRightIds[#vRightIds], ORIG()))
end
EgtSetInfo( nOutId, WIN_TANG_END, bTangEnd)
EgtSetInfo( nInId, WIN_TANG_START, bTangEnd)
end
-- verifico estensione left
for i = 1, #vLeftIds do
if EgtGetType( vLeftIds[i]) == GDB_TY.CRV_ARC then
local bTangS, bTangE = CheckSemiprofileIntersection( vLeftIds[i], nInId, nOutId)
-- se outline in tangenza con i vicini forzo estensione in tangenza
if not bTangS then
local nOutlineId = EgtGetInfo( vLeftIds[i], WIN_REF_OUTLINE, 'i')
local nPrevOutlineId = EgtGetPrev( nOutlineId) or EgtGetLastInGroup( EgtGetParent( nOutlineId))
if AreSameVectorApprox( EgtEV( nPrevOutlineId), EgtSV( nOutlineId)) then
bTangS = true
end
end
if not bTangE then
local nOutlineId = EgtGetInfo( vLeftIds[i], WIN_REF_OUTLINE, 'i')
local nNextOutlineId = EgtGetNext( nOutlineId) or EgtGetFirstInGroup( EgtGetParent( nOutlineId))
if AreSameVectorApprox( EgtEV( nOutlineId), EgtSV( nNextOutlineId)) then
bTangE = true
end
end
EgtSetInfo( vLeftIds[i], WIN_TANG_START, bTangS)
EgtSetInfo( vLeftIds[i], WIN_TANG_END, bTangE)
end
end
-- verifico estensione right
for i = 1, #vRightIds do
if EgtGetType( vRightIds[i]) == GDB_TY.CRV_ARC then
local bTangS, bTangE = CheckSemiprofileIntersection( vRightIds[i], nOutId, nInId)
if not bTangS then
local nOutlineId = EgtGetInfo( vRightIds[i], WIN_REF_OUTLINE, 'i')
local nPrevOutlineId = EgtGetPrev( nOutlineId) or EgtGetLastInGroup( EgtGetParent( nOutlineId))
if AreSameVectorApprox( EgtEV( nPrevOutlineId), EgtSV( nOutlineId)) then
bTangS = true
end
end
if not bTangE then
local nOutlineId = EgtGetInfo( vRightIds[i], WIN_REF_OUTLINE, 'i')
local nNextOutlineId = EgtGetNext( nOutlineId) or EgtGetFirstInGroup( EgtGetParent( nOutlineId))
if AreSameVectorApprox( EgtEV( nOutlineId), EgtSV( nNextOutlineId)) then
bTangE = true
end
end
EgtSetInfo( vRightIds[i], WIN_TANG_START, bTangS)
EgtSetInfo( vRightIds[i], WIN_TANG_END, bTangE)
end
end
end
---------------------------------------------------------------------
-- funzione che crea le curve del geo
local function CreateGeoCurves( nOutlineId, vPrevOutlineId, vNextOutlineId, vStartJoints, vEndJoints, nGeoLayerId, nProfileLayerId)
local nCurrProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN)
-- calcolo spostamento della curva iniziale dovuto a posizione riferimento
local b3CurrProfileFrame = GetProfileLocalBox( nCurrProfileId)
local dCurrOffset = b3CurrProfileFrame:getMax():getX()
local sProfileType = EgtGetInfo( nCurrProfileId, WIN_PROFILETYPE)
if sProfileType == WIN_FILL_RAIL or sProfileType == WIN_RAIL then
-- scostamento extra legato al bottomrail
local dDelta = EgtGetInfo( nCurrProfileId, WIN_RAILOFFS, 'd')
dCurrOffset = dCurrOffset - dDelta
end
-- creo copie degli outline e le offsetto opportunamente
-- curva out
local nOutId = EgtCopy( nOutlineId, nGeoLayerId)
EgtOffsetCurve( nOutId, dCurrOffset)
EgtSetName( nOutId, WIN_GEO_OUT)
local nSemiProfileOut = EgtGetFirstNameInGroup( nCurrProfileId, WIN_OUT)
if not nSemiProfileOut then
nSemiProfileOut = EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN .. '1') or EgtGetFirstNameInGroup( nCurrProfileId, WIN_MIXED_COMMON .. WIN_IN .. '1')
end
EgtSetInfo( nOutId, WIN_SEMI_PROFILE, nSemiProfileOut)
EgtSetInfo( nOutId, WIN_REF_OUTLINE, nOutlineId)
EgtSetInfo( nOutId, WIN_GEO_OFFS, dCurrOffset)
-- curva in
local nInId = EgtCopy( nOutlineId, nGeoLayerId)
EgtOffsetCurve( nInId, dCurrOffset - b3CurrProfileFrame:getDimX())
EgtInvertCurve( nInId)
EgtSetName( nInId, WIN_GEO_IN)
local nSemiProfileIn = EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN)
if not nSemiProfileIn then
nSemiProfileIn = EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN .. '2') or EgtGetFirstNameInGroup( nCurrProfileId, WIN_MIXED_COMMON .. WIN_IN .. '2') or
EgtGetFirstNameInGroup( nCurrProfileId, WIN_MIXED_COMMON .. WIN_IN)
end
EgtSetInfo( nInId, WIN_SEMI_PROFILE, nSemiProfileIn)
EgtSetInfo( nInId, WIN_REF_OUTLINE, - nOutlineId)
EgtSetInfo( nInId, WIN_GEO_OFFS, - dCurrOffset + b3CurrProfileFrame:getDimX())
-- curve left
local vPrevProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_START)
for i = 1, #vPrevOutlineId do
if vStartJoints[i] == WIN_PART_JNT.ANGLED then
-- recupero bordo out dell'altro pezzo ( non è detto coincida con l'outline)
local b3Profile = GetProfileLocalBox( vPrevProfileId[i])
local nOtherOut = EgtCopyGlob( vPrevOutlineId[i], nGeoLayerId)
EgtOffsetCurve( nOtherOut, b3Profile:getMax():getX())
-- a) calcolo bisettore: se pezzi lineari o in tangenza è segmento, altrimenti è tratto di parabola
local nBisector
if ( EgtGetType( nOutlineId) == GDB_TY.CRV_LINE and EgtGetType( vPrevOutlineId[i]) == GDB_TY.CRV_LINE) or
EgtEV( vPrevOutlineId[i]) * EgtSV( nOutlineId) > s_dAngledCos or
EgtGetName( nOutlineId) == EgtGetName( vPrevOutlineId[i]) then
local nOtherIn = EgtCopyGlob( vPrevOutlineId[i], nGeoLayerId)
EgtOffsetCurve( nOtherIn, b3Profile:getMin():getX())
local ptInt1 = FindIntersectionPoint( nOutId, nOtherOut, EgtSP( nOutId))
local ptInt2 = FindIntersectionPoint( nInId, nOtherIn, EgtSP( nInId))
EgtErase( nOtherIn)
nBisector = EgtLine( nGeoLayerId, ptInt2, ptInt1)
else
nBisector = CalcParabolicBisector( nOtherOut, nOutId, b3Profile:getDimX(), nGeoLayerId)
EgtInvertCurve( nBisector)
end
EgtSetName( nBisector, WIN_GEO_LEFT)
EgtSetInfo( nBisector, WIN_REF_OUTLINE, vPrevOutlineId[i])
EgtRelocateGlob( nBisector, nGeoLayerId, GDB_IN.LAST_SON)
-- b) se profili diversi per taglio corretto dei profili serve considerare anche il bordo out del pezzo adiacente
local sCurrProfile = EgtGetInfo( nCurrProfileId, WIN_PROFILETYPE)
local sPrevProfile = EgtGetInfo( vPrevProfileId[i], WIN_PROFILETYPE)
if sCurrProfile ~= sPrevProfile and not AreSameVectorApprox( EgtSV( nOutlineId), EgtEV( vPrevOutlineId[i])) then
EgtSetName( nOtherOut, WIN_GEO_LEFT)
EgtRelocateGlob( nOtherOut, nGeoLayerId, GDB_IN.LAST_SON)
local nSemiProfileId = EgtGetFirstNameInGroup( vPrevProfileId[i], WIN_OUT)
EgtSetInfo( nOtherOut, WIN_SEMI_PROFILE, nSemiProfileId)
EgtSetInfo( nOtherOut, WIN_REF_OUTLINE, vPrevOutlineId[i])
EgtSetInfo( nOtherOut, WIN_GEO_OFFS, b3Profile:getMax():getX())
else
-- considero la curva out come curva ausiliaria per il calcolo del geo
EgtSetName( nOtherOut, WIN_AUX)
EgtSetInfo( nOtherOut, WIN_TANG_START, true)
EgtSetInfo( nOtherOut, WIN_TANG_END, true)
end
else
local nPrevCurveId = EgtCopy( abs( vPrevOutlineId[i]), nGeoLayerId)
if vPrevOutlineId[i] < 0 then
EgtInvertCurve( nPrevCurveId)
end
local dOffs, nPrevSemiProfile
if vStartJoints[i] == WIN_PART_JNT.SHORT then
-- la curva del geo corrisponde al bordo del controprofilo in del pezzo vicino
local sCtrIn = GetProfileCtrIn( vPrevOutlineId[i], nOutlineId, vPrevProfileId[i], true)
local dCPDelta = GetDeltaProfile( vPrevProfileId[i], sCtrIn, vPrevOutlineId[i])
dOffs = - dCPDelta
nPrevSemiProfile = EgtGetFirstNameInGroup( vPrevProfileId[i], sCtrIn)
else
-- la curva del geo corrisponde all'out del pezzo vicino
local b3Profile = GetProfileLocalBox( vPrevProfileId[i])
dOffs = b3Profile:getMax():getX()
nPrevSemiProfile = EgtGetFirstNameInGroup( vPrevProfileId[i], WIN_OUT)
end
EgtOffsetCurve( nPrevCurveId, dOffs)
EgtSetInfo( nPrevCurveId, WIN_GEO_OFFS, dOffs)
EgtSetInfo( nPrevCurveId, WIN_SEMI_PROFILE, nPrevSemiProfile)
EgtSetInfo( nPrevCurveId, WIN_REF_OUTLINE, vPrevOutlineId[i])
EgtSetName( nPrevCurveId, WIN_GEO_LEFT)
EgtRelocateGlob( nPrevCurveId, nGeoLayerId, GDB_IN.LAST_SON)
end
end
-- curve right
local vNextProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_END)
for i = 1, #vNextOutlineId do
if vEndJoints[i] == WIN_PART_JNT.ANGLED then
local b3Profile = GetProfileLocalBox( vNextProfileId[i])
local nOtherOut = EgtCopyGlob( vNextOutlineId[i], nGeoLayerId)
EgtOffsetCurve( nOtherOut, b3Profile:getMax():getX())
-- calcolo bisettore
local nBisector
if ( EgtGetType( nOutlineId) == GDB_TY.CRV_LINE and EgtGetType( vNextOutlineId[i]) == GDB_TY.CRV_LINE) or
EgtEV( nOutlineId) * EgtSV( vNextOutlineId[i]) > s_dAngledCos or
EgtGetName( nOutlineId) == EgtGetName( vNextOutlineId[i]) then
local nOtherIn = EgtCopyGlob( vNextOutlineId[i], nGeoLayerId)
EgtOffsetCurve( nOtherIn, b3Profile:getMin():getX())
local ptInt1 = FindIntersectionPoint( nOutId, nOtherOut, EgtEP( nOutId))
local ptInt2 = FindIntersectionPoint( nInId, nOtherIn, EgtEP( nInId))
EgtErase( nOtherIn)
nBisector = EgtLine( nGeoLayerId, ptInt1, ptInt2)
else
nBisector = CalcParabolicBisector( nOutId, nOtherOut, b3Profile:getDimX(), nGeoLayerId)
end
EgtSetName( nBisector, WIN_GEO_RIGHT)
EgtSetInfo( nBisector, WIN_REF_OUTLINE, vNextOutlineId[i])
EgtRelocateGlob( nBisector, nInId, GDB_IN.BEFORE)
-- gestione per profili diversi
local sCurrProfile = EgtGetInfo( nCurrProfileId, WIN_PROFILETYPE)
local sNextProfile = EgtGetInfo( vNextProfileId[i], WIN_PROFILETYPE)
if sCurrProfile ~= sNextProfile and not AreSameVectorApprox( EgtEV( nOutlineId), EgtSV( vNextOutlineId[i])) then
EgtSetName( nOtherOut, WIN_GEO_RIGHT)
local nSemiProfileId = EgtGetFirstNameInGroup( vNextProfileId[i], WIN_OUT)
EgtSetInfo( nOtherOut, WIN_SEMI_PROFILE, nSemiProfileId)
EgtSetInfo( nOtherOut, WIN_REF_OUTLINE, vNextOutlineId[i])
EgtSetInfo( nOtherOut, WIN_GEO_OFFS, b3Profile:getMax():getX())
EgtRelocateGlob( nOtherOut, nInId, GDB_IN.BEFORE)
else
EgtSetName( nOtherOut, WIN_AUX)
EgtSetInfo( nOtherOut, WIN_TANG_START, true)
EgtSetInfo( nOtherOut, WIN_TANG_END, true)
end
else
local nNextCurveId = EgtCopy( abs( vNextOutlineId[i]), nGeoLayerId)
if vNextOutlineId[i] < 0 then
EgtInvertCurve( nNextCurveId)
end
local dOffs, nNextSemiProfile
if vEndJoints[i] == WIN_PART_JNT.SHORT then
local sCtrIn = GetProfileCtrIn( vNextOutlineId[i], nOutlineId, vNextProfileId[i], false)
local dCPDelta = GetDeltaProfile( vNextProfileId[i], sCtrIn, vNextOutlineId[i])
dOffs = - dCPDelta
nNextSemiProfile = EgtGetFirstNameInGroup( vNextProfileId[i], sCtrIn)
else
local b3Profile = GetProfileLocalBox( vNextProfileId[i])
dOffs = b3Profile:getMax():getX()
nNextSemiProfile = EgtGetFirstNameInGroup( vNextProfileId[i], WIN_OUT)
end
EgtOffsetCurve( nNextCurveId, dOffs)
EgtSetInfo( nNextCurveId, WIN_GEO_OFFS, dOffs)
EgtSetInfo( nNextCurveId, WIN_SEMI_PROFILE, nNextSemiProfile)
EgtSetInfo( nNextCurveId, WIN_REF_OUTLINE, vNextOutlineId[i])
EgtSetName( nNextCurveId, WIN_GEO_RIGHT)
EgtRelocateGlob( nNextCurveId, nInId, GDB_IN.BEFORE)
end
end
-- verifico se necessaria estensione in tangenza per pezzi ad arco
local vLeftIds = EgtGetNameInGroup( nGeoLayerId, WIN_LEFT)
local vRightIds = EgtGetNameInGroup( nGeoLayerId, WIN_RIGHT)
ComputeArcExtensions( nOutId, nInId, vLeftIds, vRightIds, vStartJoints, vEndJoints)
-- costruisco la superficie
local vIds = EgtGetAllInGroup( nGeoLayerId)
local nAreaId = CalcGeoRegion( vIds, nGeoLayerId)
if not nAreaId then
return false
end
EgtSetName( nAreaId, WIN_GEO_SURF)
EgtSetStatus( nAreaId, GDB_ST.OFF)
-- elimino curve aux
local vCrvs = {}
for i = 1, #vIds do
if EgtGetName( vIds[i]) == WIN_AUX then
EgtErase( vIds[i])
else
table.insert( vCrvs, vIds[i])
end
end
local _, vExtraCrvs = TrimOrderedCurves( vCrvs, false, nAreaId)
for i = 1, #vExtraCrvs do
EgtSetInfo( vExtraCrvs[i], WIN_GEO_EXTRA, true)
end
-- assegno spessore
local dGeoH = b3CurrProfileFrame:getDimY()
EgtModifyCurveThickness( vIds, - dGeoH)
-- salvo spessore serramento nel gruppo
local dGeoWidth = b3CurrProfileFrame:getDimX()
EgtSetInfo( nGeoLayerId, WIN_GEOWIDTH, dGeoWidth)
EgtSetInfo( nGeoLayerId, WIN_GEOHEIGHT, dGeoH)
-- calcolo lunghezza se pezzo lineare ( se arco verrà gestito nel calcolo dei tronchetti)
if EgtGetType( nOutlineId) == GDB_TY.CRV_LINE then
local vtS = EgtSV( nOutlineId)
local frRef = Frame3d( ORIG(), vtS, Z_AX() ^ vtS, Z_AX())
local b3Ref = EgtGetBBoxRef( nAreaId, GDB_BB.STANDARD, frRef)
EgtSetInfo( nGeoLayerId, WIN_GEOLEN, b3Ref:getDimX())
end
return true
end
---------------------------------------------------------------------
-- funzione che calcola l'ingombro dei pezzi del telaio
local function CalcGeo( nPartId, nOutlineId)
-- creo layer per ingombro
local nGeoLayerId = EgtGroup( nPartId)
EgtSetName( nGeoLayerId, WIN_GEO)
-- recupero il tipo di giunzioni
local vStartJoints
local vEndJoints
local nBottomRail = EgtGetInfo( nPartId, WIN_BOTTOMRAIL, 'i')
if nBottomRail then
-- se bottomrail deve essere short ( l'info sulla curva di riferisce al pezzo bottom)
vStartJoints = { WIN_PART_JNT.SHORT}
vEndJoints = { WIN_PART_JNT.SHORT}
else
vStartJoints = EgtGetInfo( nOutlineId, WIN_STARTJOINT, 'vi')
vEndJoints = EgtGetInfo( nOutlineId, WIN_ENDJOINT, 'vi')
end
-- aggiungo al gruppo profili quelli di trim
local vPrevOutlineId = EgtGetInfo( nOutlineId, WIN_PREV_OUTLINES, 'vi')
local vNextOutlineId = EgtGetInfo( nOutlineId, WIN_NEXT_OUTLINES, 'vi')
local nProfileLayerId = CalcStartEndProfiles( nPartId, nOutlineId, vPrevOutlineId, vNextOutlineId)
-- creo lati dell'outline
local bOk = CreateGeoCurves( nOutlineId, vPrevOutlineId, vNextOutlineId, vStartJoints, vEndJoints, nGeoLayerId, nProfileLayerId)
-- TODO verificare la validità del pezzo ( si è creata geo region, la curva out non è extra, ...)
end
---------------------------------------------------------------------
-- funzione che calcola l'ingombro del fill
local function CalcFillGeo( nPartId, nOutlineLayerId)
-- creo layer per ingombro
local nGeoLayerId = EgtGroup( nPartId)
EgtSetName( nGeoLayerId, WIN_GEO)
-- copio lati da Outline
local vOutlineIds = EgtGetAllInGroup( nOutlineLayerId)
for i = 1, #vOutlineIds do
local nCrv = EgtCopy( vOutlineIds[i], nGeoLayerId)
EgtSetInfo( nCrv, WIN_REF_OUTLINE, vOutlineIds[i])
end
-- recupero e salvo spessore vetro
local nProfileLayerId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE)
local nSashProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_SASH)
local dGlassThickness = EgtGetInfo( nSashProfileId, WIN_GLASSTHICKNESS, 'd')
EgtSetInfo( nGeoLayerId, WIN_GLASSTHICKNESS, dGlassThickness)
-- verifico forma e salvataggio info associate
local nCompo = EgtCurveCompo( nGeoLayerId, EgtGetAllInGroup( nGeoLayerId), false)
local bRect, ptTest, vtEdge1, vtEdge2 = EgtCurveIsARectangle( nCompo)
EgtSetInfo( nGeoLayerId, WIN_GLASS_RECT, bRect)
if bRect then
EgtSetInfo( nGeoLayerId, WIN_GEOWIDTH, vtEdge1:len())
EgtSetInfo( nGeoLayerId, WIN_GEOHEIGHT, vtEdge2:len())
else
-- se non è rettangolare salvo le dimensioni del suo box orientato in modo ottimale
local _, dDim1, dDim2 = EgtCurveMinAreaRectangleXY( nCompo)
EgtSetInfo( nGeoLayerId, WIN_GEOWIDTH, dDim1)
EgtSetInfo( nGeoLayerId, WIN_GEOHEIGHT, dDim2)
end
EgtErase( nCompo)
return nGeoLayerId
end
----------------------------------------------------------------------------------
----------------------- CURVE AUX PER CAMBIO PROFILO -----------------------------
----------------------------------------------------------------------------------
local function CalcMixedMillings( vOutlines, nOutlineProfileId, nSplitId, nSplitProfileId, bStart, bSashFill, bFillOnRight, nGrp)
-- TO DO : da capire bene come gestire il caso di cambio profilo che coinvolge più pezzi
-- TO DO : da capire quali info serve riportare nel profilo
local nGrpTmp = EgtGroup( nGrp)
local dDim1 = 61
local dDim2 = 45
local dRad = EgtGetInfo( nSplitProfileId, WIN_RAD_REF .. '1', 'd')
local ptRef = EgtIf( bStart, EgtSP( nSplitId), EgtEP( nSplitId))
-- calcolo le curve di riferimento per lo split
local b3SplitProfile = GetProfileLocalBox( nSplitProfileId)
local dSplitFixedOverl = EgtGetInfo( nSplitProfileId, WIN_FIXED_REF, 'd')
local dSplitSashOverl1 = EgtGetInfo( nSplitProfileId, WIN_SASH_REF .. '1', 'd')
local dSplitSashOverl2 = EgtGetInfo( nSplitProfileId, WIN_SASH_REF .. '2', 'd')
local nCrvSF, nCrvSS1, nCrvSS2
if bFillOnRight then
nCrvSF = EgtOffsetCurveAdv( nSplitId, b3SplitProfile:getMax():getX() - dSplitFixedOverl)
nCrvSS1 = EgtOffsetCurveAdv( nSplitId, b3SplitProfile:getMin():getX() + dSplitSashOverl1)
nCrvSS2 = EgtOffsetCurveAdv( nSplitId, b3SplitProfile:getMin():getX() + dSplitSashOverl2)
else
nCrvSF = EgtOffsetCurveAdv( nSplitId, b3SplitProfile:getMin():getX() + dSplitFixedOverl)
nCrvSS1 = EgtOffsetCurveAdv( nSplitId, b3SplitProfile:getMax():getX() - dSplitSashOverl1)
nCrvSS2 = EgtOffsetCurveAdv( nSplitId, b3SplitProfile:getMax():getX() - dSplitSashOverl2)
end
EgtRelocateGlob( nCrvSF, nGrpTmp)
EgtRelocateGlob( nCrvSS1, nGrpTmp)
EgtRelocateGlob( nCrvSS2, nGrpTmp)
-- calcolo le curve di riferimento prev
local vCompoOutlines = {}
for i = 1, #vOutlines do
vCompoOutlines[i] = EgtCopyGlob( abs( vOutlines[i]), nGrpTmp)
if vOutlines[i] < 0 then
EgtInvertCurve( vCompoOutlines[i])
end
end
local nOutlineCompo = EgtCurveCompo( nGrpTmp, vCompoOutlines)
local b3FrameProfile = GetProfileLocalBox( nOutlineProfileId)
local dFrameFixedOverl = EgtGetInfo( nOutlineProfileId, WIN_FIXED_REF, 'd')
local nCrvFF = EgtOffsetCurveAdv( nOutlineCompo, b3FrameProfile:getMin():getX() + dFrameFixedOverl)
local dFrameSashOverl1 = EgtGetInfo( nOutlineProfileId, WIN_SASH_REF .. '1', 'd')
local nCrvFS1 = EgtOffsetCurveAdv( nOutlineCompo, b3FrameProfile:getMin():getX() + dFrameSashOverl1)
local dFrameSashOverl2 = EgtGetInfo( nOutlineProfileId, WIN_SASH_REF .. '2', 'd')
local nCrvFS2 = EgtOffsetCurveAdv( nOutlineCompo, b3FrameProfile:getMin():getX() + dFrameSashOverl2)
local dFrameExtra = EgtGetInfo( nOutlineProfileId, WIN_EXTRA_DIST, 'd')
local nCrvFIn = EgtOffsetCurveAdv( nOutlineCompo, b3FrameProfile:getMin():getX() + dFrameSashOverl2 + dFrameExtra)
local dDepth = EgtGetInfo( nOutlineProfileId, WIN_SASH_DEPTH .. '2', 'd')
-- calcolo il bisettore a partire dall'incontro delle parti fixed del telaio e dello split
local nBisector
local pt1 = EgtIP( nCrvSF, nCrvFF, ptRef)
local dParRef = EgtCurveParamAtPoint( nCrvFF, pt1)
local nCrvRef = floor( dParRef)
if EgtCurveCompoRadius( nCrvFF, nCrvRef) == -1 then
-- se l'incontro tra la parte fixed del telaio e dello split avviene su un tratto lineare il bisettore è linea
local vtDir = ( EgtUV( nCrvFF, dParRef, -1) + EgtSV( nSplitId))
if not bFillOnRight then
vtDir = ( EgtUV( nCrvFF, dParRef, -1) - EgtSV( nSplitId))
end
nBisector = EgtLinePVL( nGrpTmp, pt1, vtDir, 1000)
EgtExtendCurveStartByLen( nBisector, 1000)
else
-- se l'incontro tra la parte fixed del telaio e dello split avviene su un tratto ad arco il bisettore è porzione di parabola
local nArc = EgtCopyCompoSubCurve( nCrvFF, nCrvRef, nGrpTmp)
local b3Profile = GetProfileLocalBox( nSplitProfileId)
local dDim = b3Profile:getDimX()
if bStart and bFillOnRight then
nBisector = CalcParabolicBisector( nArc, nCrvSF, dDim, nGrpTmp, true, false)
EgtInvertCurve( nBisector)
elseif bStart and not bFillOnRight then
nBisector = CalcParabolicBisector( nArc, nCrvSF, dDim, nGrpTmp, true, true)
elseif not bStart and not bFillOnRight then
nBisector = CalcParabolicBisector( nCrvSF, nArc, dDim, nGrpTmp, true, true)
EgtInvertCurve( nBisector)
elseif not bStart and bFillOnRight then
nBisector = CalcParabolicBisector( nCrvSF, nArc, dDim, nGrpTmp, true, false)
end
EgtErase( nArc)
end
-- posizione finale del tool di profilatura che determina il limite delle fresature
local nBisectTool = EgtCopyGlob( nBisector, nGrpTmp)
EgtOffsetCurve( nBisectTool, - dDim1 * 0.5)
EgtExtendCurveStartByLen( nBisectTool, 10)
EgtExtendCurveEndByLen( nBisectTool, 10)
local nCrvSash = EgtOffsetCurveAdv( nOutlineCompo, b3FrameProfile:getMin():getX() + dFrameSashOverl1 - dDim1 * 0.5)
local ptEnd = EgtIP( nCrvSash, nBisectTool, ptRef)
local nCircle = EgtCircle( nGrpTmp, ptEnd, dDim1 * 0.5)
local nCircle2 = EgtCircle( nGrpTmp, ptEnd, dDim2 * 0.5)
-- 1) Fresatura #1
local pt2 = EgtIP( nBisector, nCrvFS1, ptRef)
local dPar1 = EgtCurveParamAtPoint( nBisector, pt1)
local dPar2 = EgtCurveParamAtPoint( nBisector, pt2)
local nMill1 = EgtCopyParamRange( nBisector, min( dPar2, dPar1), max( dPar1, dPar2), nGrpTmp)
local dPar3 = EgtCurveParamAtPoint( nCrvFS1, pt2)
local _, _, dPar4 = EgtPointCurveDist( ptEnd, nCrvFS1)
local nMill2 = EgtCopyParamRange( nCrvFS1, min( dPar4, dPar3), max( dPar3, dPar4), nGrpTmp)
local nMilling
if bSashFill then
nMilling = EgtCurveCompo( nGrpTmp, { nMill2, nMill1})
else
nMilling = EgtCurveCompo( nGrpTmp, { nMill1, nMill2})
end
-- offset e contro-offset per creare fillet
local nMillingOffs = EgtOffsetCurveAdv( nMilling, - dRad)
nMilling = EgtOffsetCurveAdv( nMillingOffs, dRad)
EgtRelocateGlob( nMilling, nGrp)
EgtSetColor( nMilling, EgtStdColor( 'BLUE'))
EgtSetName( nMilling, WIN_MIXED_MILLING .. '1')
EgtSetInfo( nMilling, WIN_MIXED_SPLIT_REF, nSplitId)
EgtModifyCurveExtrusion( nMilling, Z_AX())
EgtModifyCurveThickness( nMilling, - dDepth)
EgtSetInfo( nMilling, WIN_FILL_ON_SPLIT_RIGHT, bFillOnRight)
-- 2) Fresatura #2
-- calcolo i punti di riferimento
local pt3 = EgtIP( nBisector, nCrvFIn, ptRef)
local pt4 = EgtIP( nCrvFIn, nCrvSS1, ptRef)
local pt5 = EgtIP( nCrvSS1, nCrvFS2, ptRef)
-- calcolo le curve
local dParA = EgtCurveParamAtPoint( nBisector, EgtIf( bSashFill, EgtEP( nMilling), EgtSP( nMilling)))
local dParB = EgtCurveParamAtPoint( nBisector, pt3)
local nMill3 = EgtCopyParamRange( nBisector, min( dParA, dParB), max( dParA, dParB), nGrpTmp)
local dParC = EgtCurveParamAtPoint( nCrvFIn, pt3)
local dParD = EgtCurveParamAtPoint( nCrvFIn, pt4)
local nMill4 = EgtCopyParamRange( nCrvFIn, min( dParC, dParD), max( dParC, dParD), nGrpTmp)
local dParE = EgtCurveParamAtPoint( nCrvSS1, pt4)
local dParF = EgtCurveParamAtPoint( nCrvSS1, pt5)
local nMill5 = EgtCopyParamRange( nCrvSS1, min( dParE, dParF), max( dParE, dParF), nGrpTmp)
if bFillOnRight then
EgtInvertCurve( nMill5)
end
local dParG = EgtCurveParamAtPoint( nCrvFS2, pt5)
local nMill6
if bSashFill then
nMill6 = EgtCopyParamRange( nCrvFS2, 0, dParG, nGrpTmp)
else
local _, dE = EgtCurveDomain( nCrvFS2)
nMill6 = EgtCopyParamRange( nCrvFS2, dParG, dE, nGrpTmp)
end
local nMilling2
if bSashFill then
nMilling2 = EgtCurveCompo( nGrp, { nMill6, nMill5, nMill4, nMill3})
else
nMilling2 = EgtCurveCompo( nGrp, { nMill3, nMill4, nMill5, nMill6})
end
EgtSetColor( nMilling2, EgtStdColor( 'BLUE'))
EgtSetName( nMilling2, WIN_MIXED_MILLING .. '2')
EgtModifyCurveExtrusion( nMilling2, Z_AX())
EgtModifyCurveThickness( nMilling2, - dDepth)
-- taglio sul punto finale della lavorazione di profilatura
local pt6 = EgtIP( nMilling2, nCircle2, ptRef)
if not pt6 then
_, pt6 = EgtPointCurveDist( EgtIf( bSashFill, EgtSP( nMilling), EgtEP( nMilling)), nMilling2)
end
local dParH = EgtCurveParamAtPoint( nMilling2, pt6)
if bSashFill then
EgtTrimCurveStartAtParam( nMilling2, dParH)
else
EgtTrimCurveEndAtParam( nMilling2, dParH)
end
EgtErase( nGrpTmp)
return nMilling, nMilling2
end
---------------------------------------------------------------------
-- funzione che calcola le curve legate al cambio profilo
local function CalcMixedCurves( nPartId, nSplitId)
local nGrp = EgtGroup( nPartId)
EgtSetName( nGrp, WIN_MIXED_CURVES)
EgtSetStatus( nGrp, GDB_ST.OFF)
local nProfileGrpId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nSplitProfileId = EgtGetFirstNameInGroup( nProfileGrpId, WIN_PRF_MAIN)
local nPrfChange = EgtGetInfo( nSplitId, WIN_PRF_CHANGE, 'i')
-- start
-- se cambio profilo sull'estremo start allora serve fresatura per cambio profilo
if nPrfChange & WIN_PRF_CHANGE_TYPES.START > 0 then
local vPrevOutlines = EgtGetInfo( nSplitId, WIN_PREV_OUTLINES, 'vi')
local nPrevProfileId = GetOutlineProfileId( abs( vPrevOutlines[1]))
-- verifico se lungo la direzione del prev outline l'ordine è sash/fill ( true) o fill/sash ( false)
local nStart1 = EgtGetInfo( nSplitId, WIN_MIXED_START_CHILDREN .. '1', 'i')
local bSashFill = EgtIf( nStart1 == WIN_CHILDREN_TYPES.FILL, true, false)
local nMill1, nMill2 = CalcMixedMillings( vPrevOutlines, nPrevProfileId, nSplitId, nSplitProfileId, true, bSashFill, nStart1 == WIN_CHILDREN_TYPES.FILL, nGrp)
EgtSetName( nMill1, WIN_MIXED_MILLING .. WIN_LEFT .. '1')
EgtSetName( nMill2, WIN_MIXED_MILLING .. WIN_LEFT .. '2')
-- copio le fresature sui pezzi su cui poggia
for i = 1, #vPrevOutlines do
local nPrevPartId = EgtGetInfo( abs( vPrevOutlines[i]), WIN_REF_PART, 'i')
local nMixedInters = EgtGetFirstNameInGroup( nPrevPartId, WIN_MIXED_CURVES)
if not nMixedInters then
nMixedInters = EgtGroup( nPrevPartId)
EgtSetName( nMixedInters, WIN_MIXED_CURVES)
EgtSetStatus( nMixedInters, GDB_ST.OFF)
end
local nCrv1 = EgtCopyGlob( nMill1, nMixedInters)
local nCrv2 = EgtCopyGlob( nMill2, nMixedInters)
local sSide = EgtIf( vPrevOutlines[i] > 0, WIN_IN, WIN_OUT)
EgtSetName( nCrv1, WIN_MIXED_MILLING .. sSide .. '1')
EgtSetName( nCrv2, WIN_MIXED_MILLING .. sSide .. '2')
end
end
-- end
if nPrfChange & WIN_PRF_CHANGE_TYPES.END > 0 then
local vNextOutlines = EgtGetInfo( nSplitId, WIN_NEXT_OUTLINES, 'vi')
local nNextProfileId = GetOutlineProfileId( abs( vNextOutlines[1]))
-- verifico se lungo la direzione del next outline l'ordine è sash/fill ( true) o fill/sash ( false)
local nEnd1 = EgtGetInfo( nSplitId, WIN_MIXED_END_CHILDREN .. '1', 'i')
local bSashFill = EgtIf( nEnd1 == WIN_CHILDREN_TYPES.FILL, false, true)
local nMill3, nMill4 = CalcMixedMillings( vNextOutlines, nNextProfileId, nSplitId, nSplitProfileId, false, bSashFill, nEnd1 == WIN_CHILDREN_TYPES.FILL, nGrp)
EgtSetName( nMill3, WIN_MIXED_MILLING .. WIN_RIGHT .. '1')
EgtSetName( nMill4, WIN_MIXED_MILLING .. WIN_RIGHT .. '2')
for i = 1, #vNextOutlines do
local nNextPartId = EgtGetInfo( abs( vNextOutlines[i]), WIN_REF_PART, 'i')
local nMixedInters = EgtGetFirstNameInGroup( nNextPartId, WIN_MIXED_CURVES)
if not nMixedInters then
nMixedInters = EgtGroup( nNextPartId)
EgtSetName( nMixedInters, WIN_MIXED_CURVES)
EgtSetStatus( nMixedInters, GDB_ST.OFF)
end
local nCrv1 = EgtCopyGlob( nMill3, nMixedInters)
local nCrv2 = EgtCopyGlob( nMill4, nMixedInters)
local sSide = EgtIf( vNextOutlines[i] > 0, WIN_IN, WIN_OUT)
EgtSetName( nCrv1, WIN_MIXED_MILLING .. sSide .. '1')
EgtSetName( nCrv2, WIN_MIXED_MILLING .. sSide .. '2')
end
end
end
----------------------------------------------------------------------------------
--------------------------- PROFILING PROCESSINGS --------------------------------
----------------------------------------------------------------------------------
-- funzione che copia sulla curva di lavorazione le informazioni prese dal semiprofilo corrispondente
local function GetProcessingInfoFromSemiProfile( nCrv, nSemiProfile)
if nSemiProfile then
-- setto info di lavorazione
EgtSetInfo( nCrv, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING)
-- setto info con il tipo di profiling
local sName = EgtGetName( nCrv)
if sName == WIN_GEO_LEFT or sName == WIN_GEO_RIGHT then
EgtSetInfo( nCrv, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.HEAD)
else
EgtSetInfo( nCrv, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.LONGITUDINAL)
end
-- recupero le info di lavorazione dal semiprofilo
if sName == WIN_GEO_OUT or sName == WIN_GEO_IN then
-- recupero la fase solo se si tratta di in o out
CopyInfo( nCrv, nSemiProfile, WIN_PRC_PHASE)
end
local nTools = EgtGetInfo( nSemiProfile, WIN_PRC_NTOOLS , 'i') or 0
EgtSetInfo( nCrv, WIN_PRC_NTOOLS, nTools)
for j = 1, nTools do
CopyInfo( nCrv, nSemiProfile, WIN_PRC_TOOL_NAME .. '_' .. tostring(j))
CopyInfo( nCrv, nSemiProfile, WIN_PRC_OFFL .. '_' .. tostring(j))
CopyInfo( nCrv, nSemiProfile, WIN_PRC_OFFR .. '_' .. tostring(j))
end
CopyInfo( nCrv, nSemiProfile, WIN_PRC_ID)
else
-- se non ha semiprofilo associato è un taglio
EgtSetInfo( nCrv, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.CUT)
end
end
---------------------------------------------------------------------
-- funzione che concatena, se possibile, lavorazioni con lo stesso semiprofilo
local function ChainProfilingProcessingCurves( vProcCrvsOrig, vRefCrvsOrig)
if #vProcCrvsOrig == 1 then
return vProcCrvsOrig, vRefCrvsOrig
end
local vProcCrvs = {}
local vRefCrvs = {}
local nCurrCrv = vProcCrvsOrig[1]
local vCurrRef = { vRefCrvsOrig[1]}
local sIdCurr = EgtGetInfo( vProcCrvsOrig[1], WIN_PRC_ID)
for i = 2, #vProcCrvsOrig do
local bChain = false
local sId = EgtGetInfo( vProcCrvsOrig[i] or GDB_ID.NULL, WIN_PRC_ID)
if sIdCurr == sId then
-- verifico se le curve si tagliano tra di loro
local ptInt = EgtIP( nCurrCrv, vProcCrvsOrig[i], EgtEP( nCurrCrv))
if ptInt then
bChain = true
local dPar1 = EgtCurveParamAtPoint( nCurrCrv, ptInt)
local dPar2 = EgtCurveParamAtPoint( vProcCrvsOrig[i], ptInt)
local vCompoCrvs = {}
-- se la curva non viene completamente trimmata la considero, altrimenti la cancello
if dPar1 > GEO.EPS_SMALL then
EgtTrimCurveEndAtParam( nCurrCrv, dPar1)
table.insert( vCompoCrvs, nCurrCrv)
else
EgtErase( nCurrCrv)
end
local _, dE = EgtCurveDomain( vProcCrvsOrig[i])
if abs( dPar2 - dE) > GEO.EPS_SMALL then
EgtTrimCurveStartAtParam( vProcCrvsOrig[i], dPar2)
table.insert( vCompoCrvs, vProcCrvsOrig[i])
else
EgtErase( vProcCrvsOrig[i])
end
nCurrCrv = EgtCurveCompo( EgtGetParent( vProcCrvsOrig[1]), vCompoCrvs)
table.insert( vCurrRef, vRefCrvsOrig[i])
end
end
if not bChain then
-- salvo la vecchia catena appena interrotta e inizializzo le variabili con la nuova
table.insert( vProcCrvs, nCurrCrv)
table.insert( vRefCrvs, vCurrRef)
nCurrCrv = vProcCrvsOrig[i]
vCurrRef = { vRefCrvsOrig[i]}
sIdCurr = sId
end
end
table.insert( vProcCrvs, nCurrCrv)
table.insert( vRefCrvs, vCurrRef)
-- se è stata creata una catena ( quindi una lavorazione ha più curve di riferimento associate), vanno risettate le info di lavorazione
for i = 1, #vRefCrvs do
if #vRefCrvs[i] > 1 then
EgtSetName( vProcCrvs[i], EgtGetName( vRefCrvs[i][1]))
local nSemiProfileId = EgtGetInfo( vRefCrvs[i][1], WIN_SEMI_PROFILE, 'i')
GetProcessingInfoFromSemiProfile( vProcCrvs[i], nSemiProfileId)
for j = 1, #vRefCrvs[i] do
EgtSetInfo( vRefCrvs[i][j], WIN_REF_PRC, vProcCrvs[i])
end
EgtSetInfo( vProcCrvs[i], WIN_REF_GEO, vRefCrvs[i])
end
end
return vProcCrvs, vRefCrvs
end
---------------------------------------------------------------------
-- funzione che verifica se la lavorazione è veramente necessaria considerando le interferenze tra i profili
local function TestProcessings( vProcCrvs, vRefCrvs, nGeoOut, nGeoIn)
if #vProcCrvs == 1 then
return
end
local nGrpTmp = EgtGroup( 0)
-- creo le superifici delle lavorazioni e quelle estese da usare per i trim
local vSurfs = {}
for i = 1, #vProcCrvs do
local nSemiProfileId = EgtGetInfo( vRefCrvs[i][1], WIN_SEMI_PROFILE, 'i')
if nSemiProfileId then
local nGuideId = EgtCopyGlob( vProcCrvs[i], nGrpTmp)
local dOffs = EgtGetInfo( vRefCrvs[i][1], WIN_GEO_OFFS, 'd')
EgtOffsetCurve( nGuideId, - dOffs)
local nProfileId = EgtGetParent( nSemiProfileId)
local nSurf = CreateProfileSurfById( nGuideId, nProfileId, nSemiProfileId, 0, nGrpTmp)
local nSurfExt = CreateProfileSurf( nGuideId, nProfileId, WIN_OFST .. EgtGetName( nSemiProfileId), 1000, nGrpTmp)
vSurfs[i] = { nId = nSurf, nExtId = nSurfExt}
end
end
-- superfici che delimitano il pezzo
local nOutlineId = EgtGetInfo( nGeoOut, WIN_REF_OUTLINE, 'i')
local nSemiProfileOut = EgtGetInfo( nGeoOut, WIN_SEMI_PROFILE, 'i')
local nProfileId = EgtGetParent( nSemiProfileOut)
local nSurfOut
local sName = EgtGetName( nSemiProfileOut)
if sName == WIN_OUT then
nSurfOut = CreateProfileSurf( nOutlineId, nProfileId, WIN_OFST .. sName, 1000, nGrpTmp)
elseif sName == WIN_MIXED_COMMON .. WIN_IN .. '1' then
nSurfOut = CreateProfileSurf( nOutlineId, nProfileId, WIN_OFST .. WIN_FILL .. WIN_CTRIN .. '1', 1000, nGrpTmp)
EgtInvertSurf( nSurfOut)
else
nSurfOut = CreateProfileSurf( nOutlineId, nProfileId, WIN_OFST .. 'Ctr' .. sName, 1000, nGrpTmp)
EgtInvertSurf( nSurfOut)
end
local nSemiProfileIn = EgtGetInfo( nGeoIn, WIN_SEMI_PROFILE, 'i')
local sNameIn = EgtGetName( nSemiProfileIn)
if sNameIn == WIN_MIXED_COMMON .. WIN_IN then
sNameIn = WIN_FILL .. WIN_CTRIN
elseif sNameIn == WIN_MIXED_COMMON .. WIN_IN .. '2' then
sNameIn = WIN_FILL .. WIN_CTRIN .. '2'
else
sNameIn = 'Ctr' .. sNameIn
end
local nSurfIn = CreateProfileSurf( nOutlineId, nProfileId, WIN_OFST .. sNameIn, 1000, nGrpTmp)
EgtInvertSurf( nSurfIn)
for i = 1, #vSurfs do
-- taglio la superficie con le altre lavorazioni e con il bordo
for j = 1, #vSurfs do
if i ~= j then
EgtSurfTmCut( vSurfs[i].nId, vSurfs[j].nExtId, true, false)
end
end
EgtSurfTmCut( vSurfs[i].nId, nSurfOut, true, false)
EgtSurfTmCut( vSurfs[i].nId, nSurfIn, true, false)
-- se scompare la lavorazione non serve
if EgtSurfTmPartCount( vSurfs[i].nId) == 0 then
EgtErase( vProcCrvs[i])
for j = 1, #vRefCrvs[i] do
EgtRemoveInfo( vRefCrvs[i][j], WIN_REF_PRC)
end
end
end
EgtErase( nGrpTmp)
end
---------------------------------------------------------------------
local function CreateProfilingProcessingCurve( nGeoCrvId, nPrevCrv, nSurfGeo, nPrcLayerId)
-- recupero il semiprofilo associato alla curva
local nSemiProfileId = EgtGetInfo( nGeoCrvId, WIN_SEMI_PROFILE, 'i')
local nPrcCrvId
-- se bisettrice
if not nSemiProfileId then
nPrcCrvId = EgtCopyGlob( nGeoCrvId, nPrcLayerId)
-- se lavorazione di controprofilo
else
local nGrpTmp = EgtGroup( nPrcLayerId)
local nProfileId = EgtGetParent( nSemiProfileId)
local nFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frFrame = EgtFR( nFrameId, GDB_ID.ROOT)
local b3SemiProfile = EgtGetBBoxRef( nSemiProfileId, GDB_BB.STANDARD, frFrame)
local dOffs = b3SemiProfile:getDimX()
-- calcolo la curva di lavorazione interna ( partendo dall'outline e non dal geo per essere coerente con la info di estensione)
local nRefOutlineId = EgtGetInfo( nGeoCrvId, WIN_REF_OUTLINE, 'i')
local nOutlineId = EgtCopyGlob( abs( nRefOutlineId), nGrpTmp)
if nRefOutlineId < 0 then
EgtInvertCurve( nOutlineId)
end
local dGeoOffs = EgtGetInfo( nGeoCrvId, WIN_GEO_OFFS, 'd')
local nOrigInnerProcId = EgtOffsetCurveAdv( nOutlineId, dGeoOffs - dOffs)
-- adatto la curva di lavorazione interna al pezzo
CopyInfo( nOrigInnerProcId, nGeoCrvId, WIN_TANG_START, false)
CopyInfo( nOrigInnerProcId, nGeoCrvId, WIN_TANG_END, false)
local nInnerProcId = CreateCurveExtension( nOrigInnerProcId, nGrpTmp)
local nInId, nCnt = EgtTrimCurveWithRegion( nInnerProcId, nSurfGeo, true, false)
if not nInId then
nCnt = 0
end
if nCnt > 0 then
if nCnt > 1 and AreSamePointApprox( EgtSP( nInId), EgtEP( nInId + nCnt - 1)) then
if EgtGetType( nInId) == GDB_TY.CRV_ARC then
EgtModifyCurveStartPoint( nInId, EgtSP( nInId + nCnt - 1))
else
EgtAddCurveCompoCurve( nInId, nInId + nCnt - 1, true, false)
end
nCnt = nCnt - 1
end
-- se ottengo più tratti considero quello che ha porzione in comune con la curva originale
if nCnt > 1 then
local nTestCrv = EgtOffsetCurveAdv( nGeoCrvId, - dOffs)
EgtRelocateGlob( nTestCrv, nGrpTmp)
local vOverlapCrvs = {}
for nId = nInId, nInId + nCnt - 1 do
if CheckExtensionOverlap( nId, nTestCrv) then
table.insert( vOverlapCrvs, nId)
end
end
if #vOverlapCrvs == 1 then
nInId = vOverlapCrvs[1]
elseif #vOverlapCrvs > 0 then
-- se ottengo più tratti di overlap con il geo considero il più vicino al geo precedente
local nIdx = 1
local dMinDist = GEO.INFINITO
local ptRef = EgtEP( nPrevCrv)
for i = 1, #vOverlapCrvs do
local dDist = dist( EgtSP( vOverlapCrvs[i]), ptRef)
if dDist < dMinDist then
dMinDist = dDist
nIdx = i
end
end
nInId = vOverlapCrvs[nIdx]
end
end
-- la allineo alla curva di lavoro
EgtOffsetCurve( nInId, dOffs)
local bExtra = EgtGetInfo( nGeoCrvId, WIN_GEO_EXTRA, 'b') or false
if bExtra then
-- se la lavorazione fa overlap con la curva del geo allora considero direttamente la curva di lavorazione interna
if CheckExtensionOverlap( nInId, nGeoCrvId) then
nPrcCrvId = nInId
EgtRelocateGlob( nPrcCrvId, nPrcLayerId)
end
else
-- modifico la curva del geo in allungamento
nPrcCrvId = EgtCurveCompo( nPrcLayerId, nGeoCrvId, false)
local dParS = EgtCurveParamAtPoint( nPrcCrvId, EgtSP( nInId), 100 * GEO.EPS_SMALL)
if not dParS then
local dParTrim = EgtCurveParamAtPoint( nInId, EgtSP( nPrcCrvId), 100 * GEO.EPS_SMALL)
if dParTrim then
local nNewCrv = EgtCopyParamRange( nInId, 0, dParTrim, nGrpTmp)
EgtAddCurveCompoCurve( nPrcCrvId, nNewCrv, true, false)
end
end
local dParE = EgtCurveParamAtPoint( nPrcCrvId, EgtEP( nInId), 100 * GEO.EPS_SMALL)
if not dParE then
local dParTrim = EgtCurveParamAtPoint( nInId, EgtEP( nPrcCrvId), 100 * GEO.EPS_SMALL)
if dParTrim then
local _, dE = EgtCurveDomain( nInId)
local nNewCrv = EgtCopyParamRange( nInId, dParTrim, dE, nGrpTmp)
EgtAddCurveCompoCurve( nPrcCrvId, nNewCrv)
end
end
end
end
EgtErase( nGrpTmp)
end
-- sistemo la curva e setto le info
if nPrcCrvId then
EgtModifyCurveThickness( nPrcCrvId, 0)
EgtSetStatus( nPrcCrvId, GDB_ST.ON)
EgtSetName( nPrcCrvId, EgtGetName( nGeoCrvId))
GetProcessingInfoFromSemiProfile( nPrcCrvId, nSemiProfileId)
EgtSetInfo( nGeoCrvId, WIN_REF_PRC, nPrcCrvId)
EgtSetInfo( nPrcCrvId, WIN_REF_GEO, nGeoCrvId)
end
return nPrcCrvId
end
---------------------------------------------------------------------
local function TrimTangentProcessings( nPrc1, nPrc2, ptRef)
-- se le due lavorazioni hanno lo stesso semiprofilo e sono in tangenza nel loro punto di intersezione, allora posso trimmarle per evitare di avere porzioni di lavorazioni superflue
local sId1 = EgtGetInfo( nPrc1, WIN_PRC_ID)
local sId2 = EgtGetInfo( nPrc2, WIN_PRC_ID)
if sId1 == sId2 then
local ptInt = EgtIP( nPrc1, nPrc2, ptRef)
if ptInt then
local dPar1 = EgtCurveParamAtPoint( nPrc1, ptInt)
local dPar2 = EgtCurveParamAtPoint( nPrc2, ptInt)
if AreSameVectorApprox( EgtUV( nPrc1, dPar1, -1), EgtUV( nPrc2, dPar2, -1)) then
EgtTrimCurveEndAtParam( nPrc1, dPar1)
EgtTrimCurveStartAtParam( nPrc2, dPar2)
end
end
end
end
---------------------------------------------------------------------
-- funzione che calcola le lavorazioni di profilatura a partire dalle curve del geo
local function CreateProfilingProcessingFromGeo( nGeoLayerId, nSurfGeo, nProcLayerId, nPartId)
-- a) out
local nOut = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_OUT)
local nPrcOut = CreateProfilingProcessingCurve( nOut, nil, nSurfGeo, nProcLayerId)
local sOutId = EgtGetInfo( nPrcOut, WIN_PRC_ID)
EgtSetInfo( nPartId, WIN_PRC_PROFILE_OUT, sOutId)
-- b) in
local nIn = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_IN)
local nPrcIn = CreateProfilingProcessingCurve( nIn, nil, nSurfGeo, nProcLayerId)
local sInId = EgtGetInfo( nPrcIn, WIN_PRC_ID)
EgtSetInfo( nPartId, WIN_PRC_PROFILE_IN, sInId)
-- c) right
-- costruisco le curve di lavorazione
local vRight = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_RIGHT)
local vProcRight = {}
local vRefRight = {}
for i = 1, #vRight do
local nCrvId = CreateProfilingProcessingCurve( vRight[i], nOut, nSurfGeo, nProcLayerId)
if nCrvId then
table.insert( vProcRight, nCrvId)
table.insert( vRefRight, vRight[i])
end
end
-- concateno
vProcRight, vRefRight = ChainProfilingProcessingCurves( vProcRight, vRefRight)
-- verifico se ci sono lavorazioni superflue
TestProcessings( vProcRight, vRefRight, nOut, nIn)
-- eventuale trim con out e in
local vPrcRight = EgtGetNameInGroup( nProcLayerId, WIN_RIGHT)
TrimTangentProcessings( nPrcOut, vPrcRight[1], EgtEP( nPrcOut))
TrimTangentProcessings( vPrcRight[#vPrcRight], nPrcIn, EgtSP( nPrcIn))
-- d) left
local vLeft = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_LEFT)
local vProcLeft = {}
local vRefLeft = {}
for i = 1, #vLeft do
local nCrvId = CreateProfilingProcessingCurve( vLeft[i], nIn, nSurfGeo, nProcLayerId)
if nCrvId then
table.insert( vProcLeft, nCrvId)
table.insert( vRefLeft, vLeft[i])
end
end
vProcLeft, vRefLeft = ChainProfilingProcessingCurves( vProcLeft, vRefLeft)
TestProcessings( vProcLeft, vRefLeft, nOut, nIn)
local vPrcLeft = EgtGetNameInGroup( nProcLayerId, WIN_LEFT)
TrimTangentProcessings( nPrcIn, vPrcLeft[1], EgtEP( nPrcIn))
TrimTangentProcessings( vPrcLeft[#vPrcLeft], nPrcOut, EgtSP( nPrcOut))
end
---------------------------------------------------------------------
-- funzione che calcola le lavorazioni di profiling per un pezzo di telaio con cambio profilo
local function CalcMixedFrameProfilingProcessings( nPartId, nProcLayerId, nGeoLayerId, nMainProfileId, nSurfGeoId)
-- a) lavorazioni profili
-- per le lavorazioni dei profili out, left, right e in comune si usano le corrispondenti curve del geo
local nGeoArea = EgtGetLastInGroup( nGeoLayerId)
CreateProfilingProcessingFromGeo( nGeoLayerId, nGeoArea, nProcLayerId, nPartId)
-- b) lavorazioni per i sottotratti sash e fill
-- TO DO ( da capire bene soprattuto nei casi di cambio profilo che coinvolge pezzi distinti)
-- c) fresature
local nMixedIntersGrp = EgtGetFirstNameInGroup( nPartId, WIN_MIXED_CURVES)
local vMixedInters = EgtGetAllInGroup( nMixedIntersGrp)
local dDepth1 = EgtGetInfo( nMainProfileId, WIN_SASH_DEPTH .. '1', 'd')
for i = 1, #vMixedInters do
local nMilling = EgtCopyGlob( vMixedInters[i], nProcLayerId)
-- sistemo spessore ( solo della fresatura 1, la seconda ha già profondità corretta)
if EgtEndsWith( EgtGetName( nMilling), '1') then
EgtModifyCurveThickness( nMilling, - dDepth1)
end
EgtSetInfo( nMilling, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING)
EgtSetInfo( nMilling, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC)
EgtSetInfo( nMilling, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.IN)
end
end
---------------------------------------------------------------------
-- funzione che calcola le lavorazioni di profiling nel caso di uno split coinvolto da cambio profilo
local function CalcMixedSplitProfilingProcessings( nSplitId, nProcLayerId, nGeoLayerId, nMainProfileId)
-- a) lavorazione dei profili
local nGeoArea = EgtGetLastInGroup( nGeoLayerId)
CreateProfilingProcessingFromGeo( nGeoLayerId, nGeoArea, nProcLayerId, EgtGetParent( nProcLayerId))
-- b) fresature
local nMixedIntersGrp = EgtGetFirstNameInGroup( EgtGetParent( nProcLayerId), WIN_MIXED_CURVES)
-- estremo start ( solo se presenta cambio profilo)
local nMillingLeft = EgtGetFirstNameInGroup( nMixedIntersGrp, WIN_MIXED_MILLING .. WIN_LEFT .. '1')
if nMillingLeft then
local nPrcCrv = EgtCopyGlob( nMillingLeft, nProcLayerId)
EgtSetInfo( nPrcCrv, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING)
EgtSetInfo( nPrcCrv, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC)
EgtSetInfo( nPrcCrv, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.LEFT)
end
-- estremo end
local nMillingRight = EgtGetFirstNameInGroup( nMixedIntersGrp, WIN_MIXED_MILLING .. WIN_RIGHT .. '1')
if nMillingRight then
local nPrcCrv = EgtCopyGlob( nMillingRight, nProcLayerId)
EgtInvertCurve( nPrcCrv)
EgtSetInfo( nPrcCrv, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING)
EgtSetInfo( nPrcCrv, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC)
EgtSetInfo( nPrcCrv, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.RIGHT)
end
-- lavorazioni legate ad altro split con cambio profilo che si innesta sullo split corrente
local dDepth1 = EgtGetInfo( nMainProfileId, WIN_SASH_DEPTH .. '1')
local vCrvsOut = EgtGetNameInGroup( nMixedIntersGrp, WIN_MIXED_MILLING .. WIN_OUT .. '*')
for i = 1, #vCrvsOut do
local nMilling = EgtCopyGlob( vCrvsOut[i], nProcLayerId)
if EgtEndsWith( EgtGetName( nMilling), '1') then
EgtModifyCurveThickness( nMilling, - dDepth1)
end
EgtSetInfo( nMilling, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING)
EgtSetInfo( nMilling, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC)
EgtSetInfo( nMilling, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.OUT)
end
local vCrvsIn = EgtGetNameInGroup( nMixedIntersGrp, WIN_MIXED_MILLING .. WIN_IN .. '*')
for i = 1, #vCrvsIn do
local nMilling = EgtCopyGlob( vCrvsIn[i], nProcLayerId)
if EgtEndsWith( EgtGetName( nMilling), '1') then
EgtModifyCurveThickness( nMilling, - dDepth1)
end
EgtSetInfo( nMilling, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING)
EgtSetInfo( nMilling, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC)
EgtSetInfo( nMilling, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.IN)
end
end
---------------------------------------------------------------------
-- funzione che calcola le lavorazioni di profiling
local function CalcProfilingProcessings( nPartId, nOutlineId)
-- creo gruppo delle lavorazioni
local nProcLayerId = EgtGroup( nPartId)
EgtSetName( nProcLayerId, WIN_PRC)
EgtSetStatus( nProcLayerId, GDB_ST.OFF)
-- recupero il geo e la superficie associata per limitare le lavorazioni
local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
local vGeoCrvs = EgtGetAllInGroup( nGeoLayerId)
local nSurfGeo = vGeoCrvs[#vGeoCrvs]
-- recupero il gruppo dei profili
local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN)
-- recupero le info di sovramateriale dal profilo
CopyInfo( nPartId, nMainProfileId, WIN_PRC_OVERMAT_IN, 0)
CopyInfo( nPartId, nMainProfileId, WIN_PRC_OVERMAT_OUT, 0)
CopyInfo( nPartId, nMainProfileId, WIN_PRC_OVERMAT_LEFT, 0)
CopyInfo( nPartId, nMainProfileId, WIN_PRC_OVERMAT_RIGHT, 0)
-- calcolo lavorazioni dei profili
local nPrfChange = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'i') or WIN_PRF_CHANGE_TYPES.NULL
if nPrfChange > 0 then
-- 1) cambio profilo ( su split o telaio)
if EgtGetName( nOutlineId) == WIN_SPLIT then
CalcMixedSplitProfilingProcessings( nOutlineId, nProcLayerId, nGeoLayerId, nMainProfileId)
else
CalcMixedFrameProfilingProcessings( nPartId, nProcLayerId, nGeoLayerId, nMainProfileId, nSurfGeo)
end
else
-- 2) caso standard : costruisco le curve di lavorazione a partire da quelle del geo
CreateProfilingProcessingFromGeo( nGeoLayerId, nSurfGeo, nProcLayerId, nPartId)
end
-- calcolo eventuali lavorazioni per strip
local vStripDist = EgtGetInfo( nMainProfileId, WIN_STRIP_DIST, 'vi') or {}
local nGeoIn = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_IN)
local bTangStart = EgtGetInfo( nGeoIn, WIN_TANG_END, 'b') or false
local bTangEnd = EgtGetInfo( nGeoIn, WIN_TANG_START, 'b') or false
for i = 1, #vStripDist do
local nStripOutline = EgtCopyGlob( nOutlineId, nProcLayerId)
EgtOffsetCurve( nStripOutline, vStripDist[i])
-- estendo la curva per adattarla alla regione del geo basandomi sulle estensioni della curva in ( che dovrebbe essere quella più vicina)
EgtSetInfo( nStripOutline, WIN_TANG_START, bTangStart)
EgtSetInfo( nStripOutline, WIN_TANG_END, bTangEnd)
local nStripCut = CreateCurveExtension( nStripOutline, nProcLayerId)
local nRes, nCnt = EgtTrimCurveWithRegion( nStripCut, nSurfGeo, true, false)
-- se più di un tratto considero solo quello con sovrapposizione con la curva non estesa
if nCnt > 1 and AreSamePointApprox( EgtSP( nRes), EgtEP( nRes + nCnt - 1)) then
if EgtGetType( nRes) == GDB_TY.CRV_ARC then
EgtModifyCurveStartPoint( nRes, EgtSP( nRes + nCnt - 1))
EgtErase( nRes + nCnt - 1)
else
EgtAddCurveCompoCurve( nRes, nRes + nCnt - 1, true, false)
end
nCnt = nCnt - 1
end
if nCnt > 1 then
for nId = nRes, nRes + nCnt - 1 do
if CheckExtensionOverlap( nId, nStripOutline) then
nStripCut = nId
else
EgtErase( nId)
end
end
end
EgtErase( nStripOutline)
-- aggiusto orientamento per essere coerente con il geo corrispondente
if vStripDist[i] < 0 then
EgtInvertCurve( nStripCut)
end
-- setto info di lavorazione
EgtSetName( nStripCut, WIN_PRC_TYPE.STRIP_CUT)
EgtSetInfo( nStripCut, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.STRIP_CUT)
end
-- verifico se anta ricevente ( info necessaria per ottimizzazione lavorazioni)
local nAreaId = EgtGetParent( EgtGetParent( nOutlineId))
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
local nSashType = EgtGetInfo( nAreaId, WIN_SASHTYPE, 'i')
if nSashType == WIN_SASHTYPES.INACTIVE or nSashType == WIN_SASHTYPES.INACTIVE_IN then
local bOnFrenchSplit = EgtGetInfo( nOutlineId, WIN_CRV_ON_FRENCH_SPLIT, 'b')
if bOnFrenchSplit then
EgtSetInfo( nPartId, WIN_SASHTYPE, WIN_INACTIVE)
end
end
end
end
---------------------------------------------------------------------
-- funzione che calcola gli elementi ausiliari per la creazione del grezzo nell'automatismo delle lavorazioni
local function CalcGeoRaw( nPartId, nOutlineId)
-- se pezzo ad arco il geo raw sarà calcolato tramite i tronchetti
if EgtGetType( nOutlineId) == GDB_TY.CRV_ARC then
return
end
local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
local nGeoRawLayerId = EgtCopyGlob( nGeoLayerId, nPartId)
EgtErase( EgtGetLastInGroup( nGeoRawLayerId)) -- elimino la regione
EgtSetName( nGeoRawLayerId, WIN_GEO_RAW)
EgtSetStatus( nGeoRawLayerId, GDB_ST.OFF)
-- recupero i sovramateriali da applicare alle curve
local dOvermatOut = EgtGetInfo( nPartId, WIN_PRC_OVERMAT_OUT, 'd')
local dOvermatRight = EgtGetInfo( nPartId, WIN_PRC_OVERMAT_RIGHT, 'd')
local dOvermatIn = EgtGetInfo( nPartId, WIN_PRC_OVERMAT_IN, 'd')
local dOvermatLeft = EgtGetInfo( nPartId, WIN_PRC_OVERMAT_LEFT, 'd')
-- recupero le curve del raw e applico i sovramateriali
local nOut = EgtGetFirstNameInGroup( nGeoRawLayerId, WIN_GEO_OUT)
if not EgtOffsetCurve( nOut, dOvermatOut) then
EgtErase( nOut)
end
local nIn = EgtGetFirstNameInGroup( nGeoRawLayerId, WIN_GEO_IN)
if not EgtOffsetCurve( nIn, dOvermatIn) then
EgtErase( nIn)
end
local vRight = EgtGetNameInGroup( nGeoRawLayerId, WIN_GEO_RIGHT)
for i = 1, #vRight do
if not EgtOffsetCurve( vRight[i], dOvermatRight) then
EgtErase( vRight[i])
end
end
local vLeft = EgtGetNameInGroup( nGeoRawLayerId, WIN_GEO_LEFT)
for i = 1, #vLeft do
if not EgtOffsetCurve( vLeft[i], dOvermatLeft) then
EgtErase( vLeft[i])
end
end
-- creo la composita del grezzo a partire dalle curve
local vCrvs = EgtGetAllInGroup( nGeoRawLayerId)
local nRegion = CalcIntersectionRegion( vCrvs, nGeoRawLayerId)
local nCompo = EgtExtractSurfFrChunkLoops( nRegion, 0, nGeoRawLayerId)
-- aggiungo spessore
local dDimH = EgtGetInfo( nGeoLayerId, WIN_GEOHEIGHT, 'd')
EgtModifyCurveThickness( nCompo, - dDimH)
-- creo frame ausiliario
local vtX = EgtSV( nOut)
local frGeo = Frame3d( ORIG(), vtX, Z_AX() ^ vtX, Z_AX())
local nFrameId = EgtFrame( nGeoRawLayerId, frGeo)
local b3Raw = EgtGetBBoxRef( nCompo, GDB_BB.STANDARD, frGeo)
local ptMin = b3Raw:getMin()
ptMin:toGlob( frGeo)
EgtMove( nFrameId, ( ptMin - ORIG()))
EgtSetName( nFrameId, WIN_PRC_FRAME)
EgtErase( vCrvs)
EgtErase( nRegion)
end
----------------------------------------------------------------------------------
---------------------------------- SOLIDO ----------------------------------------
----------------------------------------------------------------------------------
local function GetReferenceCurve( nCrv, nOrigCrv, dOffs, nSurfTrim)
local nRes, nCnt = EgtTrimCurveWithRegion( nCrv, nSurfTrim, true, false)
if nCnt == 1 then
EgtOffsetCurve( nRes, dOffs)
return nRes
else
-- se più di un tratto interno alla regione considero solo quello che fa overlap con l'originale
for nId = nRes, nRes + nCnt - 1 do
EgtOffsetCurve( nId, dOffs)
if CheckExtensionOverlap( nId, nOrigCrv) then
return nId
end
end
end
end
---------------------------------------------------------------------
-- funzione che crea la guida per la superficie di trim, opportunamente estesa per avere booleane ben definite
local function CalcGuideExtension( nCrvId, nGeoId, nSemiProfile, nSurfTrimId, nLayerId)
local nGrpTmp = EgtGroup( nLayerId)
-- creo estensione della curva ( può essere fatta in tangenza perchè parto dalla curva di processing)
local nExtCrvId = EgtCurveCompo( nGrpTmp, nCrvId, false)
EgtAddCurveCompoLineTg( nExtCrvId, 10000, true)
EgtAddCurveCompoLineTg( nExtCrvId, 10000, false)
local nGuideId
if not nSemiProfile then
-- se bisettore controllo solamente la curva stessa
nGuideId = GetReferenceCurve( nExtCrvId, nCrvId, 0, nSurfTrimId)
-- piccola estensione per essere oltre il minimo indispensabile
EgtExtendCurveStartByLen( nGuideId, 2)
EgtExtendCurveEndByLen( nGuideId, 2)
else
-- se semiprofilo controllo estensione richiesta per la sua parte interna ed esterna
local nProfileId = EgtGetParent( nSemiProfile)
local nFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frFrame = EgtFR( nFrameId, GDB_ID.ROOT)
local b3SemiProfile = EgtGetBBoxRef( nSemiProfile, GDB_BB.STANDARD, frFrame)
-- parametri di trim
local dParS = GEO.INFINITO
local dParE = -1
-- parte in
local nInExtCrvId = EgtOffsetCurveAdv( nExtCrvId, b3SemiProfile:getMin():getX())
local nInId = GetReferenceCurve( nInExtCrvId, nCrvId, - b3SemiProfile:getMin():getX(), nSurfTrimId)
if nInId then
dParS = EgtCurveParamAtPoint( nExtCrvId, EgtSP( nInId))
dParE = EgtCurveParamAtPoint( nExtCrvId, EgtEP( nInId))
end
-- parte out
local nOutExtCrvId = EgtOffsetCurveAdv( nExtCrvId, b3SemiProfile:getMax():getX())
local nOutId = GetReferenceCurve( nOutExtCrvId, nCrvId, - b3SemiProfile:getMax():getX(), nSurfTrimId)
if nOutId then
dParS = min( dParS, EgtCurveParamAtPoint( nExtCrvId, EgtSP( nOutId)))
dParE = max( dParE, EgtCurveParamAtPoint( nExtCrvId, EgtEP( nOutId)))
end
-- aggiusto la curva estesa tenendo conto di quanto realmente serve per il corretto trim del solido
EgtTrimCurveStartEndAtParam( nExtCrvId, dParS, dParE)
nGuideId = nExtCrvId
end
EgtRelocateGlob( nGuideId, nLayerId)
EgtErase( nGrpTmp)
return nGuideId
end
---------------------------------------------------------------------
-- funzione che crea le superfici di trim
local function CreateTrimSurfs( vGeoIds, nLayerId, nMainGuideId, nMainProfileId)
-- creo la superficie di riferimento del solido originale per capire di quanto estendere le superfici di trim in modo da avere booleane ben definite tra le superfici
local b3Profile = GetProfileLocalBox( nMainProfileId)
local dRailOffs = EgtGetInfo( nMainProfileId, WIN_RAILOFFS, 'd') or 0
local nOffsMax = EgtOffsetCurveAdv( nMainGuideId, b3Profile:getMax():getX() - dRailOffs)
local nOffsMin = EgtOffsetCurveAdv( nMainGuideId, b3Profile:getMin():getX() - dRailOffs)
EgtInvertCurve( nOffsMin)
local nCompo = EgtCurveCompo( nLayerId, nOffsMax)
EgtAddCurveCompoLine( nCompo, EgtSP( nOffsMin))
EgtAddCurveCompoCurve( nCompo, nOffsMin)
EgtCloseCurveCompo( nCompo)
local nSurfTrim = EgtSurfFlatRegion( nLayerId, nCompo)
EgtSetStatus( nSurfTrim, GDB_ST.OFF)
EgtSetStatus( nCompo, GDB_ST.OFF)
local vTrimSurfs = {}
local tabPrcCrv = {}
for i = 1, #vGeoIds do
local nGuideId
local nTrimSurf
-- recupero profilo di riferimento dalla curva geo
local nSemiProfileId = EgtGetInfo( vGeoIds[i], WIN_SEMI_PROFILE, 'i')
-- 1) minizinken
if not nSemiProfileId then
nGuideId = CalcGuideExtension( vGeoIds[i], vGeoIds[i], nil, nSurfTrim, nLayerId)
EgtMove( nGuideId, Z_AX())
nTrimSurf = EgtSurfTmByExtrusion( nLayerId, nGuideId, - Z_AX() * 2 * b3Profile:getDimY(), WIN_SURF_APPROX)
EgtInvertSurf( nTrimSurf)
-- 2) controprofilo
else
-- recupero la curva di lavorazione associata e verifico se la sua superficie di trim è già stata calcolata ( una curva di lavorazione può essere associata
-- a più curve del geo)
local nPrcCrv = EgtGetInfo( vGeoIds[i], WIN_REF_PRC, 'i')
if nPrcCrv then
if tabPrcCrv[nPrcCrv] then
-- se la superficie di trim è già stata creata salvo associazione nella curva geo
EgtSetInfo( vGeoIds[i], WIN_REF_SURF, tabPrcCrv[nPrcCrv])
else
-- nel caso di trim di split con cambio profilo non deve essere usato il semiprofilo common salvato nel geo, ma devo usare quello sash
local sSemiProfileName = EgtGetName( nSemiProfileId)
if sSemiProfileName == WIN_MIXED_COMMON .. WIN_IN then
nSemiProfileId = EgtGetFirstNameInGroup( EgtGetParent( nSemiProfileId), WIN_SASH .. WIN_CTRIN)
elseif sSemiProfileName == WIN_MIXED_COMMON .. WIN_IN .. '1' then
nSemiProfileId = EgtGetFirstNameInGroup( EgtGetParent( nSemiProfileId), WIN_SASH .. WIN_CTRIN .. '1')
elseif sSemiProfileName == WIN_MIXED_COMMON .. WIN_IN .. '2' then
nSemiProfileId = EgtGetFirstNameInGroup( EgtGetParent( nSemiProfileId), WIN_SASH .. WIN_CTRIN .. '2')
end
-- riposiziono la curva di lavorazione in corrispondenza dell'outline
local dOffs = EgtGetInfo( vGeoIds[i], WIN_GEO_OFFS, 'd')
local nOffsCrv = EgtOffsetCurveAdv( nPrcCrv, - dOffs)
nGuideId = CalcGuideExtension( nOffsCrv, vGeoIds[i], nSemiProfileId, nSurfTrim, nLayerId)
EgtErase( nOffsCrv)
local nRefOutline = EgtGetInfo( vGeoIds[i], WIN_REF_OUTLINE, 'i')
if nRefOutline < 0 then
EgtInvertCurve( nGuideId)
end
-- recupero il controprofilo da estrudere
local sTrimProfileName = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_OFST .. EgtGetName( nSemiProfileId)
-- calcolo la superficie di estrusione
nTrimSurf = CreateProfileSurf( nGuideId, EgtGetParent( nSemiProfileId), sTrimProfileName, b3Profile:getDimX(), nLayerId)
tabPrcCrv[nPrcCrv] = nTrimSurf
end
end
end
-- taglio il solido principale
if nTrimSurf then
table.insert( vTrimSurfs, nTrimSurf)
EgtSetStatus( nTrimSurf, GDB_ST.OFF)
EgtErase( nGuideId)
EgtSetInfo( vGeoIds[i], WIN_REF_SURF, nTrimSurf)
end
end
EgtErase( nSurfTrim)
EgtErase( nCompo)
return vTrimSurfs
end
---------------------------------------------------------------------
-- funzione che calcola la curva guida per il solido principale
local function CalcSolidGuide( nOutlineId, nSolidLayerId, nProfileId, nGeoLayerId)
local nGuideId
local dExtraLinearLen = 400
if EgtGetType( nOutlineId) == GDB_TY.CRV_LINE then
-- se tratto lineare non ci sono problemi per l'estensione
nGuideId = EgtCopyGlob( nOutlineId, nSolidLayerId)
EgtExtendCurveStartByLen( nGuideId, dExtraLinearLen)
EgtExtendCurveEndByLen( nGuideId, dExtraLinearLen)
else
nGuideId = EgtCurveCompo( nSolidLayerId, nOutlineId, false)
-- recupero il tipo di estensione
local nGeoOut = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_OUT)
local bTangS = EgtGetInfo( nGeoOut, WIN_TANG_START, 'b')
local bTangE = EgtGetInfo( nGeoOut, WIN_TANG_END, 'b')
-- calcolo la lunghezza di estensione per l'arco in modo che la parte interna non si chiuda in una circonferenza
local dRad = EgtArcRadius( nOutlineId)
local dAng = EgtArcAngCenter( nOutlineId) * pi / 180
local b3Profile = GetProfileLocalBox( nProfileId)
local dInnerRad = dRad - abs( b3Profile:getMin():getX())
local dExtraLen = ( pi - 0.5 * dAng) * dInnerRad * dRad / dInnerRad - 2
if bTangS then
EgtAddCurveCompoLineTg( nGuideId, dExtraLinearLen, false)
else
EgtExtendCurveStartByLen( nGuideId, dExtraLen)
end
if bTangE then
EgtAddCurveCompoLineTg( nGuideId, dExtraLinearLen, true)
else
EgtExtendCurveEndByLen( nGuideId, dExtraLen)
end
end
EgtSetName( nGuideId, WIN_MAINGUIDE)
EgtSetStatus( nGuideId, GDB_ST.OFF)
return nGuideId
end
---------------------------------------------------------------------
-- funzione che crea la superficie di taglio corrispondente alle fresature del cambio profilo che separano le parti sash e fill
local function CalcMixedCurveTrimSurf( vMixedCurves, nSolidLayerId, dExtraLen)
local vStmInters = {}
for i = 1, #vMixedCurves do
local nSplitId = EgtGetInfo( vMixedCurves[i], WIN_MIXED_SPLIT_REF, 'i')
local vtDir = EgtSV( nSplitId)
local bFillOnSplitRight = EgtGetInfo( vMixedCurves[i], WIN_FILL_ON_SPLIT_RIGHT, 'b')
if bFillOnSplitRight then
vtDir = - vtDir
end
local nCrvTrim = EgtCopyGlob( vMixedCurves[i], nSolidLayerId)
EgtAddCurveCompoLine( nCrvTrim, EgtSP( nCrvTrim) + 3 * dExtraLen * vtDir, false)
EgtAddCurveCompoLine( nCrvTrim, EgtEP( nCrvTrim) - 3 * dExtraLen * vtDir)
EgtMove( nCrvTrim, Z_AX())
EgtSetStatus( nCrvTrim, GDB_ST.OFF)
vStmInters[i] = EgtSurfTmByExtrusion( nSolidLayerId, nCrvTrim, - 2 * dExtraLen * Z_AX())
EgtErase( nCrvTrim)
end
local nStmTrim = EgtSurfTmByTriangles( nSolidLayerId, vStmInters)
return nStmTrim
end
---------------------------------------------------------------------
-- funzione che crea il solido di un pezzo di telaio con cambio profilo
local function CalcMixedFrameSolid( nOutlineId, nSolidLayerId, nMainProfileId, nGeoLayerId, dGeoWidth)
-- a) solido principale
local nGuideId = CalcSolidGuide( nOutlineId, nSolidLayerId, nMainProfileId, nGeoLayerId)
EgtSetName( nGuideId, WIN_MAINGUIDE)
EgtSetStatus( nGuideId, GDB_ST.OFF)
-- creo i solidi corrispondenti alla parte sash e alla parte fill
local sSectionSash = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_SASH .. WIN_SECTION
local nMainSash = CreateProfileSurf( nGuideId, nMainProfileId, sSectionSash, 0, nSolidLayerId)
local sSectionFill = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_FILL .. WIN_SECTION
local nMainFill = CreateProfileSurf( nGuideId, nMainProfileId, sSectionFill, 0, nSolidLayerId)
-- calcolo le superfici di taglio corrispondenti alle fresature del cambio profilo che separano la parte sash e fill
local nMixedIntersectionsGrp = EgtGetFirstNameInGroup( EgtGetParent( nSolidLayerId), WIN_MIXED_CURVES)
local vIntersections = EgtGetNameInGroup( nMixedIntersectionsGrp, WIN_MIXED_MILLING .. WIN_IN .. '1')
local nStmTrim = CalcMixedCurveTrimSurf( vIntersections, nSolidLayerId, dGeoWidth)
-- taglio le parti sash e fill e le riunisco in una sola superficie
EgtSurfTmIntersect( nMainFill, nStmTrim)
EgtSurfTmSubtract( nMainSash, nStmTrim)
EgtErase( nStmTrim)
EgtSurfTmAdd( nMainSash, nMainFill)
EgtErase( nMainFill)
local nMainSolid = nMainSash
EgtSetName( nMainSolid, WIN_SRF_MAIN)
-- creo una copia dell'estrusione principale ( usata per ferramenta)
local nOrigMainExtrusionId = EgtCopy( nMainSolid, nSolidLayerId)
EgtSetName( nOrigMainExtrusionId, WIN_SRF_ORIGMAIN)
EgtSetStatus( nOrigMainExtrusionId, GDB_ST.OFF)
-- b) trim start
local vPrevGeoIds = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_LEFT)
local vTrimStart = CreateTrimSurfs( vPrevGeoIds, nSolidLayerId, nGuideId, nMainProfileId)
for i = 1, #vTrimStart do
EgtSurfTmIntersect( nMainSolid, vTrimStart[i])
end
-- c) trim end
local vNextGeoIds = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_RIGHT)
local vTrimEnd = CreateTrimSurfs( vNextGeoIds, nSolidLayerId, nGuideId, nMainProfileId)
for i = 1, #vTrimEnd do
EgtSurfTmIntersect( nMainSolid, vTrimEnd[i])
end
return nMainSolid
end
---------------------------------------------------------------------
-- funzione che crea la superficie di trim per uno split coinvolto da cambio profilo ( controprofilo della parte sash dei vicini e fresatura)
local function CreateMixedSplitTrimSurfs( vGeoCrvs, bStart, nSolidLayerId, nSplitId, nGuideId, nMainProfileId, dGeoWidth)
-- superfici di trim
local vTrimSurfs = CreateTrimSurfs( vGeoCrvs, nSolidLayerId, nGuideId, nMainProfileId)
-- recupero la fresatura
local nMixedIntersGrp = EgtGetFirstNameInGroup( EgtGetParent( nSolidLayerId), WIN_MIXED_CURVES)
local nMillingCrv = EgtGetFirstNameInGroup( nMixedIntersGrp, WIN_MIXED_MILLING .. EgtIf( bStart, WIN_LEFT, WIN_RIGHT) .. '1')
if nMillingCrv then
-- costruisco il solido associato alla fresatura
local nGuide = EgtCopyGlob( nMillingCrv, nSolidLayerId)
EgtAddCurveCompoLineTg( nGuide, 10, true)
EgtAddCurveCompoLineTg( nGuide, 10, false)
local vtDir = EgtSV( nSplitId)
if bStart then
vtDir = - vtDir
end
EgtAddCurveCompoLine( nGuide, EgtEP( nGuide) + 2 * dGeoWidth * vtDir)
EgtAddCurveCompoLine( nGuide, EgtSP( nGuide) + 2 * dGeoWidth * vtDir, false)
EgtCloseCurveCompo( nGuide)
EgtMove( nGuide, 0.01 * Z_AX())
local nMillStm = EgtSurfTmByRegionExtrusion( nSolidLayerId, nGuide, ( EgtCurveThickness( nGuide) - 2) * Z_AX())
-- lo sottraggo alle superfici di trim
for i = 1, #vTrimSurfs do
EgtSurfTmSubtract( vTrimSurfs[i], nMillStm)
end
EgtErase( nGuide)
EgtErase( nMillStm)
end
return vTrimSurfs
end
---------------------------------------------------------------------
-- funzione che completa il semiprofilo per creare una sezione da estrudere per il solido di un mixed split
local function CreateExtrusionSection( nSemiProfileId)
-- recupero il Ref e lo taglio con il semiprofilo
local nProfileId = EgtGetParent( nSemiProfileId)
local nRefId = EgtGetFirstNameInGroup( nProfileId, WIN_REF)
local nSection = EgtCopyGlob( nRefId, nProfileId)
local dPar1 = EgtCurveParamAtPoint( nSection, EgtSP( nSemiProfileId))
local dPar2 = EgtCurveParamAtPoint( nSection, EgtEP( nSemiProfileId))
EgtTrimCurveStartEndAtParam( nSection, dPar2, dPar1)
EgtAddCurveCompoCurve( nSection, nSemiProfileId, false)
return nSection
end
---------------------------------------------------------------------
-- funzione che crea il solido di un pezzo di split coinvolto da cambio profilo
local function CalcMixedSplitSolid( nOutlineId, nSolidLayerId, nMainProfileId, nGeoLayerId, dGeoWidth)
-- a) solido principale
local nGuideId = CalcSolidGuide( nOutlineId, nSolidLayerId, nMainProfileId, nGeoLayerId)
-- creo un solido per ogni lato dello split
local vSolids = {}
for i = 1, 2 do
-- verifico se ho un solo profilo definito
local nSemiProfile = EgtGetFirstNameInGroup( nMainProfileId, WIN_IN .. tostring( i))
if nSemiProfile then
local nSection = CreateExtrusionSection( nSemiProfile)
vSolids[i] = CreateProfileSurfById( nGuideId, nMainProfileId, nSection, 0, nSolidLayerId)
else
-- creo i solidi sash e fill
local nSemiProfileSash = EgtGetFirstNameInGroup( nMainProfileId, WIN_SASH .. WIN_IN .. tostring( i))
local nSashSection = CreateExtrusionSection( nSemiProfileSash)
local nSashSolid = CreateProfileSurfById( nGuideId, nMainProfileId, nSashSection, 0, nSolidLayerId)
local nSemiProfileFill = EgtGetFirstNameInGroup( nMainProfileId, WIN_FILL .. WIN_IN .. tostring( i))
local nFillSection = CreateExtrusionSection( nSemiProfileFill)
local nFillSolid = CreateProfileSurfById( nGuideId, nMainProfileId, nFillSection, 0, nSolidLayerId)
-- calcolo le superfici di taglio corrispondenti alle fresature del cambio profilo che separano la parte sash e fill
local nMixedIntersectionsGrp = EgtGetFirstNameInGroup( EgtGetParent( nSolidLayerId), WIN_MIXED_CURVES)
local vIntersections = EgtGetNameInGroup( nMixedIntersectionsGrp, WIN_MIXED_MILLING .. EgtIf( i == 1, WIN_OUT, WIN_IN) .. '1')
local nStmTrim = CalcMixedCurveTrimSurf( vIntersections, nSolidLayerId, dGeoWidth)
-- costruisco il solido combinando opportunamente le parti sash e fill
EgtSurfTmIntersect( nFillSolid, nStmTrim)
EgtSurfTmSubtract( nSashSolid, nStmTrim)
EgtErase( nStmTrim)
EgtSurfTmAdd( nSashSolid, nFillSolid)
EgtErase( nFillSolid)
vSolids[i] = nSashSolid
end
end
-- taglio e unisco le due metà
local b3Profile = GetProfileLocalBox( nMainProfileId)
local dOffs = ( b3Profile:getMax():getX() + b3Profile:getMin():getX()) * 0.5
local nOffsGuide = EgtOffsetCurveAdv( nGuideId, dOffs)
EgtMove( nOffsGuide, 2 * Z_AX())
local nStmTrim = EgtSurfTmByExtrusion( nSolidLayerId, nOffsGuide, - Z_AX() * ( b3Profile:getDimY() + 5))
EgtSurfTmCut( vSolids[1], nStmTrim, true, false)
EgtSurfTmCut( vSolids[2], nStmTrim, false, false)
EgtErase( nStmTrim)
local nMainExtrusionId = EgtSurfTmByTriangles( nSolidLayerId, vSolids)
EgtSetName( nMainExtrusionId, WIN_SRF_MAIN)
-- creo una copia ( usata per calcolo ferramenta)
local nOrigMainExtrusionId = EgtCopy( nMainExtrusionId, nSolidLayerId)
EgtSetName( nOrigMainExtrusionId, WIN_SRF_ORIGMAIN)
EgtSetStatus( nOrigMainExtrusionId, GDB_ST.OFF)
-- b) trim start
local vGeoLeft = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_LEFT)
local vTrimStart = CreateMixedSplitTrimSurfs( vGeoLeft, true, nSolidLayerId, nOutlineId, nGuideId, nMainProfileId, dGeoWidth)
for i = 1, #vTrimStart do
EgtSurfTmIntersect( nMainExtrusionId, vTrimStart[i])
end
-- c) trim end
local vGeoRight = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_RIGHT)
local vTrimEnd = CreateMixedSplitTrimSurfs( vGeoRight, false, nSolidLayerId, nOutlineId, nGuideId, nMainProfileId, dGeoWidth)
for i = 1, #vTrimEnd do
EgtSurfTmIntersect( nMainExtrusionId, vTrimEnd[i])
end
return nMainExtrusionId
end
---------------------------------------------------------------------
-- funzione che crea il solido del pezzo
local function CalcSolid( nPartId, nOutlineId)
-- creo layer per solido
local nSolidLayerId = EgtGroup( nPartId)
EgtSetName( nSolidLayerId, WIN_SOLID)
-- recupero profilo principale
local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN)
-- recupero geo e la sua larghezza
local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
local dGeoWidth = EgtGetInfo( nGeoLayerId, WIN_GEOWIDTH, 'd')
-- gestione speciale per pezzi con CAMBIO PROFILO
local nPrfChange = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'i') or WIN_PRF_CHANGE_TYPES.NULL
if nPrfChange > 0 then
if EgtGetName( nOutlineId) == WIN_SPLIT then
return CalcMixedSplitSolid( nOutlineId, nSolidLayerId, nMainProfileId, nGeoLayerId, dGeoWidth)
else
return CalcMixedFrameSolid( nOutlineId, nSolidLayerId, nMainProfileId, nGeoLayerId, dGeoWidth)
end
end
-- a) creo il solido di estrusione principale
local nGuideId = CalcSolidGuide( nOutlineId, nSolidLayerId, nMainProfileId, nGeoLayerId)
local sSection = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_SECTION
local nMainExtrusionId = CreateProfileSurf( nGuideId, nMainProfileId, sSection, 0, nSolidLayerId)
EgtSetName( nMainExtrusionId, WIN_SRF_MAIN)
-- creo una copia ( usata per calcolo ferramenta)
local nOrigMainExtrusionId = EgtCopy( nMainExtrusionId, nSolidLayerId)
EgtSetName( nOrigMainExtrusionId, WIN_SRF_ORIGMAIN)
EgtSetStatus( nOrigMainExtrusionId, GDB_ST.OFF)
-- b) trim con i controprofili su start
local vGeoLeft = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_LEFT)
local vTrimStart = CreateTrimSurfs( vGeoLeft, nSolidLayerId, nGuideId, nMainProfileId)
for i = 1, #vTrimStart do
EgtSurfTmIntersect( nMainExtrusionId, vTrimStart[i])
end
-- c) trim con i controprofili su end
local vGeoRight = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_RIGHT)
local vTrimEnd = CreateTrimSurfs( vGeoRight, nSolidLayerId, nGuideId, nMainProfileId)
for i = 1, #vTrimEnd do
EgtSurfTmIntersect( nMainExtrusionId, vTrimEnd[i])
end
return nMainExtrusionId
end
---------------------------------------------------------------------
-- funzione che crea il solido del Fill
local function CalcFillSolid( nPartId, nGeoLayerId)
-- creo layer per solido
local nSolidLayerId = EgtGroup( nPartId)
EgtSetName( nSolidLayerId, WIN_SOLID)
-- creo compo dalle curve del geo
local vGeoList = EgtGetAllInGroup( nGeoLayerId)
local nCompoOutlineId = EgtCurveCompo( nSolidLayerId, vGeoList, false)
-- recupero spessore vetro
local dGlassThickness = EgtGetInfo( nGeoLayerId, WIN_GLASSTHICKNESS, 'd')
local nSurfId = EgtSurfTmByRegionExtrusion( nSolidLayerId, nCompoOutlineId, Z_AX() * dGlassThickness)
EgtErase( nCompoOutlineId)
end
----------------------------------------------------------------------------------
-- funzione che aggiorna il solido principale con quello associato ad una lavorazione partendo dalla sua curva
local function UpdateSolidWithProcessingCrv( nProcId, nSolidId, nLayerId)
if not EgtCurveIsClosed( nProcId) then
return
end
local vtExtr = EgtCurveExtrusion( nProcId)
local dThick = EgtCurveThickness( nProcId)
local nRefCrv = nProcId
-- se solidi semplificati approssimo in modo grossolano per velocizzare operazioni di subtract ( soprattuto su archi)
if s_bSimplSolid then
nRefCrv = EgtCopyGlob( nProcId, nLayerId)
EgtApproxCurve( nRefCrv, GDB_CA.LINES, s_dSimplSolidApprox)
end
local nProcSolidId = EgtSurfTmByRegionExtrusion( nLayerId, nRefCrv, ( dThick - 0.05) * vtExtr)
-- piccola traslazione per non essere a filo con la superficie
EgtMove( nProcSolidId, 0.05 * vtExtr)
-- sottraggo al solido
EgtSurfTmSubtract( nSolidId, nProcSolidId)
EgtErase( nProcSolidId)
if s_bSimplSolid then
EgtErase( nRefCrv)
end
end
----------------------------------------------------------------------------------
---------------------------------- DOWELS ----------------------------------------
----------------------------------------------------------------------------------
-- funzione che recupera la lunghezza del dowel
local function CalcDowelLen( nDowelId, sKey, bFullOrShort)
local sDefaultKey = EgtIf( bFullOrShort, WIN_DWL_TOP_PERP_LEN, WIN_DWL_TOP_PARA_LEN)
local dLen = EgtGetInfo( nDowelId, sKey, 'd') or EgtGetInfo( nDowelId, sDefaultKey, 'd')
dLen = dLen + s_dDowelTol
return dLen
end
---------------------------------------------------------------------
-- funzione che calcola il riferimento dove posizionare i dowels
local function CreateDowelFrameDest( nPrevRight, nCurrLeft, nRefOutline, bCurrFullOrShort)
local vtZ
local ptOrig
if EgtGetType( nRefOutline) == GDB_TY.CRV_LINE then
vtZ = EgtEV( nRefOutline)
ptOrig = EgtIf( bCurrFullOrShort, EgtEP( nRefOutline), EgtSP( nRefOutline))
else
-- se pezzo ad arco, recupero la direzione dalla curva nel punto estremo del geo
local ptRef = EgtIf( bCurrFullOrShort, EgtSP( nPrevRight), EgtEP( nCurrLeft))
local _, ptInt, dPar = EgtPointCurveDist( ptRef, nRefOutline)
vtZ = EgtUV( nRefOutline, dPar, -1)
ptOrig = ptInt
end
local frDest = Frame3d( ptOrig, - vtZ)
return frDest
end
---------------------------------------------------------------------
-- funzione che posiziona il dowel tramite i riferimenti
local function PositionDowel( nDowelId, frOrig, frDest, vtDir, nSurfId)
-- posiziono il dowel utilizzando i riferimenti
EgtTransform( nDowelId, frOrig, GDB_RT.GLOB)
EgtTransform( nDowelId, frDest, GDB_RT.GLOB)
EgtMove( nDowelId, 3000 * vtDir)
-- creo il tool corrispondente al dowel
local dRad = EgtArcRadius( nDowelId)
EgtCAvSetStdTool( s_dDowelTol, 2 * dRad, 0)
-- calcolo spostamento per posizionarlo in corrispondenza della superficie
local dStart = EgtCAvToolPosStm( EgtCP( nDowelId), - vtDir, nSurfId, - vtDir)
EgtMove( nDowelId, - dStart * vtDir)
end
---------------------------------------------------------------------
-- funzione che crea il dowel e lo sottrae al solido
local function CreateDowel( nOrigDowelId, nLayerId, frOrig, frDest, vtDir, nTestSurfId, dLen, sDowelSide, nMainExtrusionId)
-- vtDir rivolta verso interno del pezzo
local nDowelId = EgtCopyGlob( nOrigDowelId, nLayerId)
EgtSetColor( nDowelId, Color3d( 128, 128, 128))
-- posiziono il dowel
PositionDowel( nDowelId, frOrig, frDest, vtDir, nTestSurfId)
-- assegno estrusione e spessore
EgtModifyCurveExtrusion( nDowelId, - vtDir)
EgtModifyCurveThickness( nDowelId, - dLen)
-- setto info di lavorazione
EgtSetInfo( nDowelId, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.HOLE)
EgtSetInfo( nDowelId, WIN_PRC_SIDE, sDowelSide)
-- eventuale aggiornamento del solido
if nMainExtrusionId then
UpdateSolidWithProcessingCrv( nDowelId, nMainExtrusionId, nLayerId)
end
return nDowelId
end
---------------------------------------------------------------------
-- funzione che calcola i dowels tra due pezzi
local function CalcDowels( nOrigOutlineId, nOrigPrevOutlineId, bSashOrFrame, nBottomRail)
-- TODO correzione per non far uscire i dowels
-- se soglia non ci sono dowels
if EgtGetInfo( nOrigOutlineId, WIN_THRESHOLD, 'b') or EgtGetInfo( nOrigPrevOutlineId, WIN_THRESHOLD, 'b') then
return
end
-- recupero i pezzi
local nPart = EgtGetInfo( nOrigOutlineId, WIN_REF_PART, 'i')
local nPrevPart = EgtGetInfo( nOrigPrevOutlineId, WIN_REF_PART, 'i')
if nBottomRail then
if EgtGetName( nOrigOutlineId) == WIN_BOTTOM then
local vParts = EgtGetInfo( nOrigOutlineId, WIN_REF_BOTTOMRAIL_PART, 'vi')
nPart = vParts[nBottomRail]
else
local vParts = EgtGetInfo( nOrigPrevOutlineId, WIN_REF_BOTTOMRAIL_PART, 'vi')
nPrevPart = vParts[nBottomRail]
end
end
-- recupero i layer delle lavorazioni
local nLayerId = EgtGetFirstNameInGroup( nPart, WIN_PRC)
local nPrevLayerId = EgtGetFirstNameInGroup( nPrevPart, WIN_PRC)
-- recupero i profili
local nProfileLay = EgtGetFirstNameInGroup( nPart, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLay, WIN_PRF_MAIN)
local nPrevProfileLay = EgtGetFirstNameInGroup( nPrevPart, WIN_PROFILE)
local nPrevProfileId = EgtGetFirstNameInGroup( nPrevProfileLay, WIN_PRF_MAIN)
-- copio curve outlines
local nOutlineId = EgtCopyGlob( nOrigOutlineId, nLayerId)
local nPrevOutlineId = EgtCopyGlob( nOrigPrevOutlineId, nLayerId)
if nBottomRail then
-- eventuale offset per bottomrail
local dOffs
local nRefCrv
if EgtGetName( nOutlineId) == WIN_BOTTOM then
nRefCrv = nOutlineId
dOffs = EgtGetInfo( nProfileId, WIN_RAILOFFS, 'd')
else
nRefCrv = nPrevOutlineId
dOffs = EgtGetInfo( nPrevProfileId, WIN_RAILOFFS, 'd')
end
EgtOffsetCurve( nRefCrv, - dOffs)
end
-- recupero le curve di riferimento dei geo ( right per il prev e left per il corrente)
local nGeo = EgtGetFirstNameInGroup( nPart, WIN_GEO)
local nPrevGeo = EgtGetFirstNameInGroup( nPrevPart, WIN_GEO)
local vPrevGeoCrvs = EgtGetNameInGroup( nPrevGeo, WIN_GEO_RIGHT)
local nPrevRight = vPrevGeoCrvs[1]
for i = 2, #vPrevGeoCrvs do
local nRefOutline = EgtGetInfo( vPrevGeoCrvs[i], WIN_REF_OUTLINE, 'i')
if nRefOutline == nOrigOutlineId then
nPrevRight = vPrevGeoCrvs[i]
break
end
end
local vCurrGeoCrvs = EgtGetNameInGroup( nGeo, WIN_GEO_LEFT)
local nCurrLeft = vCurrGeoCrvs[1]
for i = 2, #vCurrGeoCrvs do
local nRefOutline = EgtGetInfo( vCurrGeoCrvs[i], WIN_REF_OUTLINE, 'i')
if nRefOutline == nOrigPrevOutlineId then
nCurrLeft = vCurrGeoCrvs[i]
break
end
end
-- recupero i solidi
local nPrevSolidId, nSolidId, nPrevSolidLay, nSolidLay
if s_bCalcSolid then
nSolidLay = EgtGetFirstNameInGroup( nPart, WIN_SOLID)
nSolidId = EgtGetFirstNameInGroup( nSolidLay, WIN_SRF_MAIN)
nPrevSolidLay = EgtGetFirstNameInGroup( nPrevPart, WIN_SOLID)
nPrevSolidId = EgtGetFirstNameInGroup( nPrevSolidLay, WIN_SRF_MAIN)
end
-- recupero il tipo di giunzione
local nJointType
if nBottomRail then
if EgtGetName( nOutlineId) == WIN_BOTTOM then
nJointType = WIN_PART_JNT.SHORT
else
nJointType = WIN_PART_JNT.FULL
end
else
local vJointTypes = EgtGetInfo( nOutlineId, WIN_STARTJOINT, 'vi')
local vPrevOutlines = EgtGetInfo( nOutlineId, WIN_PREV_OUTLINES, 'vi')
for i = 1, #vPrevOutlines do
if vPrevOutlines[i] == nOrigPrevOutlineId then
nJointType = vJointTypes[i]
break
end
end
end
if nJointType == WIN_PART_JNT.ANGLED then
-- TO DO
elseif nJointType == WIN_PART_JNT.FULL then
-- calcolo il riferimento del profilo
local nFrameProfile = EgtGetFirstNameInGroup( nPrevProfileId, WIN_SECTIONFRAME)
local frOrig = EgtFR( nFrameProfile, GDB_ID.ROOT)
frOrig:invert()
-- calcolo il riferimento su cui posizionare i dowels
local frDest = CreateDowelFrameDest( nPrevRight, nCurrLeft, nPrevOutlineId, true)
-- recupero info con la lunghezza ( dipendono dal profilo del pezzo full quindi dal corrente)
local sLenKey = WIN_DWL_TOP_PERP_LEN
local sPrevLenKey = WIN_DWL_TOP_PARA_LEN
if EgtGetName( nOutlineId) == WIN_BOTTOM then
sLenKey = WIN_DWL_BOTTOM_PERP_LEN
sPrevLenKey = WIN_DWL_BOTTOM_PARA_LEN
elseif EgtExistsInfo( nPart, WIN_SASHTYPE) then
-- verifico se è inactive sash dalla info settata per lavorazione
sLenKey = WIN_DWL_INACTIVE_PERP_LEN
sPrevLenKey = WIN_DWL_INACTIVE_PARA_LEN
end
-- superficie test per il posizionamento dei dowels : è la superficie in del pezzo full
local nTestSurf
if not s_bCalcSolid or s_bSimplSolid then
local sCtrIn = WIN_OFST .. GetProfileCtrIn( nOrigOutlineId, nPrevOutlineId, nProfileId, false) -- controprofilo in del pezzo corrente
nTestSurf = CreateProfileSurf( nOrigOutlineId, nProfileId, sCtrIn, 100, nLayerId)
else
-- è la superficie che viene utilizzata per trimmare l'end del pezzo prev
local nOrigSurf = EgtGetInfo( nPrevRight, WIN_REF_SURF, 'i')
nTestSurf = EgtCopyGlob( nOrigSurf, nLayerId)
end
local nTestSurfInverted = EgtCopyGlob( nTestSurf, nLayerId)
EgtInvertSurf( nTestSurfInverted)
-- analizzo le singole file di dowels
for k = 0, 3 do
-- recupero i dowels della fila k-esima
local vDowels = EgtGetNameInGroup( nPrevProfileId, WIN_DOWEL .. 'Row' .. tostring( k))
if #vDowels > 0 then
for i = 1, #vDowels do
-- dowels per pezzo corrente ( full)
local dLenFull = CalcDowelLen( vDowels[i], sLenKey, true)
CreateDowel( vDowels[i], nLayerId, frOrig, frDest, - frDest:getVersZ(), nTestSurfInverted, dLenFull, WIN_PRC_SIDETYPE.IN, nSolidId)
-- dowels per prezzo precedente ( short)
local dLenShort = CalcDowelLen( vDowels[i], sPrevLenKey, false)
CreateDowel( vDowels[i], nPrevLayerId, frOrig, frDest, frDest:getVersZ(), nTestSurf, dLenShort, WIN_PRC_SIDETYPE.RIGHT, nPrevSolidId)
end
end
end
EgtErase( nTestSurf)
EgtErase( nTestSurfInverted)
elseif nJointType == WIN_PART_JNT.SHORT then
-- calcolo il riferimento del profilo
local nFrameProfile = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frOrig = EgtFR( nFrameProfile, GDB_ID.ROOT)
frOrig:invert()
-- calcolo il riferimento su cui posizionare i dowels
local frDest = CreateDowelFrameDest( nPrevRight, nCurrLeft, nOutlineId, false)
-- recupero info con la lunghezza ( dipendono dal profilo del pezzo full, quindi da prezzo prev)
local sLenKey = WIN_DWL_TOP_PARA_LEN
local sPrevLenKey = WIN_DWL_TOP_PERP_LEN
if EgtGetName( nPrevOutlineId) == WIN_BOTTOM then
if not nBottomRail then
sLenKey = WIN_DWL_BOTTOM_PARA_LEN
sPrevLenKey = WIN_DWL_BOTTOM_PERP_LEN
else
sLenKey = WIN_DWL_BOTTOMRAIL_PARA_LEN
sPrevLenKey = WIN_DWL_BOTTOMRAIL_PERP_LEN
end
elseif EgtExistsInfo( nPrevPart, WIN_SASHTYPE) then
-- verifico se è inactive sash dalla info settata per lavorazione
sLenKey = WIN_DWL_INACTIVE_PARA_LEN
sPrevLenKey = WIN_DWL_INACTIVE_PERP_LEN
end
-- superficie test per il posizionamento dei dowels
-- è il controprofilo in del pezzo full quindi è la stessa superficie che viene utilizzata per trimmare lo start del pezzo corrente
local nTestSurf
if not s_bCalcSolid or s_bSimplSolid then
local sCtrIn = WIN_OFST .. GetProfileCtrIn( nOrigPrevOutlineId, nOutlineId, nPrevProfileId, true) -- controprofilo del pezzo full
nTestSurf = CreateProfileSurf( nOrigPrevOutlineId, nPrevProfileId, sCtrIn, 100, nLayerId)
else
local nOrigSurf = EgtGetInfo( nCurrLeft, WIN_REF_SURF, 'i')
nTestSurf = EgtCopyGlob( nOrigSurf, nLayerId)
end
local nTestSurfInverted = EgtCopyGlob( nTestSurf, nLayerId)
EgtInvertSurf( nTestSurfInverted)
-- analizzo le singole file di dowels
for k = 0, 3 do
-- recupero i dowels sulla fila k-esima
local vDowels = EgtGetNameInGroup( nProfileId, WIN_DOWEL .. 'Row' .. tostring(k))
if #vDowels > 0 then
for i = 1, #vDowels do
-- dowels per pezzo corrente ( short)
local dLenShort = CalcDowelLen( vDowels[i], sLenKey, false)
CreateDowel( vDowels[i], nLayerId, frOrig, frDest, - frDest:getVersZ(), nTestSurf, dLenShort, WIN_PRC_SIDETYPE.LEFT, nSolidId)
-- dowels per prezzo precedente ( full)
local dLenFull = CalcDowelLen( vDowels[i], sPrevLenKey, true)
CreateDowel( vDowels[i], nPrevLayerId, frOrig, frDest, frDest:getVersZ(), nTestSurfInverted, dLenFull, WIN_PRC_SIDETYPE.IN, nPrevSolidId)
end
end
end
EgtErase( nTestSurf)
EgtErase( nTestSurfInverted)
end
EgtErase( nOutlineId)
EgtErase( nPrevOutlineId)
end
---------------------------------------------------------------------
-- funzione che calcola i dowels tra uno split e i pezzi sui cui poggia
local function CalcSplitDowels( nSplitId, bStartOrEnd)
-- TO DO : da gestire incrocio dowels di tre pezzi
-- TO DO : gestione split non lineare
-- recupero il pezzo dello split
local nSplitPart = EgtGetInfo( nSplitId, WIN_REF_PART, 'i')
-- recupero il profilo originale dello split e il suo frame
local nSplitProfile = GetOutlineProfileId( nSplitId, false)
local nSplitProfileFrameId = EgtGetFirstNameInGroup( nSplitProfile, WIN_SECTIONFRAME)
local frOrig = EgtFR( nSplitProfileFrameId, GDB_ID.ROOT)
frOrig:invert()
-- recupero il gruppo delle lavorazioni
local nSplitLayerId = EgtGetFirstNameInGroup( nSplitPart, WIN_PRC)
-- recupero eventuale solido e superifici usate per il suo trim
local nSplitSolidId
if s_bCalcSolid then
local nSplitSolidLayerId = EgtGetFirstNameInGroup( nSplitPart, WIN_SOLID)
nSplitSolidId = EgtGetFirstNameInGroup( nSplitSolidLayerId, WIN_SRF_MAIN)
end
-- indviduo il lato su cui andranno i dowels
local sSplitDowelSide = EgtIf( bStartOrEnd, WIN_PRC_SIDETYPE.LEFT, WIN_PRC_SIDETYPE.RIGHT)
-- recupero le curve del geo e la superficie del pezzo ( per verificare se dowel interno)
local nSplitGeo = EgtGetFirstNameInGroup( nSplitPart, WIN_GEO)
local vGeoCrvs = EgtGetNameInGroup( nSplitGeo, EgtIf( bStartOrEnd, WIN_LEFT, WIN_RIGHT))
local nSplitSurf = EgtGetFirstNameInGroup( nSplitGeo, WIN_GEO_SURF)
-- verifico se necessario calcolare le superifici di trim associate alle curve del geo
local vAuxSurfs = {}
if not s_bCalcSolid or s_bSimplSolid then
-- simulo la guida per il calcolo del solido
local nGuideId = CalcSolidGuide( nSplitId, nSplitLayerId, nSplitProfile, nSplitGeo)
if EgtGetInfo( nSplitId, WIN_SPLITTYPE, 'i') == WIN_SPLITTYPES.MIXED then
vAuxSurfs = CreateMixedSplitTrimSurfs( vGeoCrvs, bStartOrEnd, nSplitLayerId, nSplitId, nGuideId, nSplitProfile, 100)
else
vAuxSurfs = CreateTrimSurfs( vGeoCrvs, nSplitLayerId, nGuideId, nSplitProfile)
end
EgtErase( nGuideId)
end
for i = 1, #vGeoCrvs do
-- se la curva non ha lavorazione associata allora il pezzo non influisce direttamente sullo split e può essere ignorato
local nPrcRef = EgtGetInfo( vGeoCrvs[i], WIN_REF_PRC, 'i')
if nPrcRef then
local nOrigOutline = abs( EgtGetInfo( vGeoCrvs[i], WIN_REF_OUTLINE, 'i'))
-- verifico se soglia ( in quel caso non ci sono dowels quindi va ignorato)
local bThreshold = EgtGetInfo( nOrigOutline, WIN_THRESHOLD, 'b') or false
if not bThreshold then
-- recupero il pezzo associato e il suo outline di riferimento
local nPartId = FindAssociatedPart( nOrigOutline, true)
local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i')
local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
local nGeoCrvId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_IN)
local sDowelSide = WIN_PRC_SIDETYPE.IN
-- se split verifico se interferisce con lato in o out del geo
if EgtGetName( nOutlineId) == WIN_SPLIT then
local _, _, nSide = EgtPointCurveDistSide( EgtMP( nSplitId), nOutlineId, Z_AX())
if nSide == 1 then
nGeoCrvId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_OUT)
sDowelSide = WIN_PRC_SIDETYPE.OUT
end
end
-- calcolo il frame di destinazione
local ptOrig = EgtIf( bStartOrEnd, EgtSP( nSplitId), EgtEP( nSplitId))
local frDest = Frame3d( ptOrig, - EgtSV( nSplitId))
-- recupero il layer con le lavorazioni
local nLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PRC)
-- nel layer dei profili del pezzo aggiungo il profilo dello split posizionato correttamente
local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nSplitProfileCopyId = EgtCopy( nSplitProfile, nProfileLayerId)
CopyInfo( nSplitProfileCopyId, nSplitProfile, WIN_PROFILETYPE)
EgtSetName( nSplitProfileCopyId, WIN_PRF_SPLIT)
-- posiziono il profilo sulla curva di split
EgtTransform( EgtGetAllInGroup( nSplitProfileCopyId), frOrig, GDB_RT.GLOB)
EgtChangeGroupFrame( nSplitProfileCopyId, frDest, GDB_RT.GLOB)
-- recupero eventuale solido
local nSolidId
if s_bCalcSolid then
local nSolidLayerId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID)
nSolidId = EgtGetFirstNameInGroup( nSolidLayerId, WIN_SRF_MAIN)
end
-- recupero le chiavi delle lunghezze ( dipendono dal profilo del pezzo su cui poggia lo split)
local sSplitLenKey = WIN_DWL_TOP_PARA_LEN
local sLenKey = WIN_DWL_TOP_PERP_LEN
if EgtGetName( nOutlineId) == WIN_BOTTOM then
-- verifico se ha bottomrails
local nBottomRails = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL, 'i') or 0
if nBottomRails == 0 then
sSplitLenKey = WIN_DWL_BOTTOM_PARA_LEN
sLenKey = WIN_DWL_BOTTOM_PERP_LEN
else
sSplitLenKey = WIN_DWL_RAILBOTTOM_PARA_LEN
sLenKey = WIN_DWL_RAILBOTTOM_PERP_LEN
end
elseif EgtGetName( nOutlineId) == WIN_SPLIT then
sSplitLenKey = WIN_DWL_SPLIT_PARA_LEN
sLenKey = WIN_DWL_SPLIT_PERP_LEN
end
-- creo la superficie di test per il posizionamento dei dowels
local nTrimSurf = EgtGetInfo( vGeoCrvs[i], WIN_REF_SURF, 'i')
local nTestSurf = EgtCopyGlob( nTrimSurf, nSplitLayerId)
local nTestSurfInverted = EgtCopyGlob( nTestSurf, nSplitLayerId)
EgtInvertSurf( nTestSurfInverted)
-- calcolo le direzioni entranti nei pezzi
local vtSplitDir = EgtIf( bStartOrEnd, - frDest:getVersZ(), frDest:getVersZ())
local vtDir = EgtIf( bStartOrEnd, - EgtSV( nSplitId), EgtSV( nSplitId))
-- recupero la superficie del pezzo per verificare se dowel interno
local nGeo = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
local nSurf = EgtGetFirstNameInGroup( nGeo, WIN_GEO_SURF)
-- aggiungo i dowels
local vDowels = EgtGetNameInGroup( nSplitProfile, WIN_DOWEL .. '*') or {}
for i = 1, #vDowels do
-- split
local dLen1 = CalcDowelLen( vDowels[i], sSplitLenKey, false)
local nDowel1 = CreateDowel( vDowels[i], nSplitLayerId, frOrig, frDest, vtSplitDir, nTestSurf, dLen1, sSplitDowelSide, nSplitSolidId)
-- verifico se dowel è interno al pezzo ( TO DO : da migliorare!)
local ptTest = EgtCP( nDowel1) - vtSplitDir * EgtCurveThickness( nDowel1)
local nTestPoint = EgtPoint( nSplitLayerId, ptTest)
if EgtSurfFrTestExternal( nSplitSurf, nTestPoint) then
EgtErase( nDowel1)
end
EgtErase( nTestPoint)
-- pezzo
local dLen2 = CalcDowelLen( vDowels[i], sLenKey, true)
local nDowel2 = CreateDowel( vDowels[i], nLayerId, frOrig, frDest, vtDir, nTestSurfInverted, dLen2, sDowelSide, nSolidId)
ptTest = EgtCP( nDowel2) - vtDir * EgtCurveThickness( nDowel2)
nTestPoint = EgtPoint( nLayerId, ptTest)
if EgtSurfFrTestExternal( nSurf, nTestPoint) then
EgtErase( nDowel2)
end
EgtErase( nTestPoint)
end
EgtErase( nTestSurf)
EgtErase( nTestSurfInverted)
end
end
end
EgtErase( vAuxSurfs)
end
---------------------------------------------------------------------
-- funzione che calcola le spine
local function CalculateAreaDowels( nAreaId)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
if nAreaType == WIN_AREATYPES.FRAME or nAreaType == WIN_AREATYPES.SASH then
-- verifico se presente bottomrail
local nBottomRails = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0
-- aggiungo le spine sui pezzi dell'area
local nOutline = EgtGetFirstInGroup( nOutlineLayerId)
local nPrevOutline = EgtGetLastInGroup( nOutlineLayerId)
while EgtGetInfo( nPrevOutline, WIN_EXTRA_CRV, 'b') do
nPrevOutline = EgtGetPrev( nPrevOutline)
end
while nOutline do
local bExtra = EgtGetInfo( nOutline, WIN_EXTRA_CRV, 'b') or false
if not bExtra then
-- aggiungo spine su nOutline e nPrevOutline nel loro punto di giunzione
CalcDowels( nOutline, nPrevOutline, nAreaType == WIN_AREATYPES.SASH)
-- bottomrail
if nBottomRails > 0 and ( EgtGetName( nOutline) == WIN_BOTTOM or EgtGetName( nPrevOutline) == WIN_BOTTOM) then
for j = 1, nBottomRails do
CalcDowels( nOutline, nPrevOutline, false, j)
end
end
-- aggiorno per iterazione successiva
nPrevOutline = nOutline
end
nOutline = EgtGetNext( nOutline)
end
elseif nAreaType == WIN_AREATYPES.SPLIT then
local nSplitType = EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i') or WIN_SPLITTYPES.NULL
-- se split non è di tipo french ha un pezzo associato per il quale vanno calcolate le spine
if nSplitType ~= WIN_SPLITTYPES.FRENCH then
local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT)
local vSplitIds = EgtGetAllInGroup( nSplitLayerId)
for i = 1, #vSplitIds do
-- start
CalcSplitDowels( vSplitIds[i], true)
-- end
CalcSplitDowels( vSplitIds[i], false)
end
end
end
-- calcolo le spine delle sottoaree
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
CalculateAreaDowels( nChildAreaId)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
----------------------------------------------------------------------------------
--------------------------------- STRIP ----------------------------------------
----------------------------------------------------------------------------------
-- funzione che restitutisce lo Strip piu' vicino
local function GetStripNearestToOutline( nProfileId, nOutlineId)
local sStripName = WIN_STRIP
-- gestione particolare del caso di profilo di split ( devo capire il lato corretto)
if not EgtGetFirstNameInGroup( nProfileId, sStripName) then
if nOutlineId < 0 then
sStripName = WIN_STRIP .. '1'
else
sStripName = WIN_STRIP .. '2'
end
end
if s_bSimplSolid then
sStripName = WIN_SIMPLIFIED .. sStripName
end
local nStripId = EgtGetFirstNameInGroup( nProfileId, sStripName)
return nStripId
end
---------------------------------------------------------------------
local function CreateStripGuideLines( nOutlineId, nStripId, nProfileId, nSolidLayerId)
-- restutuisco le curve ordinate in modo che la prima sia quella più esterna e la seconda quella più interna
-- recupero il box dello strip nel frame del profilo
local nProfileFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frProfile = EgtFR( nProfileFrameId, GDB_ID.ROOT)
local b3MainStrip = EgtGetBBoxRef( nStripId, GDB_BB.STANDARD, frProfile)
-- calcolo offset per strip
local dDelta = EgtGetInfo( nProfileId, WIN_RAILOFFS, 'd') or 0
local dMinOffs = b3MainStrip:getMin():getX() - dDelta
local dMaxOffs = b3MainStrip:getMax():getX() - dDelta
local nMinOffsetId = EgtCopy( abs( nOutlineId), nSolidLayerId)
EgtOffsetCurve( nMinOffsetId, dMinOffs)
local nMaxOffsetId = EgtCopy( abs( nOutlineId), nSolidLayerId)
EgtOffsetCurve( nMaxOffsetId, dMaxOffs)
-- verifico se le curve vanno invertite nel caso di split
if nOutlineId < 0 then
EgtInvertCurve( nMinOffsetId)
EgtInvertCurve( nMaxOffsetId)
return nMaxOffsetId, nMinOffsetId
end
return nMinOffsetId, nMaxOffsetId
end
---------------------------------------------------------------------
local function TrimStripSurfByPoints( pt1, pt2, nStripSurfId, nSolidLayerId)
-- creo la superficie di trim
local nTrimGuideId = EgtLine( nSolidLayerId, pt1, pt2)
EgtExtendCurveStartByLen( nTrimGuideId, 100)
EgtExtendCurveEndByLen( nTrimGuideId, 100)
EgtMove( nTrimGuideId, Z_AX())
local dDim = 100
local nTrimSurfId = EgtSurfTmByExtrusion( nSolidLayerId, nTrimGuideId, - Z_AX() * dDim, WIN_SURF_APPROX)
-- intersezione con strip
EgtSurfTmIntersect( nStripSurfId, nTrimSurfId)
EgtErase( nTrimGuideId)
EgtErase( nTrimSurfId)
end
---------------------------------------------------------------------
local function TrimStripSurfByCurve( nCrvId, nStripSurfId, nSolidLayerId, bPrev)
-- estendo la guida in tangenza
local nTrimGuideId = EgtCopyGlob( nCrvId, nSolidLayerId)
local dExtraLen = 100
if EgtGetType( nTrimGuideId) == GDB_TY.CRV_LINE then
EgtExtendCurveStartByLen( nTrimGuideId, dExtraLen)
EgtExtendCurveEndByLen( nTrimGuideId, dExtraLen)
else
nTrimGuideId = EgtCurveCompo( nSolidLayerId, nTrimGuideId)
EgtAddCurveCompoLineTg( nTrimGuideId, dExtraLen)
EgtAddCurveCompoLineTg( nTrimGuideId, dExtraLen, false)
end
EgtMove( nTrimGuideId, Z_AX())
EgtInvertCurve( nTrimGuideId)
-- creo la superficie di trim
local dDim = 100
local nTrimSurfId = EgtSurfTmByExtrusion( nSolidLayerId, nTrimGuideId, - Z_AX() * dDim, WIN_SURF_APPROX)
-- intersezione con strip
EgtSurfTmIntersect( nStripSurfId, nTrimSurfId)
EgtErase( nTrimGuideId)
EgtErase( nTrimSurfId)
end
---------------------------------------------------------------------
local function CalcAreaStrip( nOutlineLayerId)
if not s_bCalcSolid then return end
-- gruppi temporanei per i conti
local nGrp = EgtGroup( GDB_ID.ROOT)
local nGrp1 = EgtGroup( GDB_ID.ROOT)
local nGrp2 = EgtGroup( GDB_ID.ROOT)
EgtSetStatus( nGrp, GDB_ST.OFF)
EgtSetStatus( nGrp1, GDB_ST.OFF)
EgtSetStatus( nGrp2, GDB_ST.OFF)
-- estrudo i fermavetri e calcolo le curve che li limitano ( Offs1 sono quelli più lontani dal pezzo, Offs2 quelli più vicini)
local vOutlineCrvs = EgtGetAllInGroup( nOutlineLayerId)
local tabStrip = {}
for i = 1, #vOutlineCrvs do
local nOutlineId = EgtGetInfo( vOutlineCrvs[i], WIN_SOU_OUTLINE, 'i')
-- verifico se pezzo ausiliario da ignorare
local bExtra = EgtGetInfo( nOutlineId, WIN_EXTRA_CRV, 'b')
local nPartId = FindAssociatedPart( abs( nOutlineId), true)
-- recupero profilo
local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN)
local nStripId = GetStripNearestToOutline( nProfileId, nOutlineId)
-- recupero layer per solido
local nStripExtrusionId
if not bExtra then
local nSolidLayerId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID)
-- estrusione del fermavetro :
-- creazione della giuda
local nGuideId = EgtCurveCompo( nSolidLayerId, abs( nOutlineId), false)
local sProfileType = EgtGetInfo( nProfileId, WIN_PROFILETYPE)
if sProfileType == WIN_FILL_RAIL then
local dOffs = EgtGetInfo( nProfileId, WIN_RAILOFFS, 'd')
EgtOffsetCurve( nGuideId, - dOffs)
end
-- estensione : se in tangenza con le vicine estensione in tangenza altrimenti estensione standard
local nPrev = EgtGetPrev( vOutlineCrvs[i]) or EgtGetLastInGroup( nOutlineLayerId)
local nNext = EgtGetNext( vOutlineCrvs[i]) or EgtGetLastInGroup( nOutlineLayerId)
if AreSameVectorApprox( EgtEV( nPrev), EgtSV( nGuideId)) then
EgtAddCurveCompoLineTg( nGuideId, 100, false)
else
EgtExtendCurveStartByLen( nGuideId, 100)
end
if AreSameVectorApprox( EgtEV( nGuideId), EgtSV( nNext)) then
EgtAddCurveCompoLineTg( nGuideId, 100)
else
EgtExtendCurveEndByLen( nGuideId, 100)
end
-- sistemo il profilo da estrudere
local nSectionId = EgtCopyGlob( nStripId, nSolidLayerId)
local nFrameProfileId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frOrig = EgtFR( nFrameProfileId, GDB_ID.ROOT)
frOrig:invert()
local frDest = Frame3d( EgtSP( nGuideId), - EgtSV( nGuideId))
EgtTransform( nSectionId, frOrig)
EgtTransform( nSectionId, frDest)
nStripExtrusionId = EgtSurfTmSwept( nSolidLayerId, nSectionId, nGuideId, false, WIN_SURF_APPROX)
EgtSetName( nStripExtrusionId, WIN_SRF_STRIP)
EgtErase( nSectionId)
EgtErase( nGuideId)
end
-- curve limite del fermavetro
local nOffs1, nOffs2 = CreateStripGuideLines( nOutlineId, nStripId, nProfileId, nGrp)
EgtRelocateGlob( nOffs1, nGrp1)
EgtRelocateGlob( nOffs2, nGrp2)
EgtSetInfo( nOffs1, WIN_REF_OUTLINE, vOutlineCrvs[i])
EgtSetInfo( nOffs2, WIN_REF_OUTLINE, vOutlineCrvs[i])
tabStrip[vOutlineCrvs[i]] = { Offs1 = GDB_ID.NULL, Offs2 = GDB_ID.NULL, StripId = nStripExtrusionId}
end
-- taglio le curve limite dei fermavetri per individuare correttamente i pezzi con cui verranno tagliati
local vCrv1 = TrimOrderedCurves( EgtGetAllInGroup( nGrp1), true)
local vCrv2 = TrimOrderedCurves( EgtGetAllInGroup( nGrp2), true)
-- associo le curve trimmate alle curve geo corrispondenti
for i = 1, #vCrv1 do
local nOutlineRef = EgtGetInfo( vCrv1[i], WIN_REF_OUTLINE, 'i')
tabStrip[nOutlineRef].Offs1 = vCrv1[i]
end
for i = 1, #vCrv2 do
local nOutlineRef = EgtGetInfo( vCrv2[i], WIN_REF_OUTLINE, 'i')
tabStrip[nOutlineRef].Offs2 = vCrv2[i]
end
-- trim dei solidi fermavetro
for i = 1, #vOutlineCrvs do
if tabStrip[vOutlineCrvs[i]].StripId then
-- recupero solido del fermavetro
local nCrv = vOutlineCrvs[i]
local nStripId = tabStrip[nCrv].StripId
local nSolidLayerId = EgtGetParent( nStripId)
-- recupero le corrispondenti curve limite trimmate
local nCrvOffs1 = tabStrip[nCrv].Offs1
local nCrvOffs2 = tabStrip[nCrv].Offs2
-- se entrambe le curve valide
if nCrvOffs1 ~= GDB_ID.NULL and nCrvOffs2 ~= GDB_ID.NULL then
-- a) trim start
-- recupero le precedenti della curva 1 e 2
local nPrev1 = EgtGetPrev( nCrvOffs1) or EgtGetLastInGroup( nGrp1)
local nPrev2 = EgtGetPrev( nCrvOffs2) or EgtGetLastInGroup( nGrp2)
local nPrevCrv1 = EgtGetInfo( nPrev1, WIN_REF_OUTLINE, 'i')
local nPrevCrv2 = EgtGetInfo( nPrev2, WIN_REF_OUTLINE, 'i')
if nPrevCrv1 == nPrevCrv2 then
-- se le precedenti coincidono taglio basandomi solo sui riferimenti dello strip corrente
TrimStripSurfByPoints( EgtSP( nCrvOffs2), EgtSP( nCrvOffs1), nStripId, nSolidLayerId, true)
else
-- ci sono dei pezzi che scompaiono quindi vanno effettuati due tagli: uno per ricreare il bordo 2 dei pezzi che scompaiono e uno per
-- separare il pezzo corrente e il pezzo 1
-- a) recupero i pezzi che scompaiono
local nCurrCrv = tabStrip[nPrevCrv1].Offs2
nCurrCrv = EgtGetNext( nCurrCrv) or EgtGetFirstInGroup( nGrp2)
local vIds = {}
while nCurrCrv ~= nCrvOffs2 do
table.insert( vIds, nCurrCrv)
nCurrCrv = EgtGetNext( nCurrCrv) or EgtGetFirstInGroup( nGrp2)
end
local nCrvBorder = EgtCurveCompo( nGrp, vIds, false)
-- taglio
TrimStripSurfByCurve( nCrvBorder, nStripId, nSolidLayerId)
-- b) taglio che separa da pezzo 1
TrimStripSurfByPoints( EgtCP( nCrvBorder), EgtSP( nCrvOffs1), nStripId, nSolidLayerId, true)
EgtErase( nCrvBorder)
end
-- b) trim end
-- recupero le successive per le curve 1 e 2
local nNext1 = EgtGetNext( nCrvOffs1) or EgtGetFirstInGroup( nGrp1)
local nNext2 = EgtGetNext( nCrvOffs2) or EgtGetFirstInGroup( nGrp2)
local nNextCrv1 = EgtGetInfo( nNext1, WIN_REF_OUTLINE, 'i')
local nNextCrv2 = EgtGetInfo( nNext2, WIN_REF_OUTLINE, 'i')
if nNextCrv1 == nNextCrv2 then
TrimStripSurfByPoints( EgtEP( nCrvOffs1), EgtEP( nCrvOffs2), nStripId, nSolidLayerId)
else
local nCurrCrv = nCrvOffs2
nCurrCrv = EgtGetNext( nCurrCrv) or EgtGetFirstInGroup( nGrp2)
local vIds = {}
while nCurrCrv ~= tabStrip[nNextCrv1].Offs2 do
table.insert( vIds, nCurrCrv)
nCurrCrv = EgtGetNext( nCurrCrv) or EgtGetFirstInGroup( nGrp2)
end
local nCrvBorder = EgtCurveCompo( nGrp, vIds, false)
TrimStripSurfByCurve( nCrvBorder, nStripId, nSolidLayerId)
TrimStripSurfByPoints( EgtEP( nCrvOffs1), EgtCP( nCrvBorder), nStripId, nSolidLayerId)
EgtErase( nCrvBorder)
end
else
-- il pezzo scompare
EgtErase( nStripId)
end
end
end
EgtErase( nGrp)
EgtErase( nGrp1)
EgtErase( nGrp2)
end
----------------------------------------------------------------------------------
----------------------------- CALCOLO PEZZI ------------------------------------
----------------------------------------------------------------------------------
local function CalculateAreaParts( nFrameId)
-- recupero i pezzi del serramento
local vParts = {}
local vFillParts = {}
local vAuxParts = {} -- sono pezzi non fisicamente realizzabili che servono solo per i conti
local nPartId = EgtGetFirstPart( GDB_ID.ROOT)
while nPartId do
local nType = EgtGetInfo( nPartId, WIN_PART_TYPE, 'i')
if nType == WIN_PART_TYPES.FILL then
table.insert( vFillParts, nPartId)
else
local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i')
local bExtra = EgtGetInfo( nOutlineId, WIN_EXTRA_CRV, 'b') or false
if bExtra then
table.insert( vAuxParts, nPartId)
else
table.insert( vParts, { nId = nPartId, nOutlineId = nOutlineId})
end
end
nPartId = EgtGetNextPart( nPartId)
end
-- calcolo geo
for i = 1, #vParts do
CalcGeo( vParts[i].nId, vParts[i].nOutlineId)
end
-- calcolo cambio profilo sugli split di tipo mixed
for i = 1, #vParts do
if EgtGetName( vParts[i].nOutlineId) == WIN_SPLIT then
local nSplitType = EgtGetInfo( vParts[i].nOutlineId, WIN_SPLITTYPE, 'i')
if nSplitType == WIN_SPLITTYPES.MIXED then
CalcMixedCurves( vParts[i].nId, vParts[i].nOutlineId)
end
end
end
-- calcolo le lavorazioni associate ai profili
for i = 1, #vParts do
CalcProfilingProcessings( vParts[i].nId, vParts[i].nOutlineId)
end
-- calcolo il georaw per automatismo lavorazioni
for i = 1, #vParts do
CalcGeoRaw( vParts[i].nId, vParts[i].nOutlineId)
end
-- disegno solido
if s_bCalcSolid then
for i = 1, #vParts do
CalcSolid( vParts[i].nId, vParts[i].nOutlineId)
end
end
-- pezzi fill
for i = 1, #vFillParts do
local nAreaId = EgtGetInfo( vFillParts[i], WIN_AREA, 'i')
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local nGeoLayerId = CalcFillGeo( vFillParts[i], nOutlineLayerId)
-- disegno solido
if s_bCalcSolid then
CalcFillSolid( vFillParts[i], nGeoLayerId)
end
-- calcolo fermavetro
CalcAreaStrip( nOutlineLayerId)
end
-- elimino i pezzi ausiliari
EgtErase( vAuxParts)
end
----------------------------------------------------------------------------------
---------------------------------- TRONCHETTI ----------------------------------
----------------------------------------------------------------------------------
-- funzione che spezza l'anta in corrispondenza dei tronchetti del telaio
local function SplitArcByAlignment( nGeoIn, nGrp)
-- recupero il pezzo del telaio corrispondente
local nPartId = EgtGetParent( EgtGetParent( nGeoIn))
local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i')
local nFrameOutlineId = EgtGetInfo( nOutlineId, WIN_SOU_OUTLINE, 'i')
local nFramePartId = EgtGetInfo( nFrameOutlineId, WIN_REF_PART, 'i')
-- recupero le parti in cui era stato diviso l'arco del telaio
local nFrameLogsLayer = EgtGetFirstNameInGroup( nFramePartId, WIN_LOGS)
local vFrameLogs = EgtGetNameInGroup( nFrameLogsLayer, WIN_GEO_IN)
local ptC = EgtCP( vFrameLogs[1])
local nCurrCrvId = EgtCopyGlob( nGeoIn, nGrp)
local bInters = false
for i = 1, #vFrameLogs - 1 do
-- ricavo il punto di split sull'arco dell'anta
local ptFrame = EgtEP( vFrameLogs[i])
local vtDir = ptFrame - ptC
local nLineSplit = EgtLinePVL( nGrp, ptC, vtDir, vtDir:len() + 1000)
local ptInt = EgtIP( nCurrCrvId, nLineSplit, ORIG())
EgtErase( nLineSplit)
if ptInt then
nCurrCrvId = EgtSplitCurveAtPoint( nCurrCrvId, ptInt) or GDB_ID.NULL
bInters = true
elseif bInters then
-- se non ci sono più intersezioni esco
return
end
end
end
---------------------------------------------------------------------
-- funzione che spezza l'arco in base al numero di pezzi
local function SplitArcByNumber( nLogsNbr, nGeoIn, nGrp)
local nCopy = EgtCopyGlob( nGeoIn, nGrp)
EgtSplitCurve( nCopy, nLogsNbr)
end
---------------------------------------------------------------------
-- funzione che spezza gli archi per i tronchetti
local function SplitArc( nLogsNbr, vSections, bAlign, dOverMatTot, nGeoIn, nGeoOut, nGrp)
-- per allineamento con telaio
if bAlign then
return SplitArcByAlignment( nGeoIn, nGrp)
-- per sezione
elseif #vSections == 1 and nLogsNbr == 0 then
-- dalla sezione ricavo il numero minimo di pezzi
local dSection = vSections[1] - dOverMatTot
local dROut = EgtArcRadius( nGeoOut)
local dRIn = EgtArcRadius( nGeoIn)
local dAng = abs( EgtArcAngCenter( nGeoIn))
local nParts
if dSection < dROut - dRIn + GEO.EPS_SMALL then
-- sezione troppo piccola
-- TO DO : gestione errore
EgtOutBox( 'Sezione tronchetto troppo piccola', '')
elseif dSection > dROut + dRIn - GEO.EPS_SMALL then
-- la sezione comprende già l'intero pezzo
nParts = 1
else
nParts = dAng / 2 / acos( ( dROut - dSection) / dRIn)
nParts = ceil( nParts)
end
return SplitArcByNumber( nParts, nGeoIn, nGrp)
-- per numero di pezzi
else
return SplitArcByNumber( nLogsNbr, nGeoIn, nGrp)
end
end
---------------------------------------------------------------------
-- funzione che calcola la sezione dei tronchetti
local function CalcLogsSection( nLogsNbr, vSections, bAlign, dOverMatTot, nGeoIn, nGeoOut, nGrp)
-- se richiesta una sezione specifica senza vincoli sul numero di pezzi
if not bAlign and #vSections == 1 and nLogsNbr == 0 then
return vSections[1]
end
-- calcolo la sezione necessaria per la suddivisione scelta
local dMySection = 0
local dROut = EgtArcRadius( nGeoOut)
local dRIn = EgtArcRadius( nGeoIn)
if bAlign then
-- calcolo la massima sezione dai tronchetti ottenuti
local vSplits = EgtGetAllInGroup( nGrp)
for i = 1, #vSplits do
local dAng = abs( EgtArcAngCenter( vSplits[i]))
local dCurrSection = dROut - dRIn * cos( dAng / 2)
if dCurrSection > dMySection then
dMySection = dCurrSection
end
end
dMySection = dMySection + dOverMatTot
else
-- ricavo la sezione dal numero di pezzi
local dAng = abs( EgtArcAngCenter( nGeoIn))
dMySection = dROut - dRIn * cos( dAng / nLogsNbr / 2) + dOverMatTot
end
if #vSections == 0 then
-- se no vincoli sulla sezione
return dMySection
else
-- cerco la sezione più adatta dalla lista di sezioni disponibili
table.sort( vSections)
for i = 1, #vSections do
if vSections[i] > dMySection - GEO.EPS_SMALL then
return vSections[i]
end
end
-- se non ho trovato la sezione errore
EgtOutBox( 'Sezioni tronchetti troppo piccole per suddivisione richiesta', '')
return nil
end
end
---------------------------------------------------------------------
local function CalcLogs( nGrp, nGeoOut, dOverMatIn, dOverMatOut, dOverMatExt, dOverMatInt, dRefSection, bCutExtremities)
-- recupero tutti i tratti dell'arco
local vCrvsIn = EgtGetAllInGroup( nGrp)
local ptC = EgtCP( vCrvsIn[1])
-- calcolo i tronchetti
local dLenTot = 0
for i = 1, #vCrvsIn do
local ptSIn = EgtSP( vCrvsIn[i])
local ptEIn = EgtEP( vCrvsIn[i])
-- recupero il tratto corrispondente sulla curva out
local ptSOut, dParSOut, ptEOut, dParEOut
if i == 1 then
-- forzo a coincidere con l'estremo della curva out
ptEOut = EgtEP( nGeoOut)
dParEOut = 1
else
_, ptEOut, dParEOut = EgtPointCurveDist( ptSIn, nGeoOut)
end
if i == #vCrvsIn then
-- forzo a coincidere con l'estremo della curva out
ptSOut = EgtSP( nGeoOut)
dParSOut = 0
else
_, ptSOut, dParSOut = EgtPointCurveDist( ptEIn, nGeoOut)
end
local nOut = EgtCopyGlob( nGeoOut, nGrp)
EgtTrimCurveStartEndAtParam( nOut, dParSOut, dParEOut)
-- creo composita corrispondente al pezzo
local nCompo = EgtCurveCompo( nGrp, {vCrvsIn[i]}, false)
EgtAddCurveCompoLine( nCompo, ptSOut)
EgtAddCurveCompoCurve( nCompo, nOut, false)
EgtCloseCurveCompo( nCompo)
-- calcolo il frame per il tronchetto
local ptM = EgtMP( vCrvsIn[i])
local vtRad = ptM - ptC
local frRef = Frame3d( ptM, vtRad ^ Z_AX(), vtRad, Z_AX())
-- calcolo il box locale al frame
local b3Ref = EgtGetBBoxRef( nCompo, GDB_BB.STANDARD, frRef)
local ptMax = b3Ref:getMax()
local ptMin = b3Ref:getMin()
ptMin:setZ( ptMax:getZ()) -- per avere curve sullo stesso piano ( e gestire correttamente le intersezioni)
-- verifico se necessario sovramateriale extra per raggiungere la sezione desiderata
local dExtraSection = max( 0, dRefSection - b3Ref:getDimY() - dOverMatIn - dOverMatOut)
-- lato bottom
local nLineBottom = EgtLinePVL( nGrp, ptMin - ( dOverMatIn + 0.5 * dExtraSection) * Y_AX(), X_AX(), 10000)
EgtExtendCurveStartByLen( nLineBottom, 10000)
EgtTransform( nLineBottom, frRef)
-- lato top
local nLineTop = EgtLinePVL( nGrp, ptMax + ( dOverMatOut + 0.5 * dExtraSection) * Y_AX(), - X_AX(), 10000)
EgtExtendCurveStartByLen( nLineTop, 10000)
EgtTransform( nLineTop, frRef)
-- lato right
local nLineRight
if i == 1 and not bCutExtremities then
nLineRight = EgtLinePVL( nGrp, ptMin, - Y_AX(), 10000)
EgtTransform( nLineRight, frRef)
else
nLineRight = EgtLine( nGrp, ptEOut, ptSIn)
EgtExtendCurveEndByLen( nLineRight, 10000)
end
EgtOffsetCurve( nLineRight, EgtIf( i == 1, dOverMatExt, dOverMatInt))
EgtExtendCurveStartByLen( nLineRight, 10000)
-- lato left
local nLineLeft
if i == #vCrvsIn and not bCutExtremities then
nLineLeft = EgtLinePVL( nGrp, ptMax, Y_AX(), 10000)
EgtTransform( nLineLeft, frRef)
else
nLineLeft = EgtLine( nGrp, ptEIn, ptSOut)
EgtExtendCurveEndByLen( nLineLeft, 10000)
end
EgtOffsetCurve( nLineLeft, EgtIf( i == #vCrvsIn, dOverMatExt, dOverMatInt))
EgtExtendCurveStartByLen( nLineLeft, 10000)
-- taglio le curve nei loro punti di intersezione
local vCrvs = { nLineTop, nLineRight, nLineBottom, nLineLeft}
vCrvs = TrimOrderedCurves( vCrvs, true)
-- TO DO : controllo lunghezza minima
-- local dLenTop = EgtCurveLength( nLineTop)
dLenTot = dLenTot + EgtCurveLength( nLineTop)
-- creo il tronchetto
local nLogCrv = EgtCurveCompo( nGrp, vCrvs)
EgtSetName( nLogCrv, WIN_LOGS)
EgtSetColor( nLogCrv, EgtStdColor( 'BLUE'))
-- salvo i sovramateriali utilizzati nella curva
EgtSetInfo( nLogCrv, WIN_PRC_OVERMAT_IN, dOverMatIn)
EgtSetInfo( nLogCrv, WIN_PRC_OVERMAT_OUT, dOverMatOut)
EgtSetInfo( nLogCrv, WIN_PRC_OVERMAT_LEFT, EgtIf( i == #vCrvsIn, dOverMatExt, dOverMatInt))
EgtSetInfo( nLogCrv, WIN_PRC_OVERMAT_RIGHT, EgtIf( i == 1, dOverMatExt, dOverMatInt))
EgtSetStatus( vCrvsIn[i], GDB_ST.OFF)
EgtSetStatus( nOut, GDB_ST.OFF)
EgtErase( nCompo)
end
-- salvo i dati della sezione ( analogamente a quanto fatto nel geo per pezzi lineari)
EgtSetInfo( nGrp, WIN_GEOWIDTH, dRefSection)
CopyInfo( nGrp, EgtGetParent( nGeoOut), WIN_GEOHEIGHT)
EgtSetInfo( nGrp, WIN_GEOLEN, dLenTot)
end
---------------------------------------------------------------------
-- funzione che crea la spina per tronchetti
local function CalcLogDowel( nOrigPartId, nCrvOut, bLeftOrRight, nProcLayerId, nProfileId, nInfoGrp, nSolidId)
-- creo il frame per il posizionamento del dowel
local nOutlineRef = EgtGetInfo( nOrigPartId, WIN_REF_OUTLINE, 'i')
local ptRef = EgtIf( bLeftOrRight, EgtSP( nCrvOut), EgtEP( nCrvOut))
local _, ptOrig, dParOrig = EgtPointCurveDist( ptRef, nOutlineRef)
local vtFrame = EgtUV( nOutlineRef, dParOrig, -1)
local frDest = Frame3d( ptOrig, - vtFrame)
-- calcolo direzione verso interno del pezzo
local vtDir = frDest:getVersZ()
if bLeftOrRight then
vtDir = - vtDir
end
-- recupero i dati del dowel
local dDowelDiam = 5 -- EgtGetInfo( nInfoGrp, WIN_DWL_DIAM, 'd')
local dDowelLen = 10 -- EgtGetInfo( nInfoGrp, WIN_DWL_LOG_LEN, 'd')
-- creo il dowel nel riferimento della sezione
-- TO DO : recupero della sezione corretta nel caso di cambio profilo
local nSectionId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTION) or EgtGetFirstNameInGroup( nProfileId, WIN_SASH .. WIN_SECTION)
local nDowelId = EgtCircle( nProcLayerId, EgtGP( nSectionId), 0.5 * dDowelDiam)
-- posiziono il dowel usando i riferimenti
local nFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME)
local frOrig = EgtFR( nFrameId)
frOrig:invert()
EgtTransform( nDowelId, frOrig)
EgtTransform( nDowelId, frDest)
local nPartId = EgtGetParent( nProcLayerId)
local dOverMat = EgtGetInfo( nPartId, EgtIf( bLeftOrRight, WIN_PRC_OVERMAT_LEFT, WIN_PRC_OVERMAT_RIGHT))
EgtMove( nDowelId, - vtDir * ( s_dDowelTol + dOverMat))
EgtModifyCurveExtrusion( nDowelId, - vtDir)
local dLen = dDowelLen + dOverMat + s_dDowelTol
EgtModifyCurveThickness( nDowelId, - dLen)
-- setto info di lavorazione
EgtSetInfo( nDowelId, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.HOLE)
EgtSetInfo( nDowelId, WIN_PRC_SIDE, EgtIf( bLeftOrRight, WIN_PRC_SIDETYPE.LEFT, WIN_PRC_SIDETYPE.RIGHT))
-- eventuale aggiornamento del solido
if nSolidId then
UpdateSolidWithProcessingCrv( nDowelId, nSolidId, nProcLayerId)
end
end
---------------------------------------------------------------------
-- funzione che crea i pezzi dei tronchetti
local function CalcLogParts( nOrigPartId, bFinishedLogs)
local nProfileGrp = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE)
-- local nInfoGrp = EgtGetFirstNameInGroup( nProfileGrp, WIN_INFO_GRP)
-- recupero i gruppi dal pezzo ad arco
local nProfileLayerId = EgtGetFirstNameInGroup( nOrigPartId, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN)
local nOrigSolidLayerId = EgtGetFirstNameInGroup( nOrigPartId, WIN_SOLID)
local nOrigProcLayerId = EgtGetFirstNameInGroup( nOrigPartId, WIN_PRC)
-- recupero dimensione del profilo
local nGeoLayerId = EgtGetFirstNameInGroup( nOrigPartId, WIN_GEO)
local dThick = EgtGetInfo( nGeoLayerId, WIN_GEOHEIGHT, 'd')
-- recupero i tronchetti
local nLogLayerId = EgtGetFirstNameInGroup( nOrigPartId, WIN_LOGS)
local vCrvIn = EgtGetNameInGroup( nLogLayerId, WIN_GEO_IN)
local vCrvOut = EgtGetNameInGroup( nLogLayerId, WIN_GEO_OUT)
local vLogs = {}
for i = 1, #vCrvIn do
-- creo il pezzo per il trochetto
local nPartId = EgtGroup( GDB_ID.ROOT)
EgtSetName( nPartId, WIN_LOGS)
EgtSetColor( nPartId, Color3d( 204, 102, 0))
EgtSetStatus( nPartId, GDB_ST.OFF)
table.insert( vLogs, nPartId)
local nCrvIn = vCrvIn[i]
local nCrvOut = vCrvOut[i]
local nLogCrv = EgtGetNext( nCrvOut)
-- setto le info con i sovramateriali corrispondenti
CopyInfo( nPartId, nLogCrv, WIN_PRC_OVERMAT_IN, 0)
CopyInfo( nPartId, nLogCrv, WIN_PRC_OVERMAT_OUT, 0)
CopyInfo( nPartId, nLogCrv, WIN_PRC_OVERMAT_LEFT, 0)
CopyInfo( nPartId, nLogCrv, WIN_PRC_OVERMAT_RIGHT, 0)
-- a) GEORAW
local nGeoRawLayerId = EgtGroup( nPartId)
EgtSetName( nGeoRawLayerId, WIN_GEO_RAW)
local nGeoRawCrvId = EgtCopyGlob( nLogCrv, nGeoRawLayerId)
EgtModifyCurveThickness( nGeoRawCrvId, - dThick)
-- creo il frame ausiliario
local vtX = EgtSV( nLogCrv)
local frGeo = Frame3d( EgtSP( nLogCrv), vtX, Z_AX() ^ vtX, Z_AX())
local nFrameId = EgtFrame( nGeoRawLayerId, frGeo)
EgtSetName( nFrameId, WIN_PRC_FRAME)
-- b) SOLIDO
local nSolidId
if s_bCalcSolid then
local nSolidLayerId = EgtGroup( nPartId)
EgtSetName( nSolidLayerId, WIN_SOLID)
if #vCrvIn == 1 then
-- essendo singolo pezzo il solido è quello originale
local nOrigSolidId = EgtGetFirstNameInGroup( nOrigSolidLayerId, WIN_SRF_MAIN)
EgtCopyGlob( nOrigSolidId, nSolidLayerId)
elseif bFinishedLogs then
-- recupero il solido originale e lo taglio opportunamente agli estremi
local nOrigSolidId = EgtGetFirstNameInGroup( nOrigSolidLayerId, WIN_SRF_MAIN)
nSolidId = EgtCopyGlob( nOrigSolidId, nSolidLayerId)
local bBox = GetProfileLocalBox( nProfileId)
local dDimY = bBox:getDimY()
if i ~= 1 then
local nTrimCrv = EgtLine( nSolidLayerId, EgtUP( nLogCrv, 2), EgtUP( nLogCrv, 1))
EgtMove( nTrimCrv, Z_AX())
local nTrimSrf = EgtSurfTmByExtrusion( nSolidLayerId, nTrimCrv, - Z_AX() * ( dDimY + 2), WIN_SURF_APPROX)
EgtSurfTmIntersect( nSolidId, nTrimSrf)
EgtErase( { nTrimCrv, nTrimSrf})
end
if i ~= #vCrvIn then
local nTrimCrv = EgtLine( nSolidLayerId, EgtSP( nLogCrv), EgtUP( nLogCrv, 3))
EgtMove( nTrimCrv, Z_AX())
local nTrimSrf = EgtSurfTmByExtrusion( nSolidLayerId, nTrimCrv, - Z_AX() * ( dDimY + 2), WIN_SURF_APPROX)
EgtSurfTmIntersect( nSolidId, nTrimSrf)
EgtErase( { nTrimCrv, nTrimSrf})
end
else
-- il solido è esattamente il tronchetto
local bBox = GetProfileLocalBox( nProfileId)
nSolidId = EgtSurfTmByRegionExtrusion( nSolidLayerId, nLogCrv, - bBox:getDimY() * Z_AX())
EgtSetName( nSolidId, WIN_SOLID)
end
end
-- c) LAVORAZIONI
-- se unico tronchetto le lavorazioni sono quelle del pezzo originale
if #vCrvIn == 1 then
EgtRelocateGlob( nOrigProcLayerId, nPartId)
EgtSetStatus( nOrigProcLayerId, GDB_ST.ON)
return
end
local nProcLayerId = EgtGroup( nPartId)
EgtSetName( nProcLayerId, WIN_PRC)
-- profili in e out
if bFinishedLogs then
local nCrvInCopy = EgtCopyGlob( nCrvIn, nProcLayerId)
local nSemiProfileInId = EgtGetInfo( nCrvInCopy, WIN_SEMI_PROFILE, 'i')
GetProcessingInfoFromSemiProfile( nCrvInCopy, nSemiProfileInId)
EgtSetStatus( nCrvInCopy, GDB_ST.ON)
local nCrvOutCopy = EgtCopyGlob( nCrvOut, nProcLayerId)
local nSemiProfileOutId = EgtGetInfo( nCrvOutCopy, WIN_SEMI_PROFILE, 'i')
GetProcessingInfoFromSemiProfile( nCrvOutCopy, nSemiProfileOutId)
EgtSetStatus( nCrvOutCopy, GDB_ST.ON)
end
-- profilo left
if i == #vCrvIn and bFinishedLogs then
-- recupero la curva di lavorazione dal pezzo originale
local nLeftPrc = EgtGetFirstNameInGroup( nOrigProcLayerId, WIN_GEO_LEFT)
EgtRelocateGlob( nLeftPrc, nProcLayerId)
elseif i ~= #vCrvIn then
-- minizinken
local nLeftId = EgtLine( nProcLayerId, EgtUP( nLogCrv, 3), EgtSP( nLogCrv))
EgtSetName( nLeftId, WIN_LEFT)
-- assegno le info di lavorazione
-- EgtSetInfo( nLeftId, WIN_PRC_NTOOLS, 1)
-- local sToolName = EgtGetInfo( nInfoGrp, WIN_PRC_TOOL_NAME)
-- EgtSetInfo( nLeftId, WIN_PRC_TOOL_NAME .. '_1', sToolName)
-- local dOffR = EgtGetInfo( nInfoGrp, WIN_PRC_OFFR, 'd')
-- -- TO DO : verificare valore OffsR
-- EgtSetInfo( nLeftId, WIN_PRC_OFFR .. '_1', dOffR)
-- local dOffL = EgtGetInfo( nInfoGrp, WIN_PRC_OFFL .. '_1', 'd')
-- EgtSetInfo( nLeftId, WIN_PRC_OFFL .. '_1', dOffL)
end
-- profilo right
if i == 1 and bFinishedLogs then
-- recupero la curva di lavorazione dal pezzo originale
local nRightPrc = EgtGetFirstNameInGroup( nOrigProcLayerId, WIN_GEO_RIGHT)
EgtRelocateGlob( nRightPrc, nProcLayerId)
elseif i ~= 1 then
-- minizinken
local nRightId = EgtLine( nProcLayerId, EgtUP( nLogCrv, 1), EgtUP( nLogCrv, 2))
EgtSetName( nRightId, WIN_RIGHT)
-- assegno info di lavorazione
-- EgtSetInfo( nRightId, WIN_PRC_NTOOLS, 1)
-- local sToolName = EgtGetInfo( nInfoGrp, WIN_PRC_TOOL_NAME)
-- EgtSetInfo( nRightId, WIN_PRC_TOOL_NAME .. '_1', sToolName)
-- local dOffR = EgtGetInfo( nInfoGrp, WIN_PRC_OFFR, 'd')
-- -- TO DO : verificare valore OffsR
-- EgtSetInfo( nRightId, WIN_PRC_OFFR .. '_1', dOffR)
-- local dOffL = EgtGetInfo( nInfoGrp, WIN_PRC_OFFL .. '_2', 'd')
-- EgtSetInfo( nRightId, WIN_PRC_OFFL .. '_1', dOffL)
end
-- dowels per incastro dei tronchetti
if i ~= 1 then
CalcLogDowel( nOrigPartId, nCrvOut, false, nProcLayerId, nProfileId, nInfoGrp, nSolidId)
end
if i ~= #vCrvIn then
CalcLogDowel( nOrigPartId, nCrvOut, true, nProcLayerId, nProfileId, nInfoGrp, nSolidId)
end
-- se i tronchetti sono gestiti come pezzi finiti cerco le lavorazioni del pezzo orginale che appartengono al tronchetto
if bFinishedLogs then
local vProcessings = EgtGetAllInGroup( nOrigProcLayerId)
local nSurfTest = EgtSurfFlatRegion( nProcLayerId, nLogCrv)
for i = 1, #vProcessings do
local sPrcType = EgtGetInfo( vProcessings[i], WIN_PRC_FEATURE_TYPE)
-- forature
if sPrcType == WIN_PRC_TYPE.HOLE then
local sSide = EgtGetInfo( vProcessings[i], WIN_PRC_SIDE)
-- se dowel sull'estremo lo assegno direttamente al tronchetto corrispondente
if ( sSide == WIN_PRC_SIDETYPE.LEFT and i == #vCrvIn) or ( sSide == WIN_PRC_SIDETYPE.RIGHT and i == 1) then
EgtRelocateGlob( vProcessings[i], nProcLayerId)
end
-- altrimenti verifico se interno al tronchetto corrente
if sSide == WIN_PRC_SIDETYPE.IN then
local _, _, nSide = EgtPointCurveDistSide( EgtCP( vProcessings[i]), nLogCrv, Z_AX())
if nSide == -1 then
-- copio perchè la stessa lavorazione potrebbe coinvolgere più tronchetti
EgtCopyGlob( vProcessings[i], nProcLayerId)
else
-- verifico anche la faccia di fondo
local vtExtr = EgtCurveExtrusion( vProcessings[i])
local dThickness = EgtCurveThickness( vProcessings[i])
_, _, nSide = EgtPointCurveDistSide( EgtCP( vProcessings[i]) + dThickness * vtExtr, nLogCrv, Z_AX())
if nSide == -1 then
EgtCopyGlob( vProcessings[i], nProcLayerId)
end
end
end
-- fermavetro
elseif sPrcType == WIN_PRC_TYPE.STRIP_CUT then
-- TO DO da sistemare
local nStrip = EgtCopyGlob( vProcessings[i], nProcLayerId)
EgtTrimCurveWithRegion( nStrip, nSurfTest, true, false)
else
-- TO DO lavorazioni legate alla ferramenta, cambio profilo
end
end
EgtErase( nSurfTest)
end
end
-- salvo nel pezzo ad arco i pezzi dei tronchetti associati
EgtSetInfo( nOrigPartId, WIN_LOGS, vLogs)
end
---------------------------------------------------------------------
-- funzione che crea gli elementi ausiliari per la creazione del grezzo nell'automatismo delle lavorazioni
local function CalcGeoRawFromLogs( nPartId)
-- creo il GeoRaw per il pezzo ad arco
local nGeoRawLayerId = EgtGroup( nPartId)
EgtSetName( nGeoRawLayerId, WIN_GEO_RAW)
EgtSetStatus( nGeoRawLayerId, GDB_ST.OFF)
-- recupero i vari tronchetti
local nLogGrp = EgtGetFirstNameInGroup( nPartId, WIN_LOGS)
local vLogCrvs = EgtGetNameInGroup( nLogGrp, WIN_LOGS)
-- salvo le info di sovramateriale nel pezzo
CopyInfo( nPartId, vLogCrvs[1], WIN_PRC_OVERMAT_IN, 0)
CopyInfo( nPartId, vLogCrvs[1], WIN_PRC_OVERMAT_OUT, 0)
local nOvermatLateral = EgtGetInfo( vLogCrvs[1], WIN_PRC_OVERMAT_RIGHT, 'd')
EgtSetInfo( nPartId, WIN_PRC_OVERMAT_RIGHT, nOvermatLateral)
EgtSetInfo( nPartId, WIN_PRC_OVERMAT_LEFT, nOvermatLateral)
-- costruisco il grezzo a partire dai tronchetti
local vCrvs = {}
local vIdIn = {}
-- recupero le curve in e out dei tronchetti
for i = #vLogCrvs, 1, -1 do
local nLineOut = EgtLine( nGeoRawLayerId, EgtUP( vLogCrvs[i], 0), EgtUP( vLogCrvs[i], 1))
local nLineIn = EgtLine( nGeoRawLayerId, EgtUP( vLogCrvs[i], 2), EgtUP( vLogCrvs[i], 3))
table.insert( vCrvs, nLineOut)
table.insert( vIdIn, nLineIn)
end
local nLineR = EgtLine( nGeoRawLayerId, EgtEP( vCrvs[#vCrvs]), EgtSP( vIdIn[#vIdIn]))
table.insert( vCrvs, nLineR)
for i = #vIdIn, 1, -1 do
table.insert( vCrvs, vIdIn[i])
end
local nLineL = EgtLine( nGeoRawLayerId, EgtEP( vIdIn[1]), EgtSP( vCrvs[1]))
table.insert( vCrvs, nLineL)
-- taglio le curve nelle intersezioni ( va eliminato il sovramateriale per minizinken)
local nPrevId = vCrvs[#vCrvs]
local vPtInters = {}
for i = 1, #vCrvs do
vPtInters[i] = FindIntersectionPoint( nPrevId, vCrvs[i], EgtSP( vCrvs[i]))
nPrevId = vCrvs[i]
end
vPtInters[#vPtInters + 1] = vPtInters[1]
for i = 1, #vCrvs do
EgtExtendCurveStartByLen( vCrvs[i], 100)
EgtExtendCurveEndByLen( vCrvs[i], 100)
local dParS = EgtCurveParamAtPoint( vCrvs[i], vPtInters[i])
local dParE = EgtCurveParamAtPoint( vCrvs[i], vPtInters[i+1])
EgtTrimCurveStartEndAtParam( vCrvs[i], dParS, dParE)
end
-- costruisco la compo del grezzo
local nCompo = EgtCurveCompo( nGeoRawLayerId, vCrvs)
local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
local dDimH = EgtGetInfo( nGeoLayerId, WIN_GEOHEIGHT, 'd')
EgtModifyCurveThickness( nCompo, - dDimH)
-- creo il frame ausiliario
local vtX = EgtSV( nCompo)
local frGeo = Frame3d( EgtSP( nCompo), vtX, Z_AX() ^ vtX, Z_AX())
local nFrameId = EgtFrame( nGeoRawLayerId, frGeo)
EgtSetName( nFrameId, WIN_PRC_FRAME)
end
---------------------------------------------------------------------
-- funzione che calcola i tronchetti di un pezzo ad arco
function WinCalculate.CreateArcLogs( nPartId, nLogsNbr, vSections, bAlign, dOverMatOut, dOverMatIn, dOverMatExt, dOverMatInt, bCutExtremities)
-- verifico dati in ingresso
if bAlign then nLogsNbr = 0 end
if not bAlign and nLogsNbr == 0 and ( #vSections == 0 or #vSections > 1) then
return
end
-- recupero o creo il gruppo per i tronchetti
local nGrp = EgtGetFirstNameInGroup( nPartId, WIN_LOGS)
if not nGrp then
nGrp = EgtGroup( nPartId)
EgtSetName( nGrp, WIN_LOGS)
else
EgtEmptyGroup( nGrp)
end
-- recupero il geo del pezzo
local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
local nGeoIn = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_IN)
local nGeoOut = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_OUT)
-- spezzo l'arco interno
SplitArc( nLogsNbr, vSections, bAlign, dOverMatOut + dOverMatIn, nGeoIn, nGeoOut, nGrp)
-- calcolo la sezione di riferimento per i tronchetti
local dSection = CalcLogsSection( nLogsNbr, vSections, bAlign, dOverMatOut + dOverMatIn, nGeoIn, nGeoOut, nGrp)
if not dSection then
return
end
-- creo i tronchetti
CalcLogs( nGrp, nGeoOut, dOverMatIn, dOverMatOut, dOverMatExt, dOverMatInt, dSection, bCutExtremities)
-- TODO : recupero modalità di lavorazione dei tronchetti
local bFinishedLogs = false
-- creo i pezzi associati ai tronchetti
local vLogs = EgtGetInfo( nPartId, WIN_LOGS, 'vi') or {}
EgtErase( vLogs)
CalcLogParts( nPartId, bFinishedLogs)
if not bFinishedLogs then
-- sistemo il Georaw per il pezzo ad arco
CalcGeoRawFromLogs( nPartId)
else
-- TODO segnalare che il pezzo non va lavorato
end
end
----------------------------------------------------------------------------------
---------------------------------- FERRAMENTA ----------------------------------
----------------------------------------------------------------------------------
-- funzione che disegna le cerniere
local function DrawHingesStd( nOutlineId, nSolidLayerId)
-- dimensioni cerniere
local dDimH = 16
local dDimV = 70
local dFilletRad = 5
local nFrameOutlineId = abs( EgtGetInfo( nOutlineId, WIN_SOU_OUTLINE, 'i'))
local dDelta = ( EgtSP( nOutlineId) - EgtSP( nFrameOutlineId)) * Z_AX()
if dDelta < GEO.EPS_SMALL then
return
end
local vtDir = EgtSV( nOutlineId)
local vtDirIn = Vector3d( vtDir)
vtDirIn:rotate( Z_AX(), -90)
-- prima cerniera
local pt1 = EgtSP( nOutlineId) - dDelta * Z_AX()
local nCompo = EgtCurveCompoFromPoints( nSolidLayerId, { pt1 + dFilletRad * vtDir, pt1 + ( dDimV - dFilletRad) * vtDir})
EgtAddCurveCompoArcTg( nCompo, pt1 + dDimV * vtDir + dFilletRad * vtDirIn)
EgtAddCurveCompoLine( nCompo, pt1 + dDimV * vtDir + ( dDimH - dFilletRad) * vtDirIn)
EgtAddCurveCompoArcTg( nCompo, pt1 + ( dDimV - dFilletRad) * vtDir + dDimH * vtDirIn)
EgtAddCurveCompoLine( nCompo, pt1 + dFilletRad * vtDir + dDimH * vtDirIn)
EgtAddCurveCompoArcTg( nCompo, pt1 + ( dDimH - dFilletRad) * vtDirIn)
EgtAddCurveCompoLine( nCompo, pt1 + dFilletRad * vtDirIn)
EgtAddCurveCompoArcTg( nCompo, EgtSP( nCompo))
local nStm1 = EgtSurfTmByRegionExtrusion( nSolidLayerId, nCompo, dDelta * Z_AX())
EgtSetColor( nStm1, Color3d( 128, 128, 128))
EgtSetName( nStm1, WIN_HDW_HINGES)
EgtErase( nCompo)
-- seconda cerniera
local pt2 = EgtEP( nOutlineId) - dDelta * Z_AX() - dDimV * vtDir
local nStm2 = EgtCopyGlob( nStm1, nSolidLayerId)
EgtMove( nStm2, pt2 - pt1)
-- correzioni per telai non rettangolari
local nFrameAreaId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*')
local nFrameType = EgtGetInfo( nFrameAreaId, WIN_FRAME_TYPE, 'i')
-- a) arco
if nFrameType == WIN_FRAME_TYPES.ROUND_ARC or nFrameType == WIN_FRAME_TYPES.SEGMENTAL_ARC then
local sName = EgtGetName( nOutlineId)
-- calcolo il delta da applicare ( euristico, calcolato in base ai risultati ferramenta)
local dDelta = 24 -- caso di arco a tutto sesto
local dDeltaSegArc = 54.7 -- caso di arco ribassato
if nFrameType == WIN_FRAME_TYPES.SEGMENTAL_ARC then
-- nel caso di arco ribassato il delta va calcolato rispetto al frame della ferramenta
local nAreaId = EgtGetParent( EgtGetParent( nOutlineId))
local nHdwFramesId = EgtGetFirstNameInGroup( nAreaId, WIN_HDW_FRAME)
local sFrameName = EgtIf( sName == WIN_LEFT, 'B*', 'C*')
local nFrameId = EgtGetFirstNameInGroup( nHdwFramesId, sFrameName)
if sName == WIN_LEFT then
dDelta = ( EgtSP( nFrameId) - EgtSP( nOutlineId)) * vtDir
else
dDelta = ( EgtEP( nOutlineId) - EgtSP( nFrameId)) * vtDir
end
dDelta = dDelta + dDeltaSegArc
end
-- traslazione
if sName == WIN_LEFT then
EgtMove( nStm1, dDelta * vtDir)
else
EgtMove( nStm2, - dDelta * vtDir)
end
-- b) trapezio
elseif nFrameType == WIN_FRAME_TYPES.CHAMFER_SIDE then
-- calcolo il delta da applicare. Euristico. Dal calcolo della ferramenta si vede che la cerniera si trova circa nel punto di intersezione tra nOutlineId e una retta inclinata
-- come il top e passante per il frame della ferramenta
local sName = EgtGetName( nOutlineId)
local nOutlineLayId = EgtGetParent( nOutlineId)
local nAreaId = EgtGetParent( nOutlineLayId)
local nHdwFramesId = EgtGetFirstNameInGroup( nAreaId, WIN_HDW_FRAME)
local sFrameName = EgtIf( sName == WIN_LEFT, 'B*', 'C*')
local nFrameId = EgtGetFirstNameInGroup( nHdwFramesId , sFrameName)
local nTopId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_TOP)
local vtTop = EgtSV( nTopId)
local ptRef = EgtIf( sName == WIN_LEFT, EgtSP( nOutlineId), EgtEP( nOutlineId))
local vtDist = EgtSP( nFrameId) - ptRef
local dDelta = ( vtDist ^ vtTop):len() / ( vtTop ^ vtDir):len()
if sName == WIN_LEFT then
EgtMove( nStm1, dDelta * vtDir)
else
EgtMove( nStm2, - dDelta * vtDir)
end
end
end
---------------------------------------------------------------------
-- funzione che disegna le cerniere per la preview ( posizionamento più grossolano e disegno 2d)
local function DrawHingesPreview( nOutlineId, nLayerId)
-- dimensioni cerniere
local dDimL = 80
local dDimW = 20
local nFrameOutlineId = abs( EgtGetInfo( nOutlineId, WIN_SOU_OUTLINE, 'i'))
local dDelta = ( EgtSP( nOutlineId) - EgtSP( nFrameOutlineId)) * Z_AX()
if dDelta < GEO.EPS_SMALL then
return
end
local vtDir = EgtSV( nOutlineId)
local vtDirIn = Vector3d( vtDir)
vtDirIn:rotate( Z_AX(), -90)
-- alzo leggermente la quota in z per evitare sovrapposizioni problematiche nell'eportazione svg
local frHinge = Frame3d( EgtSP( nOutlineId) + Z_AX(), vtDir, vtDirIn, - Z_AX())
-- prima cerniera
local nSfr1 = EgtSurfFrStadium( nLayerId, ORIG(), Point3d( dDimL, dDimW, 0))
EgtSetColor( nSfr1, Color3d( 128, 128, 128))
EgtTransform( nSfr1, frHinge)
EgtInvertSurf( nSfr1)
-- seconda cerniera
local pt2 = EgtEP( nOutlineId) - dDimL * vtDir
local nSfr2 = EgtCopyGlob( nSfr1, nLayerId)
EgtMove( nSfr2, pt2 - EgtSP( nOutlineId))
-- contorni
local nLoop1 = EgtExtractSurfFrChunkLoops( nSfr1, 0, nLayerId)
EgtSetColor( nLoop1, EgtStdColor( 'BLACK'))
local nLoop2 = EgtExtractSurfFrChunkLoops( nSfr2, 0, nLayerId)
EgtSetColor( nLoop2, EgtStdColor( 'BLACK'))
end
---------------------------------------------------------------------
local function DrawHinges( nOutlineId, nLayerId, bPreview)
if bPreview then
DrawHingesPreview( nOutlineId, nLayerId)
else
DrawHingesStd( nOutlineId, nLayerId)
end
end
---------------------------------------------------------------------
-- funzione che disegna la maniglia
local function DrawHandleStd( nOutlineId, sHandleSide, dHandleH, nSolidLayerId, bSlide)
-- dati della maniglia
local dBase1T = 40
local dBase1B = 40
local dBase2 = 18
local dH = 9
local dLen1 = 53
local dLen2 = 115
local dRadH = 12.5
local dFillet = 10
local dExtraGapDelta = 15
if bSlide then
dBase1T = 50
dBase1B = 100
dBase2 = 18
dLen2 = 155
dRadH = 10
dExtraGapDelta = 35.5
end
local nPartId = EgtGetInfo( nOutlineId, WIN_REF_PART, 'i')
local ptRef = EgtIf( sHandleSide == 'Sx', EgtSP( nOutlineId), EgtEP( nOutlineId))
local vtDir = EgtIf( sHandleSide == 'Sx', EgtSV( nOutlineId), - EgtEV( nOutlineId))
local vtDirIn = Vector3d( vtDir)
vtDirIn:rotate( Z_AX(), EgtIf( sHandleSide == 'Sx', 90, -90))
-- recupero il riferimento rispetto a cui leggere l'altezza maniglia
local nProfileLayId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLayId, EgtIf( sHandleSide == 'Sx', WIN_PRF_START, WIN_PRF_END))
local dGapHardware = EgtGetInfo( nProfileId, WIN_GAPDELTA, 'd')
-- recupero di quanto spostare la maniglia rispetto all'outline
local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayId, WIN_PRF_MAIN)
local dGapDelta = EgtGetInfo( nMainProfileId, WIN_GAPDELTA, 'd')
local dDeltaIn = dGapDelta + dExtraGapDelta
-- punto su cui centrare la maniglia
local ptC = ptRef + ( dHandleH + dGapHardware) * vtDir + dDeltaIn * vtDirIn
local nCrv1 = EgtRectangle2P( nSolidLayerId, ptC - dBase1B * vtDir - dBase2 * vtDirIn, ptC + dBase1T * vtDir + dBase2 * vtDirIn)
local nStm1 = EgtSurfTmByRegionExtrusion( nSolidLayerId, {nCrv1}, dH * Z_AX())
local nCrv2 = EgtLinePVL( nSolidLayerId, ORIG(), X_AX(), dLen1 - dFillet)
local nCrv4 = EgtLinePVL( nSolidLayerId, Point3d( dLen1, -dFillet, 0), - Y_AX(), dLen2 - dFillet)
local nCrv3 = EgtArc2PR( nSolidLayerId, EgtEP( nCrv2), EgtSP( nCrv4), dFillet, false)
local nGuide = EgtCurveCompo( nSolidLayerId, { nCrv2, nCrv3, nCrv4})
local frTransf = Frame3d( ptC, Z_AX(), vtDir, Z_AX() ^ vtDir)
EgtTransform( nGuide, frTransf)
local nSection = EgtCircle( nSolidLayerId, EgtSP( nGuide), dRadH)
local nStm2 = EgtSurfTmSwept( nSolidLayerId, nSection, nGuide, true)
EgtSurfTmAdd( nStm1, nStm2)
EgtSetName( nStm1, WIN_HDW_HANDLE)
EgtSetColor( nStm1, Color3d( 128, 128, 128))
EgtErase( { nCrv1, nGuide, nSection, nStm2})
end
---------------------------------------------------------------------
-- disegno della maniglia per preview
local function DrawHandlePreview( nOutlineId, sHandleSide, dHandleH, nLayerId, bSlide)
-- dati della maniglia
local dRad = 20
local dDimW = 20
local dDimH = 100
local ptRef = EgtIf( sHandleSide == 'Sx', EgtSP( nOutlineId), EgtEP( nOutlineId))
local vtDir = EgtIf( sHandleSide == 'Sx', - EgtSV( nOutlineId), EgtEV( nOutlineId))
local vtDirIn = Vector3d( vtDir)
vtDirIn:rotate( Z_AX(), EgtIf( sHandleSide == 'Sx', -90, 90))
-- recupero dati del profilo per centrare la maniglia sul pezzo
local nPartId = EgtGetInfo( nOutlineId, WIN_REF_PART, 'i')
local nProfileLayId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayId, WIN_PRF_MAIN)
local b3Profile = GetProfileLocalBox( nMainProfileId)
local dSide = abs( b3Profile:getMin():getX() + 0.5 * b3Profile:getDimX())
-- correzione per caso speciale di telaio e ante allineate ( euristica)
local nParentAreaId = EgtGetParent( EgtGetParent( nOutlineId))
local nSashType = EgtGetInfo( nParentAreaId, WIN_SASHTYPE, 'i') or WIN_SASHTYPES.NULL
if nSashType == WIN_SASHTYPES.NULL then
local nFrameOutlineId = abs( EgtGetInfo( nOutlineId, WIN_SOU_OUTLINE, 'i'))
local dDelta = ( EgtSP( nOutlineId) - EgtSP( nFrameOutlineId)) * Z_AX()
if dDelta < GEO.EPS_SMALL then
dSide = dSide + 9
end
end
-- punto su cui centrare la maniglia
local ptC = ptRef - dHandleH * vtDir + dSide * vtDirIn + Z_AX()
local nSfr1 = EgtSurfFrDisk( nLayerId, ptC, dRad)
EgtSetColor( nSfr1, Color3d( 128, 128, 128))
local nLoop = EgtExtractSurfFrChunkLoops( nSfr1, 0, nLayerId)
EgtSetColor( nLoop, EgtStdColor( 'BLACK'))
local nSfr2 = EgtSurfFrStadium( nLayerId, ORIG(), Point3d( dDimH, dDimW, 0))
local ptFrame = ptC + EgtIf( sHandleSide == 'Sx', 1, -1) * 0.5 * dDimW * vtDirIn + Z_AX()
local frHandle = Frame3d( ptFrame, vtDir, EgtIf( sHandleSide == 'Sx', - vtDirIn, vtDirIn), Z_AX())
EgtTransform( nSfr2, frHandle)
EgtSetColor( nSfr2, Color3d( 128, 128, 128))
local nLoop2 = EgtExtractSurfFrChunkLoops( nSfr2, 0, nLayerId)
EgtSetColor( nLoop2, EgtStdColor( 'BLACK'))
end
---------------------------------------------------------------------
local function DrawHandle( nOutlineId, sHandleSide, dHandleH, nLayerId, bSlide, bPreview)
if bPreview then
DrawHandlePreview( nOutlineId, sHandleSide, dHandleH, nLayerId, bSlide)
else
DrawHandleStd( nOutlineId, sHandleSide, dHandleH, nLayerId, bSlide)
end
end
---------------------------------------------------------------------
local function GetHandleHeight( nAreaId)
-- verifico se è definita tra le opzioni
local vOptions = EgtGetInfo( nAreaId, WIN_HDW_OPTIONS, 'vs') or {}
for i = 1, #vOptions do
local vString = EgtSplitString( vOptions[i], '=')
if #vString == 2 and vString[1] == WIN_HDW_HANDLE_HEIGHT then
local dVal = tonumber( vString[2])
if dVal then
return dVal
else
break
end
end
end
-- chiedo il file di opzioni dalla ferramenta
local _, _, tOptions = WinCalculate.AddHardware( nAreaId, false, false, false, true)
if #tOptions > 0 then
-- lettura della stringa xml delle opzioni
local handler = XMLHandler:new()
local parser = XML.parser( handler)
parser:parse( tOptions[1])
local tabOptions = handler.root
-- cerco parametro altezza maniglia
for i = 1, #tabOptions['ParametriOpzioni']['Parametri'] do
if tabOptions['ParametriOpzioni']['Parametri'][i]['NomeParametro'] == WIN_HDW_HANDLE_HEIGHT then
local sHandleH = tabOptions['ParametriOpzioni']['Parametri'][i]['ValoreCorrente']
return tonumber( sHandleH)
end
end
end
return 500 -- restituisco valore di default
end
---------------------------------------------------------------------
-- funzione che disegna la ferramenta
local function DrawSashHardware( nAreaId, nRefAreaId, nLayerId, bPreview)
local nOutlineLayId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local nOpeningType = EgtGetInfo( nAreaId, WIN_OPENING_TYPE, 'i')
if nOpeningType == WIN_OPENING_TYPES.NULL or nOpeningType == WIN_OPENING_TYPES.FIXED then
return
-- Vasistas
elseif nOpeningType == WIN_OPENING_TYPES.TILTONLY_TOP then
-- cerniere sul pezzo inferiore
local nBottomId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_BOTTOM)
DrawHinges( nBottomId, nLayerId, bPreview)
-- recupero lato maniglia
local vOptions = EgtGetInfo( nRefAreaId, WIN_HDW_OPTIONS, 'vs') or {}
local sOptionHandleSide
for i = 1, #vOptions do
local vString = EgtSplitString( vOptions[i], '=')
if vString[1] == 'PosizioneManiglia' then
sOptionHandleSide = vString[2]
break
end
end
-- se non ho trovato l'opzione la recupero dalle opzioni di default ( simile a GetHandleHeigt)
if not sOptionHandleSide then
local _, _, tOptions = WinCalculate.AddHardware( nAreaId, false, false, false, true)
if #tOptions > 0 then
-- lettura della stringa xml delle opzioni
local handler = XMLHandler:new()
local parser = XML.parser( handler)
parser:parse( tOptions[1])
local tabOptions = handler.root
-- cerco parametro altezza maniglia
for i = 1, #tabOptions['ParametriOpzioni']['Parametri'] do
if tabOptions['ParametriOpzioni']['Parametri'][i]['NomeParametro'] == 'PosizioneManiglia' then
sOptionHandleSide = tabOptions['ParametriOpzioni']['Parametri'][i]['ValoreCorrente']
end
end
end
end
local sHandleSide = 'Sx'
local nOutlineId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_RIGHT)
if sOptionHandleSide == 'destra' then
sHandleSide = 'Dx'
nOutlineId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_LEFT)
elseif sOptionHandleSide == 'sopra' then
nOutlineId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_TOP)
end
-- altezza maniglia è fissata a metà del lato ( con compensazione per frame di riferimento della ferramenta)
local nPartId = EgtGetInfo( nOutlineId, WIN_REF_PART, 'i')
local nProfileLayId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLayId, EgtIf( sHandleSide == 'Sx', WIN_PRF_START, WIN_PRF_END))
local dGapHardware = EgtGetInfo( nProfileId, WIN_GAPDELTA, 'd')
local dHandleH = 0.5 * EgtCurveLength( nOutlineId) - dGapHardware
-- disegno maniglia
DrawHandle( nOutlineId, sHandleSide, dHandleH, nLayerId, false, bPreview)
-- Alzante scorrevole
elseif nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_LEFT or nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_RIGHT or
nOpeningType == WIN_OPENING_TYPES.LIFTSLIDE_LEFT or nOpeningType == WIN_OPENING_TYPES.LIFTSLIDE_RIGHT then
local bLeftSlide = ( nOpeningType == WIN_OPENING_TYPES.COPLANARSLIDE_LEFT or nOpeningType == WIN_OPENING_TYPES.LIFTSLIDE_LEFT)
local nOutlineId = EgtGetFirstNameInGroup( nOutlineLayId, EgtIf( bLeftSlide, WIN_RIGHT, WIN_LEFT))
local sHandleSide = EgtIf( bLeftSlide, 'Sx', 'Dx')
-- recupero altezza maniglia dalle opzioni
local dHandleH = GetHandleHeight( nRefAreaId)
DrawHandle( nOutlineId, sHandleSide, dHandleH, nLayerId, true, bPreview)
-- Standard
else
local nSashType = EgtGetInfo( nAreaId, WIN_SASHTYPE, 'i') or WIN_SASHTYPES.NULL
-- recupero pezzi interessati dalla ferramenta
local nLeftId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_LEFT)
local nRightId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_RIGHT)
-- recupero lato maniglia
local sHandleSide = EgtGetInfo( nRefAreaId, WIN_HDW_HANDLE)
-- cerniere
if nSashType == WIN_SASHTYPES.INACTIVE or nSashType == WIN_SASHTYPES.INACTIVE_OUT or
nSashType == WIN_SASHTYPES.ACTIVE or nSashType == WIN_SASHTYPES.ACTIVE_OUT then
-- le cerniere vanno messe sul lato che poggia sul telaio
local bLeftInactive = EgtGetInfo( nLeftId, WIN_CRV_ON_FRENCH_SPLIT, 'b') or false
DrawHinges( EgtIf( bLeftInactive, nRightId, nLeftId), nLayerId, bPreview)
elseif nSashType == WIN_SASHTYPES.NULL then
-- è il lato senza maniglia
if sHandleSide == 'Sx' then
DrawHinges( nLeftId, nLayerId, bPreview)
else
DrawHinges( nRightId, nLayerId, bPreview)
end
end
-- maniglia
if nSashType == WIN_SASHTYPES.ACTIVE or nSashType == WIN_SASHTYPES.ACTIVE_IN or nSashType == WIN_SASHTYPES.NULL then
-- recupero altezza maniglia
local dHandleH = GetHandleHeight( nRefAreaId)
if sHandleSide == 'Sx' then
DrawHandle( nRightId, sHandleSide, dHandleH, nLayerId, false, bPreview)
else
DrawHandle( nLeftId, sHandleSide, dHandleH, nLayerId, false, bPreview)
end
end
end
end
---------------------------------------------------------------------
-- funzione che calcola i dati necessari per la ferramenta
local function SearchSash( nAreaId, SashList)
-- verifico il tipo
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
-- creo gruppo temporaneo per i conti
local nOutlineOffsetLayerId = EgtGroup( nAreaId)
-- creo gruppo per i riferimenti della ferramenta per l'anta
local nHdwSashLayerId = EgtGroup( nAreaId)
EgtSetName( nHdwSashLayerId, WIN_HDW_FRAME)
EgtSetStatus( nHdwSashLayerId, GDB_ST.OFF)
-- recupero o creo gruppo per i riferimenti della ferramenta per il telaio
local nFrameAreaId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*')
local nHdwFrameLayerId = EgtGetFirstNameInGroup( nFrameAreaId, WIN_HDW_FRAME)
if not nHdwFrameLayerId then
nHdwFrameLayerId = EgtGroup( nFrameAreaId)
EgtSetName( nHdwFrameLayerId, WIN_HDW_FRAME)
EgtSetStatus( nHdwFrameLayerId, GDB_ST.OFF)
end
-- verifico se alzante scorrevole
local bSlide = EgtGetInfo( nFrameAreaId, WIN_SLIDE_WINDOW, 'b') or false
-- ricostruisco gli outlines dell'anta in corrispondenza del canalino della ferramenta ( orgine dei riferimenti)
local vOutlineCopy = {}
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local nOutlineId = EgtGetFirstInGroup( nOutlineLayerId)
while nOutlineId do
local nSashProfileId = GetOutlineProfileId( nOutlineId)
local dGapDelta = EgtGetInfo( nSashProfileId, WIN_GAPDELTA, 'd')
local nOutlineCopyId = EgtCopy( nOutlineId, nOutlineOffsetLayerId)
EgtOffsetCurve( nOutlineCopyId, - dGapDelta)
table.insert( vOutlineCopy, nOutlineCopyId)
-- setto info ausiliarie sulla curva
EgtSetInfo( nOutlineCopyId, 'ORIG', nOutlineId)
CopyInfo( nOutlineCopyId, nSashProfileId, WIN_GAPDELTAZ)
local b3Profile = GetProfileLocalBox( nSashProfileId)
EgtSetInfo( nOutlineCopyId, WIN_GAPDELTAZ .. 2, b3Profile:getDimY())
nOutlineId = EgtGetNext( nOutlineId)
end
vOutlineCopy = TrimOrderedCurves( vOutlineCopy, true)
-- costruisco i riferimenti
local tFrame = {}
for i = 1, #vOutlineCopy do
-- 1) Riferimenti ANTA
local ptOrig = EgtEP( vOutlineCopy[i])
local sOrigName = string.char( string.byte( 'A') + #vOutlineCopy - i)
local vtDir = EgtEV( vOutlineCopy[i])
local nFA1Id = EgtFrame( nHdwSashLayerId, Frame3d( ptOrig, - vtDir, vtDir ^ Z_AX(), Z_AX()))
EgtSetName( nFA1Id, sOrigName .. '.FA1')
local vtIn = Vector3d( vtDir)
vtIn:rotate( Z_AX(), -90)
local dGapDeltaZ = EgtGetInfo( vOutlineCopy[i], WIN_GAPDELTAZ, 'd')
local nFA2Id = EgtFrame( nHdwSashLayerId, Frame3d( ptOrig - dGapDeltaZ * Z_AX(), - vtDir, vtDir ^ vtIn, vtIn))
EgtSetName( nFA2Id, sOrigName .. '.FA2')
local dGapDeltaZ2 = EgtGetInfo( vOutlineCopy[i], WIN_GAPDELTAZ .. 2, 'd')
local nFA3Id = EgtFrame( nHdwSashLayerId, Frame3d( ptOrig - dGapDeltaZ2 * Z_AX(), - vtDir, vtDir ^ -Z_AX(), -Z_AX()))
EgtSetName( nFA3Id, sOrigName .. '.FA3')
-- 2) Riferimenti TELAIO
-- ricavo elemento su cui poggia. Deve essere un elemento reale, quindi se fosse french split lo ignoro
local bFrenchSplit = EgtGetInfo( vOutlineCopy[i], WIN_CRV_ON_FRENCH_SPLIT, 'b')
if not bFrenchSplit then
local nSouId = EgtGetInfo( vOutlineCopy[i], WIN_SOU_OUTLINE, 'i')
-- ricavo aria lato telaio
local nFrameProfileId = GetOutlineProfileId( abs( nSouId))
local dGapDeltaOut = EgtGetInfo( nFrameProfileId, WIN_GAPDELTA, 'd')
if not dGapDeltaOut then
-- recupero informazione dal lato corretto ( split orizzontale)
if nSouId > 0 then
dGapDeltaOut = EgtGetInfo( nFrameProfileId, WIN_GAPDELTA .. '2', 'd')
else
dGapDeltaOut = EgtGetInfo( nFrameProfileId, WIN_GAPDELTA .. '1', 'd')
end
end
-- verifico il segno dell'offset
if nSouId < 0 then
dGapDeltaOut = - dGapDeltaOut
end
local nOutlineOutId = EgtCopy( abs( nSouId), nOutlineOffsetLayerId)
EgtOffsetCurve( nOutlineOutId, - dGapDeltaOut)
-- recupero origine come proiezione sul telaio dell'origine dell'anta
local _, ptOrigFr = EgtPointCurveDist( ptOrig, nOutlineOutId)
if bSlide then
-- nel caso di alzante scorrevole l'origine non è proiettata
ptOrigFr = EgtEP( nOutlineOutId)
end
local nFT1Id = EgtFrame( nHdwFrameLayerId, Frame3d( ptOrigFr, - vtDir, vtDir ^ Z_AX(), Z_AX()))
EgtSetName( nFT1Id, sOrigName .. '.FT1')
table.insert( tFrame, nFT1Id)
local vtFrameIn = Vector3d( vtDir)
vtFrameIn:rotate( Z_AX(), 90)
local dFrameGapDeltaZ = EgtGetInfo( nFrameProfileId, WIN_GAPDELTAZ, 'd')
local nFT2Id = EgtFrame( nHdwFrameLayerId, Frame3d( ptOrigFr - dFrameGapDeltaZ * Z_AX(), - vtDir, vtDir ^ vtFrameIn, vtFrameIn))
EgtSetName( nFT2Id, sOrigName .. '.FT2')
table.insert( tFrame, nFT2Id)
local b3FrameProfile = GetProfileLocalBox( nFrameProfileId)
local dGapDeltaZ2 = b3FrameProfile:getDimY()
local nFT3Id = EgtFrame( nHdwFrameLayerId, Frame3d( ptOrigFr - dGapDeltaZ2 * Z_AX(), - vtDir, vtDir ^ -Z_AX(), -Z_AX()))
EgtSetName( nFT3Id, sOrigName .. '.FT3')
table.insert( tFrame, nFT3Id)
end
end
-- preparo tabella per l'anta con i dati necessari per la ferramenta
local tSash = { nAreaId = nAreaId}
-- calcolo in centro per ordinamento
local b3Outline = EgtGetBBox( nOutlineLayerId, GDB_BB.STANDARD)
tSash.ptCenter = b3Outline:getCenter()
-- calcolo le dimensioni
tSash.LHeight = EgtCurveLength( vOutlineCopy[4])
tSash.RHeight = EgtCurveLength( vOutlineCopy[2])
tSash.BWidth = EgtCurveLength( vOutlineCopy[1])
if EgtGetType( vOutlineCopy[3]) == GDB_TY.CRV_ARC then
-- tSash.BCLength = EgtCurveLength( vOutlineCopy[3]) -- in alternativa a BCArrow, è il parametro LBBA nel file di richiesta
tSash.BCArrow = dist( EgtMP( vOutlineCopy[3]), 0.5 * ( EgtEP( vOutlineCopy[3]) + EgtSP( vOutlineCopy[3])))
end
-- salvo i frame del telaio associati
tSash.Frame = tFrame
table.insert( SashList, tSash)
EgtErase( nOutlineOffsetLayerId)
end
-- verifico se ci sono sotto-aree
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
-- lancio costruzione pezzi di quell'area
SearchSash( nChildAreaId, SashList)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
---------------------------------------------------------------------
-- funzione che calcola le lavorazioni dell'hardware
local function CalcHdwMachining( tMachining, SashList)
local nFrameAreaId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*')
local nHdwFrameLayerId = EgtGetFirstNameInGroup( nFrameAreaId, WIN_HDW_FRAME)
for i = 1, #tMachining do
local sPart = tMachining[i]['WindowPart']
local nSashIndex = tMachining[i]['SashIndex']
local sSashPart = tMachining[i]['SashPart']
local dPosX = tMachining[i]['PosX']
local dPosY = tMachining[i]['PosY']
local dPosZ = tMachining[i]['PosZ']
local sMacro = tMachining[i]['Macro']
local sSide = tMachining[i]['Side'] -- FT1, FT2, FT3, FA1, FA2, FA3
local sOrigin = tMachining[i]['Origin'] -- AB, BC, CD, DA
local nSashId = SashList[nSashIndex].nAreaId
local nOutlineLayerId = EgtGetFirstNameInGroup( nSashId, WIN_OUTLINE)
local vOutlineIds = EgtGetAllInGroup( nOutlineLayerId)
local nA = string.byte( 'A')
local nSashPart = string.byte( sSashPart)
local nOutlineIndex = #vOutlineIds - ( nSashPart - nA)
local nOutlineId = vOutlineIds[nOutlineIndex]
local nPartId = GDB_ID.NULL
local frHdw
if sPart == 'TELAIO' then
local nFrameOutlineId = abs( EgtGetInfo( nOutlineId, WIN_SOU_OUTLINE, 'i'))
nPartId = EgtGetInfo( nFrameOutlineId, WIN_REF_PART, 'i')
local nHdwFrameId = EgtGetLastNameInGroup( nHdwFrameLayerId, nSashIndex .. '.' .. sSashPart .. '.' .. sSide)
frHdw = EgtFR( nHdwFrameId)
elseif sPart == 'ANTA' then
nPartId = EgtGetInfo( nOutlineId, WIN_REF_PART, 'i')
local nHdwFrameLayerId = EgtGetFirstNameInGroup( nSashId, WIN_HDW_FRAME)
local nHdwFrameId = EgtGetLastNameInGroup( nHdwFrameLayerId, sSashPart .. '.' .. sSide)
frHdw = EgtFR( nHdwFrameId)
end
local nProcLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PRC)
-- recupero solido ( se non calcolato non vengono utilizzate)
local nSolidLayerId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID) or GDB_ID.NULL
local nMainExtrusionId = EgtGetFirstNameInGroup( nSolidLayerId, WIN_SRF_MAIN)
local nOrigMainId = EgtGetFirstNameInGroup( nSolidLayerId, WIN_SRF_ORIGMAIN)
-- calcolo il punto centrale della lavorazione
local ptCenter = Point3d( dPosX, dPosY, dPosZ)
-- gestione particolare per traverso superiore ad arco
if EgtGetType( nOutlineId) == GDB_TY.CRV_ARC then
local nProfileLayId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLayId, WIN_PRF_MAIN)
-- calcolo outline del telaio sul canalino della ferramenta
local nRefOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i')
local nOffsetId = EgtCopyGlob( nRefOutlineId, nPartId)
local dGapDelta = EgtGetInfo( nProfileId, WIN_GAPDELTA, 'd')
EgtOffsetCurve( nOffsetId, - dGapDelta)
-- recupero origine sulla curva di offset a partire dai frame dell'anta
local nHdwSashLayerId = EgtGetFirstNameInGroup( nSashId, WIN_HDW_FRAME)
local sHdwName = EgtIf( sOrigin == 'AB', 'B', 'C') .. '.FA1'
local nHdwSashId = EgtGetLastNameInGroup( nHdwSashLayerId, sHdwName)
local _, _, dParRef = EgtPointCurveDist( EgtSP( nHdwSashId), nOffsetId)
local dLen = EgtCurveLengthAtParam( nOffsetId, dParRef)
dLen = dLen + dPosX
local dPar = EgtCurveParamAtLength( nOffsetId, dLen)
local ptOrig = EgtUP( nOffsetId, dPar)
-- ricostruisco il frame in base alla nuova origine
local vtDir = EgtUV( nOffsetId, dPar, -1)
if sSide == 'FT1' or sSide == 'FA1' then
frHdw = Frame3d( ptOrig, - vtDir, vtDir ^ Z_AX(), Z_AX())
elseif sSide == 'FT2' or sSide == 'FA2' then
local vtDirIn = Vector3d( vtDir)
vtDirIn:rotate( Z_AX(), 90)
local dFrameGapDeltaZ = EgtGetInfo( nProfileId, WIN_GAPDELTAZ, 'd')
frHdw = Frame3d( ptOrig - dFrameGapDeltaZ * Z_AX(), - vtDir, vtDir ^ vtDirIn, vtDirIn)
elseif sSide == 'FT3' or sSide == 'FA3' then
local b3FrameProfile = GetProfileLocalBox( nProfileId)
local dGapDeltaZ2 = b3FrameProfile:getDimY()
frHdw = Frame3d( ptOrig - dGapDeltaZ2 * Z_AX(), - vtDir, vtDir ^ -Z_AX(), -Z_AX())
end
-- calcolo il centro della lavorazione riferito al nuovo frame
ptCenter = Point3d( 0, dPosY, dPosZ)
EgtErase( nOffsetId)
end
local vMacro = EgtSplitString( sMacro, '_')
if vMacro[1] == 'FRESATA' then
elseif vMacro[1] == 'ASOLA' or vMacro[1] == 'MANIGLIA' then
local dLength, dWidth, dHeight
if vMacro[1] == 'ASOLA' then
dLength = tonumber( vMacro[2])
dWidth = tonumber( vMacro[3])
dHeight = tonumber( vMacro[4])
-- NB in alcune macro ASOLA il secondo parametro non è la width ma la width/2 !
-- TODO Al momento sembra che questo avvenga solo quando il suo valore è 8. Da verificare
if abs( dWidth - 8) < GEO.EPS_SMALL then
dWidth = dWidth * 2
end
elseif vMacro[1] == 'MANIGLIA' and vMacro[2] == '160' then
-- macro speciale che corrisponde ad ASOLA_216_12_56 quindi forzo direttamente i valori
-- TODO gestione di queste macro non parlanti
dLength = 216
dWidth = 12
dHeight = 56
elseif vMacro[1] == 'MANIGLIA' then -- and vMacro[2] == '15'
-- corrisponde ad ASOLA_69_12_30
dLength = 69
dWidth = 12
dHeight = 30
end
local ptP1 = ptCenter + ( dLength / 2 - dWidth / 2) * X_AX() + dWidth / 2 * Y_AX()
local ptP2 = ptCenter - ( dLength / 2 - dWidth / 2) * X_AX() + dWidth / 2 * Y_AX()
local nPocketOutlineId = EgtCurveCompoFromPoints( nProcLayerId, { ptP1, ptP2})
EgtAddCurveCompoArcTg( nPocketOutlineId, ptCenter - ( dLength / 2 - dWidth / 2) * X_AX() - dWidth / 2 * Y_AX())
EgtAddCurveCompoArcTg( nPocketOutlineId, ptCenter + ( dLength / 2 - dWidth / 2) * X_AX() - dWidth / 2 * Y_AX(), false)
EgtCloseCurveCompo( nPocketOutlineId)
EgtSetColor( nPocketOutlineId, EgtStdColor( 'GRAY'))
-- setto info di lavorazione
EgtSetInfo( nPocketOutlineId, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING)
EgtSetInfo( nPocketOutlineId, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC)
EgtSetInfo( nPocketOutlineId, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.IN)
EgtModifyCurveExtrusion( nPocketOutlineId, Z_AX())
EgtModifyCurveThickness( nPocketOutlineId, - dHeight)
-- porto la lavorazione in globale
EgtTransform( nPocketOutlineId, frHdw)
-- aggiornamento del solido
if s_bCalcSolid then
UpdateSolidWithProcessingCrv( nPocketOutlineId, nMainExtrusionId, nSolidLayerId)
end
elseif vMacro[1] == 'TASCA' then
elseif vMacro[1] == 'VITE' then
local dRadius = 1.5
local dDepth = 2
if vMacro[2] == 'CANALINO' then
dRadius = 2
dDepth = 3
elseif vMacro[2] == 'ANTA' then
dRadius = 2.5
dDepth = 4
end
local nHoleId = EgtCircle( nProcLayerId, ptCenter, dRadius)
EgtMove( nHoleId, Z_AX())
EgtModifyCurveExtrusion( nHoleId, Z_AX())
EgtModifyCurveThickness( nHoleId, - ( dDepth + 1))
EgtTransform( nHoleId, frHdw)
EgtSetInfo( nHoleId, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.HOLE)
elseif vMacro[1] == 'FORO' then
local sDiameter = EgtReplaceString( vMacro[2], 'D', '')
local dRadius = tonumber( sDiameter) / 2
local nHoleId = EgtCircle( nProcLayerId, ptCenter, dRadius)
-- setto info di lavorazione
EgtModifyCurveExtrusion( nHoleId, Z_AX())
-- TODO : come gestire profondità non definita?
local dDepth = tonumber(25)
if #vMacro == 3 then
dDepth = tonumber( vMacro[3])
end
EgtModifyCurveThickness( nHoleId, - dDepth)
EgtSetColor( nHoleId, EgtStdColor( 'GRAY'))
EgtSetInfo( nHoleId, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.HOLE)
-- porto la lavorazione in globale
EgtTransform( nHoleId, frHdw)
-- aggiornamento del solido
if s_bCalcSolid then
UpdateSolidWithProcessingCrv( nHoleId, nMainExtrusionId, nSolidLayerId)
end
end
end
end
---------------------------------------------------------------------
-- funzione che aggiunge l'hardware
local function AddHardwareForSash( nFrameId, nReturnMode, OutputKitList, OutputPositionList, OutputOptionList)
-- cerco ed indicizzo ante del serramento
local SashList = {}
SearchSash( nFrameId, SashList)
-- ordino per X e Y
local function compareXY(a,b)
if abs( a.ptCenter:getX() - b.ptCenter:getX()) < GEO.EPS_SMALL then
return a.ptCenter:getY() < b.ptCenter:getY()
else
return a.ptCenter:getX() < b.ptCenter:getX()
end
end
table.sort( SashList, compareXY)
-- correggo nomi Frame del telaio in base all'ordinamento delle ante
for nIndex = 1, #SashList do
for nFrameIndex = 1, #SashList[nIndex].Frame do
local nFrameId = SashList[nIndex].Frame[nFrameIndex]
local sName = EgtGetName( nFrameId)
EgtSetName( nFrameId, nIndex .. '.' .. sName)
end
end
-- recupero preferito della ferramenta
local nFavourite = EgtGetInfo( nFrameId, WIN_HDW_FAVOURITE)
if not nFavourite or nFavourite == WIN_HDW_NULL then
EgtOutLog('Warning! No hardware favourite set!')
return
end
local sHandle = EgtGetInfo( nFrameId, WIN_HDW_HANDLE)
if not sHandle then
EgtOutLog('Warning! No hardware handle set!')
return
end
local sText = 'S_NAME=' .. nFavourite .. '\n' ..
'RECORDID=15A' .. '\n'
-- recupero il tipo di apertura
local nOpeningType = WIN_OPENING_TYPES.NULL
if #SashList > 0 then
nOpeningType = EgtGetInfo( SashList[1].nAreaId, WIN_OPENING_TYPE, 'i')
end
-- recupero se scorrevole
local nFrameAreaId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*')
local bSlide = EgtGetInfo( nFrameAreaId, WIN_SLIDE_WINDOW, 'b') or false
if bSlide then
-- le dimensioni per alzante scorrevole sono quelle del telaio
local nOutlineLayId = EgtGetFirstNameInGroup( nFrameId, WIN_AREAOUTLINE)
local nBottomId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_BOTTOM)
local dMet = EgtCurveLength( nBottomId)
local nLeftId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_LEFT)
local dHet = EgtCurveLength( nLeftId)
sText = sText .. 'MET=' .. tostring( dMet) .. '\n'
sText = sText .. 'HET=' .. tostring( dHet) .. '\n'
else
if #SashList >= 1 and abs( SashList[1].LHeight - SashList[1].RHeight) < GEO.EPS_SMALL then
sText = sText .. 'HBB=' .. tostring( SashList[1].LHeight) .. '\n'
else
for nSashIndex = 1, #SashList do
if nSashIndex == 1 then
sText = sText .. 'HBB_sx=' .. tostring( SashList[nSashIndex].LHeight) .. '\n'
else
sText = sText .. 'HBB_' .. tostring( nSashIndex - 1) .. 'B=' .. tostring( SashList[nSashIndex].LHeight) .. '\n'
end
if nSashIndex == #SashList then
sText = sText .. 'HBB_dx=' .. tostring( SashList[nSashIndex].RHeight) .. '\n'
else
sText = sText .. 'HBB_' .. tostring( nSashIndex) .. '=' .. tostring( SashList[nSashIndex].RHeight) .. '\n'
end
end
end
if #SashList == 1 then
sText = sText .. 'LBB=' .. tostring( SashList[1].BWidth) .. '\n'
if SashList[1].BCArrow then
sText = sText .. 'FRECCIA_1=' .. tostring( SashList[1].BCArrow) .. '\n'
end
else
for nSashIndex = 1, #SashList do
sText = sText .. 'LBB' .. nSashIndex .. '=' .. tostring( SashList[nSashIndex].BWidth) .. '\n'
if SashList[nSashIndex].BCArrow then
sText = sText .. 'FRECCIA_' .. nSashIndex .. '=' .. tostring( SashList[nSashIndex].BCArrow) .. '\n'
end
end
end
end
sText = sText .. 'FINESTRAPORTAFINESTRA=Finestra' .. '\n' ..
'Q=1' .. '\n'
-- opzione manoserramento ( non per vasistas altrimenti sovrascrive l'opzione)
if nOpeningType ~= WIN_OPENING_TYPES.TILTONLY_TOP then
sText = sText .. 'MANOSERRAMENTO=' .. sHandle .. '\n'
end
local vOptions = EgtGetInfo( nFrameId, WIN_HDW_OPTIONS, 'vs') or {}
for i = 1, #vOptions do
sText = sText .. vOptions[i] .. '\n'
end
-- Canali
local QuestionChannel = "EgwHardwareQuestion"
local AnswerChannel = "EgwHardwareAnswer" .. os.time()
local Question = { nThreadIndex = 0,
nId = 2,
ExecEnvironment = 1,
Args = { UID = 0,
OutputChannel = AnswerChannel,
Mode = 3,
SubMode = 2,
Manufacturer = 1,
ReturnMode = nReturnMode,
Input = sText}}
local JsonQuestion = JSON:encode( Question)
local bOk = EgtRedisAsyncPublish( s_nRedisConnectionId, QuestionChannel, JsonQuestion)
local AnswerArgs
if bOk then
-- EgtOutLog( 'Messaggio Redis pubblicato:' .. QuestionChannel .. ' ' .. JsonQuestion)
EgtOutLog( 'Messaggio Redis pubblicato')
local bOk, Answer = EgtRedisAsyncSubscribeOneMessage( s_nRedisConnectionId, AnswerChannel, 5000)
if bOk then
-- EgtOutLog( 'Risposta Redis ricevuta:' .. Answer)
EgtOutLog( 'Risposta Redis ricevuta')
local JsonAnswer = JSON:decode( Answer)
AnswerArgs = JsonAnswer['Args']
AnswerArgs.OutputChannel = nil
else
EgtOutLog( 'Errore! Risposta dal canale calcolo hardware Agb non arrivata!')
return
end
else
EgtOutLog( 'Errore! Pubblicazione sul canale calcolo hardware Agb fallita!')
return
end
if ( nReturnMode & WIN_HDW_RETURNMODE.HARDWARELIST) ~= 0 then
local tHardware = JSON:decode( AnswerArgs.HardwareList)
table.insert( OutputKitList, tHardware)
end
if ( nReturnMode & WIN_HDW_RETURNMODE.POSITIONLIST) ~= 0 then
local tPosition = JSON:decode( AnswerArgs.PositionList)
table.insert( OutputPositionList, tPosition)
end
if ( nReturnMode & WIN_HDW_RETURNMODE.MACHININGLIST) ~= 0 then
local tMachining = JSON:decode( AnswerArgs.MachiningList)
CalcHdwMachining( tMachining, SashList)
-- disegno la ferramenta
if s_bCalcSolid then
-- recupero o creo il gruppo per disegno ferramenta
local nAuxLayerId = GetAuxLayer()
for i = 1, #SashList do
DrawSashHardware( SashList[i].nAreaId, nFrameId, nAuxLayerId)
end
end
end
if ( nReturnMode & WIN_HDW_RETURNMODE.OPTIONLIST) ~= 0 then
table.insert( OutputOptionList, AnswerArgs.OptionList)
end
end
---------------------------------------------------------------------
local function AddHardwareRec( nAreaId, nReturnMode, OutputKitList, OutputPositionList, OutputOptionList)
local sHardware = EgtGetInfo( nAreaId, WIN_HDW_FAVOURITE)
if sHardware and sHardware ~= WIN_HDW_NULL then
-- se area ha un preferito definito allora devo calcolare la ferramenta sulle sue ante
return AddHardwareForSash( nAreaId, nReturnMode, OutputKitList, OutputPositionList, OutputOptionList)
else
-- verifico se ci sono sotto-aree
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
-- lancio verifica di quell'area
AddHardwareRec( nChildAreaId, nReturnMode, OutputKitList, OutputPositionList, OutputOptionList)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
end
---------------------------------------------------------------------
-- funzione che aggiunge l'hardware
function WinCalculate.AddHardware( nAreaId, bMachiningList, bHardwareList, bPositionList, bOptionList)
-- connessione a Redis
local bRedisConnect = false
if WDG and WDG.REDISID and WDG.REDISID > 0 then
-- connessione già creata dall'esterno
s_nRedisConnectionId = WDG.REDISID
elseif s_nRedisConnectionId == 0 then
-- se nessuna connessione la creo
bRedisConnect, s_nRedisConnectionId = EgtRedisAsyncConnect( 'redis.ufficio:26379, serviceName=devel, DefaultDatabase=6, keepAlive=180, connectTimeout=15000, syncTimeout=15000, asyncTimeout=15000, abortConnect=false, ssl=false, allowAdmin=true')
if not bRedisConnect then
EgtOutLog( 'Errore! Impossibile connettersi con il server Redis dal Lua!')
end
end
-- calcolo codice di ritorno, i.e. tipologie di conti da fare sulla ferramenta ( e.g calcolo lavorazioni, calcolo lista ferramenta, ...)
local nReturnMode = 0
if bMachiningList then
nReturnMode = nReturnMode + WIN_HDW_RETURNMODE.MACHININGLIST
end
if bHardwareList then
nReturnMode = nReturnMode + WIN_HDW_RETURNMODE.HARDWARELIST
end
if bPositionList then
nReturnMode = nReturnMode + WIN_HDW_RETURNMODE.POSITIONLIST
end
if bOptionList then
nReturnMode = nReturnMode + WIN_HDW_RETURNMODE.OPTIONLIST
end
local OutputKitList = {}
local OutputPositionList = {}
local OutputOptionList = {}
AddHardwareRec( nAreaId, nReturnMode, OutputKitList, OutputPositionList, OutputOptionList)
-- se la connessione è stata creata in questa funzione la chiudo
if bRedisConnect then
EgtRedisAsyncDisconnect( s_nRedisConnectionId)
s_nRedisConnectionId = 0
end
return OutputKitList, OutputPositionList, OutputOptionList
end
---------------------------------------------------------------------
-- funzione che disegna l'hardware
local function DrawHardware( nAreaId, nAuxLayerId)
-- verifico il tipo
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
-- se anta disegno la ferramenta se è stato definito un preferito
local sFavourite = EgtGetInfo( nAreaId, WIN_HDW_FAVOURITE)
if sFavourite and sFavourite ~= WIN_HDW_NULL then
DrawSashHardware( nAreaId, nAreaId, nAuxLayerId)
end
return
elseif nAreaType == WIN_AREATYPES.SPLIT then
local nSplitType = EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i') or WIN_SPLITTYPES.NULL
if nSplitType == WIN_SPLITTYPES.FRENCH then
local sHdwFavourite = EgtGetInfo( nAreaId, WIN_HDW_FAVOURITE)
if sHdwFavourite and sHdwFavourite ~= WIN_HDW_NULL then
-- disegno ferramenta per tutte le ante avendo come gruppo di riferimento delle info il parent dell'area split french
local vSashes = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
for j = 1, #vSashes do
DrawSashHardware( vSashes[j], nAreaId, nAuxLayerId)
end
end
return
else
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
-- lancio verifica di quell'area
DrawHardware( nChildAreaId, nAuxLayerId)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
else
-- verifico se ci sono sotto-aree
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
-- lancio verifica di quell'area
DrawHardware( nChildAreaId, nAuxLayerId)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
end
----------------------------------------------------------------------------------
----------------------------------- ACCESSORI ----------------------------------
----------------------------------------------------------------------------------
-- funzione che individua l'intersezione tra nOutlineId e la curva del geo indicata da sGeoRef del pezzo avente come outline nRefCrvId
local function GetTrimParamByGeo( nOutlineId, nRefCrvId, sGeoRef)
-- recupero la curva di interessa del geo
local nRefPart = EgtGetInfo( nRefCrvId, WIN_REF_PART, 'i')
local nRefGeo = EgtGetFirstNameInGroup( nRefPart, WIN_GEO)
local nGeoCrv = EgtGetFirstNameInGroup( nRefGeo, sGeoRef)
-- recupero punto di intersezione ( con eventuale estensione delle curve)
local ptInt = FindIntersectionPoint( nOutlineId, nGeoCrv, ORIG())
-- ricavo il parametro di intersezione sulla curva di outline ( senza estensione)
local dPar = EgtCurveParamAtPoint( nOutlineId, ptInt)
return dPar
end
----------------------------------------------------------------------------------
-- funzione che calcola e disegna la soglia
local function CalcThreshold( nOutlineId, nAreaId)
-- recupero il profilo della soglia
local nProfileId = GetOutlineProfileId( nOutlineId)
local dLenTot = 0
-- disegno
local nAuxGrp = GetAuxLayer()
local nStm = CreateProfileSurf( nOutlineId, nProfileId, WIN_SECTION, 0, nAuxGrp)
if nStm then
EgtSetColor( nStm, Color3d( 128, 128, 128))
EgtSetName( nStm, WIN_THRESHOLD)
dLenTot = EgtCurveLength( nOutlineId)
end
-- se slide window ci sono parti extra da estrudere in corrispondenza delle ante fisse
-- ( slide window ha una struttura di aree standard e forma rettangolare)
local bSlideWindow = EgtGetInfo( nAreaId, WIN_SLIDE_WINDOW, 'b') or false
if bSlideWindow then
-- 1) soglia extra per parte mobile
local nGuideId = EgtCopyGlob( nOutlineId, nAuxGrp)
-- taglio la curva guida con i pezzi di telaio vicini
local nPrevCrv = EgtGetLastInGroup( EgtGetParent( nOutlineId))
local dParS = GetTrimParamByGeo( nGuideId, nPrevCrv, WIN_GEO_IN)
local nNextCrv = EgtGetNext( nOutlineId)
local dParE = GetTrimParamByGeo( nGuideId, nNextCrv, WIN_GEO_IN)
EgtTrimCurveStartEndAtParam( nGuideId, dParS, dParE)
local vMovableSections = EgtGetNameInGroup( nProfileId, WIN_MOVABLE .. WIN_SECTION)
for i = 1, #vMovableSections do
local nStmExtra = CreateProfileSurfById( nGuideId, nProfileId, vMovableSections[i], 0, nAuxGrp)
EgtSetColor( nStmExtra, Color3d( 128, 128, 128))
EgtSetName( nStmExtra, WIN_MOVABLE .. WIN_SECTION)
end
dLenTot = dLenTot + #vMovableSections * EgtCurveLength( nGuideId)
EgtErase( nGuideId)
-- 2) soglia extra per le sottoante fisse
-- recupero i profili extra da estrudere
local vExtraSections = EgtGetNameInGroup( nProfileId, WIN_FIXED .. WIN_SECTION)
if #vExtraSections > 0 then
-- cerco tutte le sottoante fisse
local nSplitArea = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
local vSashAreas = EgtGetNameInGroup( nSplitArea, WIN_AREA .. '*')
for i = 1, #vSashAreas do
local nSashType = EgtGetInfo( vSashAreas[i], WIN_SASHTYPE, 'i')
if nSashType == WIN_SASHTYPES.SLIDE_FIXED then
local nGuideId = EgtCopyGlob( nOutlineId, nAuxGrp)
-- trim della guida con il geo dei pezzi vicini
local nOutlineLayerId = EgtGetFirstNameInGroup( vSashAreas[i], WIN_OUTLINE)
local nLeftCrv = EgtGetFirstNameInGroup( nOutlineLayerId, WIN_LEFT)
local dParS = GetTrimParamByGeo( nGuideId, nLeftCrv, WIN_GEO_OUT)
local nRightCrv = EgtGetFirstNameInGroup( nOutlineLayerId, WIN_RIGHT)
local dParE = GetTrimParamByGeo( nGuideId, nRightCrv, WIN_GEO_OUT)
EgtTrimCurveStartEndAtParam( nGuideId, dParS, dParE)
for j = 1, #vExtraSections do
local nStmExtra = CreateProfileSurfById( nGuideId, nProfileId, vExtraSections[j], 0, nAuxGrp)
EgtSetColor( nStmExtra, Color3d( 128, 128, 128))
EgtSetName( nStmExtra, WIN_FIXED .. WIN_THRESHOLD)
end
-- aggiorno lunghezza ( TODO da gestire separatamente con i tipi di soglia)
dLenTot = dLenTot + #vExtraSections * EgtCurveLength( nGuideId)
EgtErase( nGuideId)
end
end
end
end
-- salvo info lunghezza
EgtSetInfo( nAreaId, WIN_THRESHOLD_LEN, dLenTot)
end
---------------------------------------------------------------------
-- funzione che calcola e disegna il gocciolatoio
local function CalcWaterdrip( nPartId, nOutlineId, nAreaId, bDraw)
-- verifico presenza gocciolatoio
local nProfileLayId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLayId, WIN_PRF_MAIN)
local nWaterdripId = EgtGetFirstNameInGroup( nProfileId, WIN_WATERDRIP)
if not nWaterdripId then
return
end
local dLenTot = 0
-- recupero il gruppo per il disegno dei solidi
local nSolidLayId
if bDraw and s_bCalcSolid then
nSolidLayId = GetAuxLayer()
end
local vParams = {}
-- calcolo i limiti del gocciolatoio in base ai pezzi vicini del telaio
local vPrevCrvs = EgtGetInfo( nOutlineId, WIN_PREV_OUTLINES, 'vi')
local dParS = GetTrimParamByGeo( nOutlineId, vPrevCrvs[1], WIN_GEO_IN)
table.insert( vParams, dParS)
local vNextCrvs = EgtGetInfo( nOutlineId, WIN_NEXT_OUTLINES, 'vi')
local dParE = GetTrimParamByGeo( nOutlineId, vNextCrvs[1], WIN_GEO_IN)
table.insert( vParams, dParE)
-- calcolo eventuali interruzioni nel gocciolatoio per la presenza di montanti
local vSplits = {}
local nBottomRail = EgtGetInfo( nOutlineId, WIN_REF_BOTTOMRAIL_PART, 'i')
if not nBottomRail then -- se ha bottomrail gli split non causano interruzioni nel gocciolatoio
local vStack = { nAreaId}
local i = 1
while vStack[i] do
local nAreaType = EgtGetInfo( vStack[i], WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SPLIT then
local nSplitType = EgtGetInfo( vStack[i], WIN_SPLITTYPE, 'i')
if nSplitType ~= WIN_SPLITTYPES.FRENCH then
local nSplitLayerId = EgtGetFirstNameInGroup( vStack[i], WIN_SPLIT)
local vCurrSplits = EgtGetAllInGroup( nSplitLayerId)
for j = 1, #vCurrSplits do
-- verifico se lo split poggia sulla curva bottom
local dDist1 = EgtPointCurveDist( EgtSP( vCurrSplits[j]), nOutlineId)
local dDist2 = EgtPointCurveDist( EgtEP( vCurrSplits[j]), nOutlineId)
if dDist1 < GEO.EPS_SMALL or dDist2 < GEO.EPS_SMALL then
-- recupero l'intervallo di interruzione dello split sull'outline
local dParIn = GetTrimParamByGeo( nOutlineId, vCurrSplits[j], WIN_GEO_IN)
table.insert( vParams, dParIn)
local dParOut = GetTrimParamByGeo( nOutlineId, vCurrSplits[j], WIN_GEO_OUT)
table.insert( vParams, dParOut)
end
end
end
end
-- se non è anta ( che interrompe la cascata di pezzi relativi al telaio) salvo le sottaree per analizzarle
if nAreaType ~= WIN_AREATYPES.SASH then
local vChildren = EgtGetNameInGroup( vStack[i], WIN_AREA .. '*') or {}
vStack = EgtJoinTables( vStack, vChildren)
end
-- passo all'area successiva
i = i + 1
end
end
-- riordino i parametri ed elimino quelli coincidenti
table.sort( vParams)
local vNewParams = { vParams[1]}
for j = 2, #vParams do
if abs( vParams[j] - vNewParams[#vNewParams]) > GEO.EPS_ZERO then
table.insert( vNewParams, vParams[j])
end
end
vParams = vNewParams
for j = 1, #vParams, 2 do
-- ricavo la guida per il tratto di gocciolatoio
local nGuideId = EgtCopyParamRange( nOutlineId, vParams[j], vParams[j+1], nSolidLayId)
dLenTot = dLenTot + EgtCurveLength( nGuideId)
if bDraw and s_bCalcSolid then
-- estrudo la superficie
local nStm = CreateProfileSurf( nGuideId, nProfileId, WIN_WATERDRIP, 0, nSolidLayId)
EgtSetColor( nStm, Color3d( 128, 128, 128))
EgtSetName( nStm, WIN_WATERDRIP)
end
EgtErase( nGuideId)
end
-- salvo la lunghezza del gocciolatoio
EgtSetInfo( nAreaId, WIN_WATERDRIP_LEN, dLenTot)
end
---------------------------------------------------------------------
-- funzione che calcola e disegna le guarnizioni
local function CalcGaskets( nAreaId, bDraw)
local nOutlineLayId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOrigOutlines = EgtGetAllInGroup( nOutlineLayId)
local dLenTot = 0
-- recupero dati dei pezzi che serviranno nei conti e i veri outlines da considerare
local tParts = {}
local vOutlines = {}
for i = 1, #vOrigOutlines do
local bThreshold = EgtGetName( vOrigOutlines[i]) == WIN_BOTTOM and EgtGetInfo( vOrigOutlines[i], WIN_THRESHOLD, 'b')
if bThreshold then
-- gestione speciale per soglia che non ha pezzo associato
local nMainProfileId = GetOutlineProfileId( vOrigOutlines[i])
tParts[i] = { nProfileId = nMainProfileId, frProfile = nil}
vOutlines[i] = vOrigOutlines[i]
else
local nPartId = FindAssociatedPart( vOrigOutlines[i], false)
local nProfileLayId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayId, WIN_PRF_MAIN)
local nFrameId = EgtGetFirstNameInGroup( nMainProfileId, WIN_SECTIONFRAME)
local frProfile = EgtFR( nFrameId, GDB_ID.ROOT)
tParts[i] = { nProfileId = nMainProfileId, frProfile = frProfile}
vOutlines[i] = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i')
end
end
-- gruppo temporaneo per i conti
local nGrp = EgtGroup( nAreaId)
-- cerco tutte le possibili guarnizioni
for i = 1, 3 do
-- nome della guarnizione corrente
local sGasket = WIN_GASKET .. tostring( i)
local vCrvs = {}
for i = 1, #vOutlines do
local nCrv = EgtCopyGlob( vOutlines[i], nGrp)
table.insert( vCrvs, nCrv)
-- calcolo offset da applicare alla curva
local dOffs
local vGasketIds = EgtGetNameInGroup( tParts[i].nProfileId, sGasket .. '*')
if #vGasketIds == 1 then
-- se guarnizione recupero offset dalla sua dimensione
local b3Box = EgtGetBBoxRef( vGasketIds[1], GDB_BB.STANDARD, tParts[i].frProfile)
dOffs = b3Box:getMax():getX()
tParts[i].sGasket = sGasket
elseif #vGasketIds > 1 then
-- se ho più guarnizioni devo identificare quella dal lato corretto ( caso di split)
local nCrvRef = EgtIf( i == 1, vOrigOutlines[2], vOrigOutlines[i-1])
local _, _, nSide = EgtPointCurveDistSide( EgtMP( nCrvRef), nCrv, Z_AX())
if nSide == 1 then
tParts[i].sGasket = sGasket .. '_1'
local nGasketId = EgtGetFirstNameInGroup( tParts[i].nProfileId, tParts[i].sGasket)
local b3Box = EgtGetBBoxRef( nGasketId, GDB_BB.STANDARD, tParts[i].frProfile)
dOffs = b3Box:getMin():getX()
else
tParts[i].sGasket = sGasket .. '_2'
local nGasketId = EgtGetFirstNameInGroup( tParts[i].nProfileId, tParts[i].sGasket)
local b3Box = EgtGetBBoxRef( nGasketId, GDB_BB.STANDARD, tParts[i].frProfile)
dOffs = b3Box:getMax():getX()
end
else
-- se non ha guarnizione è curva di trim ( quindi deve avere info)
dOffs = EgtGetInfo( tParts[i].nProfileId, WIN_TRIM .. sGasket, 'd')
if not dOffs then
-- se non ha info di trim significa che devo passare alla guarnizione successiva
vCrvs = {}
break
end
dOffs = - dOffs
tParts[i].sGasket = nil
end
-- offset
EgtOffsetCurve( nCrv, dOffs)
end
if #vCrvs > 0 then
-- taglio le curve
TrimOrderedCurves( vCrvs, true)
-- aggiorno lunghezza
for i = 1, #vCrvs do
if tParts[i].sGasket then -- devo ignorare le curve di trim
dLenTot = dLenTot + EgtCurveLength( vCrvs[i])
end
end
-- disegno
if bDraw and s_bCalcSolid then
-- recupero il gruppo per il disegno dei solidi
local nSolidLayerId = GetAuxLayer()
for i = 1, #vCrvs do
if tParts[i].sGasket then
-- estrusione principale della giunzione
local nGasketStm = CreateProfileSurf( vOutlines[i], tParts[i].nProfileId, tParts[i].sGasket, 100, nSolidLayerId)
EgtSetColor( nGasketStm, Color3d( 128, 128, 128))
EgtSetName( nGasketStm, sGasket)
-- trim start
local nPrev = EgtIf( i == 1, #vCrvs, i - 1)
local nGuideId
if not tParts[nPrev].sGasket then
-- se precedente è curva di trim la uso direttamente
nGuideId = EgtCopyGlob( vCrvs[nPrev], nSolidLayerId)
EgtInvertCurve( nGuideId)
else
-- taglio lungo la bisettrice
local vtDir = 0.5 * ( EgtSV( vCrvs[i]) - EgtEV( vCrvs[nPrev]))
if vtDir:isSmall() then
vtDir = EgtSV( vCrvs[i])
vtDir:rotate( Z_AX(), 90)
end
nGuideId = EgtLinePVL( nSolidLayerId, EgtSP( vCrvs[i]), vtDir, 200)
EgtExtendCurveStartByLen( nGuideId, 100)
end
local nTrimStart = EgtSurfTmByExtrusion( nSolidLayerId, nGuideId, - 200 * Z_AX())
EgtSurfTmIntersect( nGasketStm, nTrimStart)
EgtErase( { nGuideId, nTrimStart})
-- trim end
local nNext = EgtIf( i == #vCrvs, 1, i + 1)
if not tParts[nNext].sGasket then
nGuideId = EgtCopyGlob( vCrvs[nNext], nSolidLayerId)
else
local vtDir = 0.5 * ( EgtSV( vCrvs[nNext]) - EgtEV( vCrvs[i]))
if vtDir:isSmall() then
vtDir = EgtSV( vCrvs[nNext])
vtDir:rotate( Z_AX(), 90)
end
nGuideId = EgtLinePVL( nSolidLayerId, EgtEP( vCrvs[i]), vtDir, 200)
EgtExtendCurveStartByLen( nGuideId, 100)
end
local nTrimEnd = EgtSurfTmByExtrusion( nSolidLayerId, nGuideId, - 200 * Z_AX())
EgtInvertSurf( nTrimEnd)
EgtSurfTmIntersect( nGasketStm, nTrimEnd)
EgtErase( { nGuideId, nTrimEnd})
end
end
end
end
end
-- aggiorno valore lunghezza
EgtSetInfo( nAreaId, WIN_GASKET_LEN, dLenTot)
EgtErase( nGrp)
end
---------------------------------------------------------------------
function WinCalculate.AddAccessories( nAreaId, bDraw)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.FRAME then
local nOutlineLayId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
-- accessori del pezzo inferiore: soglia e gocciolatoio
local nBottomId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_BOTTOM)
local bThreshold = EgtGetInfo( nBottomId, WIN_THRESHOLD, 'b') or false
if bThreshold then
-- soglia
CalcThreshold( nBottomId, nAreaId)
else
-- gocciolatoio
local nPartId = EgtGetInfo( nBottomId, WIN_REF_PART, 'i')
CalcWaterdrip( nPartId, nBottomId, nAreaId, bDraw)
end
-- guarnizioni se definisce direttamente anta
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*') or GDB_ID.NULL
local nChildType = EgtGetInfo( nChildAreaId, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL
if nChildType == WIN_AREATYPES.SASH then
CalcGaskets( nAreaId, bDraw)
end
-- TODO guarnizioni per gocciolatoio
elseif nAreaType == WIN_AREATYPES.SASH then
-- guarnizioni
CalcGaskets( nAreaId, bDraw)
elseif nAreaType == WIN_AREATYPES.SPLIT then
-- guarnizioni se è french split
local nSplitId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT)
local nSplitType = EgtGetInfo( nSplitId, WIN_SPLITTYPE, 'i') or WIN_SPLITTYPES.NULL
if nSplitType == WIN_SPLITTYPES.FRENCH then
CalcGaskets( nAreaId, bDraw)
end
elseif nAreaType == WIN_AREATYPES.NULL then
-- guarnizioni se ha come sottoarea un'anta
local nChildArea = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*') or GDB_ID.NULL
local nChildType = EgtGetInfo( nChildArea, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL
if nChildType == WIN_AREATYPES.SASH then
CalcGaskets( nAreaId, bDraw)
end
end
-- calcolo accessori per sotto-aree
local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*')
while nChildAreaId do
WinCalculate.AddAccessories( nChildAreaId, bDraw)
nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*')
end
end
----------------------------------------------------------------------------------
--------------------------------- PREVIEW ----------------------------------------
----------------------------------------------------------------------------------
local function CalcBottomRailPreview( nPreviewGrp, nOutlineId, nBottomRail, nGeoGrp)
-- costruisco box complessivo degli zoccoli
local vCrvs = {}
-- la curva out corrisponde al geo in del pezzo bottom
local nPartGeoIn = EgtGetFirstNameInGroup( nGeoGrp, WIN_GEO_IN)
vCrvs[1] = EgtCopyGlob( nPartGeoIn, nPreviewGrp)
EgtInvertCurve( vCrvs[1])
-- la curva right corrisponde al geo in del pezzo adiacente
local vNextOutlines = EgtGetInfo( nOutlineId, WIN_NEXT_OUTLINES, 'vi')
local nNextPart = FindAssociatedPart( abs( vNextOutlines[1]), false)
local nNextGeo = EgtGetFirstNameInGroup( nNextPart, WIN_GEO)
local nNextIn = EgtGetFirstNameInGroup( nNextGeo, WIN_GEO_IN)
vCrvs[2] = EgtCopyGlob( nNextIn, nPreviewGrp)
EgtInvertCurve( vCrvs[2])
-- la curva in corrisponde al geo in dell'ultimo bottomrail
local vBottomRails = EgtGetInfo( nOutlineId, WIN_REF_BOTTOMRAIL_PART, 'vi')
local nBottomRailPart = vBottomRails[#vBottomRails]
local nGeoLayer = EgtGetFirstNameInGroup( nBottomRailPart, WIN_GEO)
local nGeoIn = EgtGetFirstNameInGroup( nGeoLayer, WIN_GEO_IN)
vCrvs[3] = EgtCopyGlob( nGeoIn, nPreviewGrp)
-- la curva left corrisponde al geo in del pezzo adiacente
local vPrevOutlines = EgtGetInfo( nOutlineId, WIN_PREV_OUTLINES, 'vi')
local nPrevPart = FindAssociatedPart( abs( vPrevOutlines[1]), false)
local nPrevGeo = EgtGetFirstNameInGroup( nPrevPart, WIN_GEO)
local nPrevIn = EgtGetFirstNameInGroup( nPrevGeo, WIN_GEO_IN)
vCrvs[4] = EgtCopyGlob( nPrevIn, nPreviewGrp)
EgtInvertCurve( vCrvs[4])
-- creo la regione e ne estraggo il bordo
local nAreaId = CalcIntersectionRegion( vCrvs, nPreviewGrp)
EgtSetColor( nAreaId, Color3d( 251, 128, 4))
local nCrvId = EgtExtractSurfFrChunkLoops( nAreaId, 0, nPreviewGrp)
EgtSetColor( nCrvId, EgtStdColor( 'BLACK'))
EgtModifyCurveThickness( nCrvId, 0)
-- creo linee di divisione tra gli zoccoli
if nBottomRail > 1 then
local b3Surf = EgtGetBBoxGlob( nAreaId, GDB_BB.STANDARD)
local dLen = b3Surf:getDimX()
local dH = b3Surf:getDimY()
local vBottomRailDims = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL .. WIN_PART_DIM, 'vd')
local dTotDim = 0
for i = 1, #vBottomRailDims do
dTotDim = dTotDim + vBottomRailDims[i]
end
local dPos = 0
for i = 1, nBottomRail - 1 do
dPos = dPos + vBottomRailDims[i] * dH / dTotDim
local pt = b3Surf:getMin() + dPos * Y_AX()
local nCrvId = EgtLinePVL( nPreviewGrp, pt, X_AX(), dLen)
EgtSetColor( nCrvId, EgtStdColor( 'BLACK'))
end
end
EgtErase( vCrvs)
end
----------------------------------------------------------------------------------
local function CalcPartPreview( nPartId, nPreviewGrp)
local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i')
local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO)
-- recupero il tipo di giunzioni
local vStartJoints = EgtGetInfo( nOutlineId, WIN_STARTJOINT, 'vi')
local vEndJoints = EgtGetInfo( nOutlineId, WIN_ENDJOINT, 'vi')
local nAreaId
-- se pezzo semplice senza giunzioni short come preview posso considerare direttamente la regione del geo
if #vStartJoints == 1 and #vEndJoints == 1 and vStartJoints[1] ~= WIN_PART_JNT.SHORT and vEndJoints[1] ~= WIN_PART_JNT.SHORT then
local nGeoSurf = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_SURF)
nAreaId = EgtCopyGlob( nGeoSurf, nPreviewGrp)
EgtSetStatus( nAreaId, GDB_ST.ON)
-- altrimenti devo calcolare le curve che delimitano la regione ( in modo simile a quanto fatto in CreateGeoCurves)
else
local nGrpTmp = EgtGroup( nPreviewGrp)
local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE)
local nProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN)
local b3Profile = GetProfileLocalBox( nProfileId)
-- a) curva out : ricalcolo curva del geo ( non posso utilizzare direttamente quella del geo perchè non deve avere estensioni)
local nOutId = EgtCopy( nOutlineId, nGrpTmp)
EgtOffsetCurve( nOutId, b3Profile:getMax():getX())
local nGeoOut = EgtGetFirstNameInGroup( nGeoLayerId, WIN_OUT)
CopyInfo( nOutId, nGeoOut, WIN_TANG_START, false)
CopyInfo( nOutId, nGeoOut, WIN_TANG_END, false)
-- b) curva in
local nInId = EgtCopy( nOutlineId, nGrpTmp)
EgtOffsetCurve( nInId, b3Profile:getMin():getX())
EgtInvertCurve( nInId)
local nGeoIn = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_IN)
CopyInfo( nInId, nGeoIn, WIN_TANG_START, false)
CopyInfo( nInId, nGeoIn, WIN_TANG_END, false)
-- c) curve left
local vGeoLeft = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_LEFT)
local vPrevOutlineId = EgtGetInfo( nOutlineId, WIN_PREV_OUTLINES, 'vi')
local vPrevProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_START)
for i = 1, #vPrevOutlineId do
if vStartJoints[i] == WIN_PART_JNT.ANGLED then
-- recupero la bisettrice dal geo
for k = 1, #vGeoLeft do
if EgtGetInfo( vGeoLeft[k], WIN_REF_OUTLINE, 'i') == vPrevOutlineId[i] and not EgtExistsInfo( vGeoLeft[k], WIN_SEMI_PROFILE) then
EgtCopyGlob( vGeoLeft[k], nGrpTmp)
end
end
-- curva aux : considero l'out del pezzo precedente
local nCrvId = EgtCopyGlob( abs( vPrevOutlineId[1]), nGrpTmp)
local b3Profile = GetProfileLocalBox( vPrevProfileId[1])
EgtOffsetCurve( nCrvId, b3Profile:getMax():getX())
else
-- se è pezzo del telaio contro soglia lo tratto come se fosse full
if EgtGetName( nOutlineId) ~= WIN_SPLIT and EgtGetInfo( abs( vPrevOutlineId[i]), WIN_THRESHOLD, 'b') then
vStartJoints[i] = WIN_PART_JNT.FULL
end
if vStartJoints[i] == WIN_PART_JNT.SHORT then
local b3Profile = GetProfileLocalBox( vPrevProfileId[i])
local nCrvId = EgtCopy( abs( vPrevOutlineId[i]), nGrpTmp)
local dRailDelta = EgtGetInfo( vPrevProfileId[i], WIN_RAILOFFS, 'd') or 0
local dOffs = b3Profile:getMin():getX() - dRailDelta
if vPrevOutlineId[i] < 0 then
EgtInvertCurve( nCrvId)
dOffs = - b3Profile:getMax():getX()
end
EgtOffsetCurve( nCrvId, dOffs)
-- per un risultato graficamente migliore se il pezzo precedente è in tangenza con il vicino, impongo estensione in tangenza, altrimenti considero quella
-- calcolata dal geo
local nStartType = EgtGetInfo( abs( vPrevOutlineId[i]), WIN_STARTJOINT, 'i')
if nStartType == WIN_PART_JNT.ANGLED then
EgtSetInfo( nCrvId, WIN_TANG_START, true)
else
CopyInfo( nCrvId, vGeoLeft[i], WIN_TANG_START, false)
end
local nEndType = EgtGetInfo( abs( vPrevOutlineId[i]), WIN_ENDJOINT, 'i')
if nEndType == WIN_PART_JNT.ANGLED then
EgtSetInfo( nCrvId, WIN_TANG_END, true)
else
CopyInfo( nCrvId, vGeoLeft[i], WIN_TANG_END, false)
end
else -- full
-- considero l'out del pezzo precedente
local nCrvId = EgtCopy( abs( vPrevOutlineId[i]), nGrpTmp)
local b3Profile = GetProfileLocalBox( vPrevProfileId[i])
local dOffs = b3Profile:getMax():getX()
if vPrevOutlineId[i] < 0 then
EgtInvertCurve( nCrvId)
dOffs = - b3Profile:getMin():getX()
end
EgtOffsetCurve( nCrvId, dOffs)
CopyInfo( nCrvId, vGeoLeft[i], WIN_TANG_START, false)
CopyInfo( nCrvId, vGeoLeft[i], WIN_TANG_END, false)
end
end
end
-- d) curve right
local vGeoRight = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_RIGHT)
local vNextOutlineId = EgtGetInfo( nOutlineId, WIN_NEXT_OUTLINES, 'vi')
local vNextProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_END)
for i = 1, #vNextOutlineId do
if vEndJoints[i] == WIN_PART_JNT.ANGLED then
-- recupero la bisettrice dal geo
local nCrvId
for k = 1, #vGeoRight do
if EgtGetInfo( vGeoRight[k], WIN_REF_OUTLINE, 'i') == vNextOutlineId[i] and not EgtExistsInfo( vGeoRight[k], WIN_SEMI_PROFILE) then
nCrvId = EgtCopyGlob( vGeoRight[k], nGrpTmp)
EgtRelocateGlob( nCrvId, nInId, GDB_IN.BEFORE)
end
end
-- curva aux
local nAuxCrv = EgtCopyGlob( abs( vNextOutlineId[i]), nGrpTmp)
local b3Profile = GetProfileLocalBox( vNextProfileId[i])
EgtOffsetCurve( nAuxCrv, b3Profile:getMax():getX())
EgtRelocateGlob( nAuxCrv, nInId, GDB_IN.BEFORE)
else
local nCrvId
-- se è pezzo del telaio contro soglia lo tratto come se fosse full
if EgtGetName( nOutlineId) ~= WIN_SPLIT and EgtGetInfo( abs( vNextOutlineId[i]), WIN_THRESHOLD, 'b') then
vEndJoints[i] = WIN_PART_JNT.FULL
end
if vEndJoints[i] == WIN_PART_JNT.SHORT then
nCrvId = EgtCopyGlob( abs( vNextOutlineId[i]), nGrpTmp)
local b3Profile = GetProfileLocalBox( vNextProfileId[i])
local dRailDelta = EgtGetInfo( vNextProfileId[i], WIN_RAILOFFS, 'd') or 0
local dOffs = b3Profile:getMin():getX() - dRailDelta
if vNextOutlineId[i] < 0 then
EgtInvertCurve( nCrvId)
dOffs = - b3Profile:getMax():getX()
end
EgtOffsetCurve( nCrvId, dOffs)
local nStartType = EgtGetInfo( abs( vNextOutlineId[i]), WIN_STARTJOINT, 'i')
if nStartType == WIN_PART_JNT.ANGLED then
EgtSetInfo( nCrvId, WIN_TANG_START, true)
else
CopyInfo( nCrvId, vGeoRight[i], WIN_TANG_START, false)
end
local nEndType = EgtGetInfo( abs( vNextOutlineId[i]), WIN_ENDJOINT, 'i')
if nEndType == WIN_PART_JNT.ANGLED then
EgtSetInfo( nCrvId, WIN_TANG_END, true)
else
CopyInfo( nCrvId, vGeoRight[i], WIN_TANG_END, false)
end
else -- full
local b3Profile = GetProfileLocalBox( vNextProfileId[i])
nCrvId = EgtCopyGlob( abs( vNextOutlineId[i]), nGrpTmp)
local dOffs = b3Profile:getMax():getX()
if vNextOutlineId[i] < 0 then
EgtInvertCurve( nCrvId)
dOffs = - b3Profile:getMin():getX()
end
EgtOffsetCurve( nCrvId, dOffs)
CopyInfo( nCrvId, vGeoRight[i], WIN_TANG_START, false)
CopyInfo( nCrvId, vGeoRight[i], WIN_TANG_END, false)
end
EgtRelocateGlob( nCrvId, nInId, GDB_IN.BEFORE)
end
end
local vIds = EgtGetAllInGroup( nGrpTmp)
nAreaId = CalcGeoRegion( vIds, nPreviewGrp)
EgtErase( nGrpTmp)
end
-- se pezzo scompare
if not nAreaId then
return
end
-- sistemo la regione
local nParentAreaId = EgtGetParent( EgtGetParent( nOutlineId))
local nAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
-- se anta traslazione per gestire meglio i casi di telaio e ante allineati
EgtMove( nAreaId, Vector3d( 0, 0, - 0.1))
-- se anta con parte ricevente traslazione per evitare sovrapposizione con parte battente
local nSashType = EgtGetInfo( nParentAreaId, WIN_SASHTYPE, 'i')
if nSashType == WIN_SASHTYPES.INACTIVE or nSashType == WIN_SASHTYPES.INACTIVE_IN or nSashType == WIN_SASHTYPES.ACTIVE_OUT then
EgtMove( nAreaId, Vector3d( 0, 0, - 0.1))
elseif nSashType == WIN_SASHTYPES.INACTIVE_OUT then
EgtMove( nAreaId, Vector3d( 0, 0, - 0.2))
end
elseif nAreaType == WIN_AREATYPES.SPLIT then
-- se inglesina esterna la abbasso per averla sotto il vetro
if EgtGetInfo( nOutlineId, WIN_MUNTINFILL_SIDE, 'i') == WIN_MUNTINFILL_SIDES.OUT then
EgtMove( nAreaId, Vector3d( 0, 0, - 1000))
end
end
EgtSetColor( nAreaId, Color3d( 251, 128, 4))
-- estraggo il contorno
local nCompoId = EgtExtractSurfFrChunkLoops( nAreaId, 0, nPreviewGrp)
EgtSetColor( nCompoId, EgtStdColor( 'BLACK'))
-- se bottom aggiungo anche eventuale preview del bottomrail
if EgtGetName( nOutlineId) == WIN_BOTTOM then
local nBottomRail = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL, 'i') or 0
if nBottomRail > 0 then
CalcBottomRailPreview( nPreviewGrp, nOutlineId, nBottomRail, nGeoLayerId)
end
end
end
----------------------------------------------------------------------------------
local function CalcFillPreview( nPartId, nPreviewGrp)
-- creo bordo a partire dall'outline
local nAreaId = EgtGetInfo( nPartId, WIN_AREA, 'i')
local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local vOutlineList = EgtGetAllInGroup( nOutlineLayerId)
local nCompoOutlineId = EgtCurveCompoByChain( nPreviewGrp, vOutlineList, EgtSP( vOutlineList[1]), false)
-- creo area
local nSurfId = EgtSurfFlatRegion( nPreviewGrp, {nCompoOutlineId})
EgtSetColor( nSurfId, EgtGetColor( nPartId))
EgtErase( nCompoOutlineId)
end
----------------------------------------------------------------------------------
local function CalcThresholdPreview( nAreaId, nPreviewGrp)
-- recupero il bottom del telaio
local nOutlineGrpId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE)
local nBottomId = EgtGetFirstNameInGroup( nOutlineGrpId, WIN_BOTTOM)
local nProfileId = GetOutlineProfileId( nBottomId, false)
local b3Profile = GetProfileLocalBox( nProfileId)
-- creo il rettangolo della soglia e lo posiziono sullo sfondo
local ptOrig = EgtSP( nBottomId)
local nSurfId = EgtSurfFrRectangle( nPreviewGrp, ptOrig, ptOrig + EgtCurveLength( nBottomId) * X_AX() + b3Profile:getDimX() * Y_AX())
EgtSetColor( nSurfId, Color3d( 128, 128, 128))
EgtMove( nSurfId, - 500 * Z_AX())
local nCompoId = EgtExtractSurfFrChunkLoops( nSurfId, 0, nPreviewGrp)
EgtSetColor( nCompoId, EgtStdColor( 'BLACK'))
end
----------------------------------------------------------------------------------
local function CalcHardwarePreview( nAreaId, nPreviewGrp)
local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
-- se anta disegno la ferramenta se è definita
local sHdwFavourite = EgtGetInfo( nAreaId, WIN_HDW_FAVOURITE)
if sHdwFavourite and sHdwFavourite ~= WIN_HDW_NULL then
DrawSashHardware( nAreaId, nAreaId, nPreviewGrp, true)
end
return
elseif nAreaType == WIN_AREATYPES.SPLIT then
local nSplitType = EgtGetInfo( nAreaId, WIN_SPLITTYPE, 'i') or WIN_SPLITTYPES.NULL
if nSplitType == WIN_SPLITTYPES.FRENCH then
local sHdwFavourite = EgtGetInfo( nAreaId, WIN_HDW_FAVOURITE)
if sHdwFavourite and sHdwFavourite ~= WIN_HDW_NULL then
-- disegno ferramenta per tutte le ante avendo come gruppo di riferimento delle info il parent dell'area split french
local vSashes = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*')
for j = 1, #vSashes do
DrawSashHardware( vSashes[j], nAreaId, nPreviewGrp, true)
end
end
return
else
-- se non è split french devo controllare le sue sottoaree
local vChildrenAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*') or {}
for i = 1, #vChildrenAreas do
CalcHardwarePreview( vChildrenAreas[i], nPreviewGrp)
end
end
else
-- controllo le sue sottoaree
local vChildrenAreas = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*') or {}
for i = 1, #vChildrenAreas do
CalcHardwarePreview( vChildrenAreas[i], nPreviewGrp)
end
end
end
----------------------------------------------------------------------------------
local function CalcPreview( nFrameId)
-- creo gruppo per la preview
local nPreviewGrp = EgtGroup( GDB_ID.ROOT)
EgtSetName( nPreviewGrp, WIN_PREVIEW)
EgtSetLevel( nPreviewGrp, GDB_LV.SYSTEM)
EgtSetStatus( nPreviewGrp, GDB_ST.OFF)
-- scorro tutti i pezzi e ne realizzo la preview
local nPartId = EgtGetFirstPart()
while nPartId do
local nPartType = EgtGetInfo( nPartId, WIN_PART_TYPE, 'i') or WIN_PART_TYPES.NULL
if nPartType == WIN_PART_TYPES.FILL then
CalcFillPreview( nPartId, nPreviewGrp)
elseif nPartType == WIN_PART_TYPES.BOTTOMRAIL then
-- pezzo di bottomrail viene ignorato perchè già creato con il corrispondente pezzo bottom
else
CalcPartPreview( nPartId, nPreviewGrp)
end
nPartId = EgtGetNextPart( nPartId)
end
-- preview soglia
local nOutlineGrpId = EgtGetFirstNameInGroup( nFrameId, WIN_OUTLINE)
local nBottomId = EgtGetFirstNameInGroup( nOutlineGrpId, WIN_BOTTOM)
local bThreshold = EgtGetInfo( nBottomId, WIN_THRESHOLD, 'b') or false
if bThreshold then
CalcThresholdPreview( nFrameId, nPreviewGrp)
end
-- copio i disegni di apertura delle ante dal gruppo delle aree
local vStack = { nFrameId}
local i = 1
while i <= #vStack do
local nAreaType = EgtGetInfo( vStack[i], WIN_AREATYPE, 'i')
if nAreaType == WIN_AREATYPES.SASH then
local nOpeningGrp = EgtGetFirstNameInGroup( vStack[i], WIN_SASH_OPENING)
local vOpeningCrvs = EgtGetAllInGroup( nOpeningGrp)
for j = 1, #vOpeningCrvs do
local nId = EgtCopyGlob( vOpeningCrvs[j], nPreviewGrp)
EgtSetColor( nId, EgtStdColor( 'BLACK'))
end
else
-- aggiungo allo stack di aree da controllare le sue aree figlie
local vChildrenAreas = EgtGetNameInGroup( vStack[i], WIN_AREA .. '*') or {}
vStack = EgtJoinTables( vStack, vChildrenAreas)
end
i = i + 1
end
-- preview ferramenta
CalcHardwarePreview( nFrameId, nPreviewGrp)
end
----------------------------------------------------------------------------------
------------------------------ FUNZIONI ----------------------------------------
----------------------------------------------------------------------------------
-- funzione che crea tutti i pezzi della finestra partendo dal telaio
function WinCalculate.CreatePartFromArea( nFrameId)
s_nSashNbr = 0
-- assegno il tipo di profilo alle curve del base outline
CalculateAreaProfileType( nFrameId)
-- calcolo outline a partire dal base outline
CalculateAreaOutline( nFrameId)
SetAreaProfiles( nFrameId)
-- creo i pezzi con i profili
CreateAreaParts( nFrameId)
GetAreaPrevNextOutlines( nFrameId)
-- creo pezzi
CalculateAreaParts( nFrameId)
-- calcolo le spine
CalculateAreaDowels( nFrameId)
-- calcolo preview 2d se richiesta
if s_bCalcPreview then
CalcPreview( nFrameId)
end
end
---------------------------------------------------------------------
return WinCalculate