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