-- -- 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 require( 'EgtBase') require( 'WinConst') _G.package.loaded.JSON = nil local JSON = require( 'JSON') _G.package.loaded.XML = nil local XML = require( 'xml2lua') _G.package.loaded.XMLHandler = nil 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_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 --------------------------------------------------------------------- -- 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 = EgtGetParent( nCrv1) local dExtraLen = 10000 local nCrvA, nCrvB if EgtGetType( nCrv1) == GDB_TY.CRV_LINE and EgtGetType( nCrv2) == 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 EgtGetType( nCrv1) == GDB_TY.CRV_ARC and EgtGetType( nCrv2) == 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)) else -- 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( { nCrvA, nCrvB}) end return ptInt 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 -- costruisco le circonferenze associate agli archi verificando non ve ne siano di coincidenti local dExtraLen = 10000 local vSemiPlaneSurfs = {} 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( vSemiPlaneSurfs, nSemiPlaneId) else -- creo circonferenza corrispondente local nCircleId = EgtCopyGlob( vCrvs[i], nGrpTmp) local dAngOld = EgtArcAngCenter( vCrvs[i]) EgtModifyArcAngCenter( nCircleId, EgtIf( dAngOld > 0, 360, -360)) -- verifico se coincide con altra circonferenza già costruita local dRad = EgtArcRadius( nCircleId) local ptC = EgtCP( nCircleId) local bOverlap = false for j = 1, #tArcs do if AreSamePointApprox( tArcs[j].ptC, ptC) and abs( tArcs[j].dRad - dRad) < GEO.EPS_SMALL then bOverlap = true table.insert( tArcs[j].nArcId, vCrvs[i]) break end end if not bOverlap then table.insert( tArcs, { nCircleId = nCircleId, nArcId = {vCrvs[i]}, dRad = dRad, ptC = ptC}) end end end -- calcolo la regione definita dai semipiani for i = 2, #vSemiPlaneSurfs do EgtSurfFrIntersect( vSemiPlaneSurfs[1], vSemiPlaneSurfs[i]) EgtErase( vSemiPlaneSurfs[i]) end nSurfId = vSemiPlaneSurfs[1] -- se presenti archi, calcolo il loro contributo alla regione if #tArcs > 0 then local nCrvBorder = EgtExtractSurfFrChunkLoops( nSurfId, 0, nGrpTmp) -- riordino circonferenze 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 local nCircleId = tArcs[i].nCircleId -- limito la circonferenza alla regione local nSurfTrim = EgtSurfFlatRegion( nGrpTmp, nCrvBorder) local nCrv, nCnt = EgtTrimCurveWithRegion( nCircleId, nSurfTrim, true, false) if not nCrv then -- è errore, lo ignoro 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 EgtModifyCurveStartPoint( nCrv, EgtSP( nCrv + nCnt - 1)) EgtErase( nCrv + nCnt - 1) 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) 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 -- considero solo i tratti che poggiano sulle curve orginali for j = 1, #vArcs do local bOk = false for k = 1, #tArcs[i].nArcId do local nOrigArc = tArcs[i].nArcId[k] local dParS = EgtCurveParamAtPoint( nOrigArc, EgtSP( vArcs[j])) local dParE = EgtCurveParamAtPoint( nOrigArc, EgtEP( vArcs[j])) 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( vArcs[j], EgtSP( nOrigArc)) local dPar2 = EgtCurveParamAtPoint( vArcs[j], EgtEP( nOrigArc)) if dPar1 or dPar2 then bOk = true break end elseif dParS and abs( dParS - 1) > GEO.EPS_SMALL then bOk = true break elseif dParE and dParE > GEO.EPS_SMALL then bOk = true break end end if not bOk then EgtErase( vArcs[j]) else -- modifico il bordo con il nuovo tratto 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]) end end end end -- ricostruisco la superficie nSurfId = EgtSurfFlatRegion( nGrpTmp, nCrvBorder) end EgtRelocateGlob( nSurfId, nGrp) EgtErase( nGrpTmp) return nSurfId end --------------------------------------------------------------------- -- Gestione delle curve superflue in TrimOrderedCurves : le modalità di trattamento sono indicate da nMode e sono le seguenti -- 0/nil = curva eliminata ( caso standard) -- 1 = curva eliminata rimuovendo la corrispondenza dalle info della curva di base outline da cui deriva ( se chiamata da outline) -- 2 = curva non viene eliminata ma viene settata info che indica di ignorarla ( se chiamata dal geo) local function AdjustExtraCurvesForTrim( nCrvId, nSurfId, nMode) if not nMode or nMode == 0 then EgtErase( nCrvId) elseif nMode == 1 then -- rimuovo la info che riconduce alla curva che sto per eliminare dalla curva corrispondente del base outline local nBaseOutline = EgtGetInfo( nCrvId, WIN_COPY, 'i') EgtRemoveInfo( nBaseOutline, WIN_COPY) -- elimino la curva EgtErase( nCrvId) elseif nMode == 2 then -- se la curva è fuori dalla regione non va eliminata ma viene settata info che indica di ignorarla. Se è on o in allora il suo contributo è lo stesso di un'altra -- curva di bordo quindi può essere eliminata local nTestCrv = EgtCopyGlob( nCrvId, EgtGetParent( nSurfId)) local nTmp, nCnt = EgtTrimCurveWithRegion( nTestCrv, nSurfId, true, true) if nCnt > 0 then -- elimino il profilo corrispondente solo se non è curva in o out ( per non eliminare il profilo principale) local nSemiProfileId = EgtGetInfo( nCrvId, WIN_SEMI_PROFILE, 'i') local nProfileId = EgtGetParent( nSemiProfileId) if EgtGetName( nProfileId) ~= WIN_PRF_MAIN then EgtErase( nProfileId) end -- elimino la curva EgtErase( nCrvId) else EgtSetInfo( nCrvId, WIN_GEO_EXTRA, true) EgtSetStatus( nCrvId, GDB_ST.OFF) end end 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, nExtraCurvesMode) -- costruisco la regione definita dalle curve local nGrpTmp = EgtGroup( GDB_ID.ROOT) EgtSetStatus( nGrpTmp, GDB_ST.OFF) local nSurfId = CalcIntersectionRegion( vCrvs, nGrpTmp) -- copia estesa delle curve local dExtraLen = 10000 local vCopies = {} for i = 1, #vCrvs do vCopies[i] = EgtCopyGlob( vCrvs[i], nGrpTmp) if EgtGetType( vCrvs[i]) == GDB_TY.CRV_LINE then -- se linea allungo le estremità EgtExtendCurveStartByLen( vCopies[i], dExtraLen) EgtExtendCurveEndByLen( vCopies[i], dExtraLen) else -- se arco lo trasformo in una circonferenza local dAngOld = EgtArcAngCenter( vCrvs[i]) EgtModifyArcAngCenter( vCopies[i], EgtIf( dAngOld > 0, 360, -360)) end end -- recupero le curve di bordo della regione local nBorderId = EgtExtractSurfFrChunkLoops( nSurfId, 0, nGrpTmp) local nCrvBorder, nCnt = EgtExplodeCurveCompo( nBorderId) -- individuo una curva di vCrvs e un tratto di nCrvBorder in corrispondenza biunivoca per gestire correttamente il ciclo -- ( 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), vCopies[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 local vResultCurves = {} local nC = nFirstIdxCrv local nB = nFirstIdxBorder repeat -- se ho terminato le curve di bordo da associare devo cancellare tutte le curve rimaste if nB == nFirstIdxBorder and nC ~= nFirstIdxCrv then AdjustExtraCurvesForTrim( vCrvs[nC+1], nSurfId, nExtraCurvesMode) else local dDist = EgtPointCurveDist( EgtMP( nCrvBorder + nB), vCopies[nC+1]) -- se trovo corrispondenza if dDist < GEO.EPS_SMALL then -- assegno il nome local sName = EgtGetName( vCrvs[nC+1]) if sName then EgtSetName( nCrvBorder + nB, sName) end -- copio le info local vInfo = EgtGetAllInfo( vCrvs[nC+1]) for j = 1, #vInfo do local sInfo = EgtSplitString( vInfo[j], '=') EgtSetInfo( nCrvBorder + nB, sInfo[1], sInfo[2]) end -- riposiziono EgtRelocateGlob( nCrvBorder + nB, vCrvs[nC+1], GDB_IN.AFTER) -- modifico l'id sostutuendolo alla curva originale EgtErase( vCrvs[nC+1]) EgtChangeId( nCrvBorder + nB, vCrvs[nC+1]) table.insert( vResultCurves, vCrvs[nC+1]) -- passo alla curva di bordo successiva nB = ( nB + 1) % nCnt else -- la curva non appartiene al bordo, quindi va gestita opportunamente AdjustExtraCurvesForTrim( vCrvs[nC+1], nSurfId, nExtraCurvesMode) end end -- passo alla curva successiva nC = ( nC + 1) % #vCrvs until nC == nFirstIdxCrv EgtErase( nGrpTmp) return vResultCurves end --------------------------------------------------------------------- -- funzione che data una curva di outline restituisce l'id del suo profilo local function GetOutlineProfileId( nOutlineId, bForceBottomRail, nProfileType) -- ciclo fino a trovare il primo parent che abbia un AreaType definito ( frame o sash) local nParentId = EgtGetParent( nOutlineId) local nAreaType = 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) end -- recupero il nome del profilo local sProfileName = EgtGetInfo( nOutlineId, WIN_PROFILETYPE) -- controlli per bottomrail if EgtGetName( nOutlineId) == WIN_BOTTOM and bForceBottomRail then local nBottomRailTot = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL, 'i') or 0 if nBottomRailTot > 0 then sProfileName = WIN_FILL_RAIL end elseif nProfileType == WIN_PRF.BOTTOMRAIL then sProfileName = WIN_RAIL elseif nProfileType == WIN_PRF.BOTTOMRAIL_FINAL then sProfileName = WIN_FILL_RAIL end -- recupero il profilo return EgtGetFirstNameInGroup( nLayerId, sProfileName) end --------------------------------------------------------------------- -- funzione che recupera il pezzo associato ad un outline local function FindAssociatedPart( nOutlineId, bUseBottomRail) local nCrvId = nOutlineId local nPartId = EgtGetInfo( nCrvId, WIN_REF_PART, 'i') if not nPartId then -- cerco la prima curva da cui deriva che ha un pezzo associato -- recupero il base outline da cui deriva local nBaseOutline = EgtGetInfo( nOutlineId, WIN_COPY, 'i') nBaseOutline = EgtGetInfo( nBaseOutline, WIN_SOU, 'i') while nBaseOutline and not nPartId do -- verifico se ha un profilo associato ( e quindi un pezzo) local sProfileType = EgtGetInfo( nBaseOutline, WIN_PROFILETYPE) if sProfileType then -- recupero l'outline associato nCrvId = EgtGetInfo( nBaseOutline, WIN_COPY, 'i') nPartId = EgtGetInfo( nCrvId, WIN_REF_PART, 'i') end nBaseOutline = EgtGetInfo( nBaseOutline, WIN_SOU, 'i') end end -- 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, GDB_RT.GLOB) return b3Box end ---------------------------------------------------------------------------------- ----------------------------- CALCOLO DEI PROFILI ------------------------------ ---------------------------------------------------------------------------------- -- funzione che restituisce il primo tipo di area definito tra le sottoaree che si generano da nAreaId local function GetAreaChildrenType( nAreaId) local vStack = EgtGetNameInGroup( nAreaId, WIN_AREA .. '*') or {} local i = 1 while vStack[i] do local nType = EgtGetInfo( vStack[i], WIN_AREATYPE, 'i') -- appena trovo un tipo definito esco if nType == WIN_AREATYPES.FILL then return WIN_CHILDREN_TYPES.FILL elseif nType == WIN_AREATYPES.SASH then return WIN_CHILDREN_TYPES.SASH else -- altrimenti analizzo le sottoaree local vSubAreas = EgtGetNameInGroup( vStack[i], WIN_AREA .. '*') or {} vStack = EgtJoinTables( vStack, vSubAreas) end i = i + 1 end -- se non trovo un tipo definito return WIN_CHILDREN_TYPES.NULL end --------------------------------------------------------------------- local function GetClosestAreaChildrenType( nAreaId) local nChildrenType = WIN_CHILDREN_TYPES.NULL local nType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i') while nChildrenType == WIN_CHILDREN_TYPES.NULL and nType ~= WIN_AREATYPES.FRAME do nAreaId = EgtGetParent( nAreaId) nType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i') nChildrenType = GetAreaChildrenType( nAreaId) end return nChildrenType end --------------------------------------------------------------------- -- funzione che verifica la tipologia delle curve figlie di una curva local function GetChildrenType( 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( 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 -- recupero i suoi figli local vChildren = EgtGetInfo( vStack[i], WIN_CHILD, 'vi') or {} if #vChildren == 0 then -- se non ha figli, per non creare problemi nel caso di cambio profilo ( in cui è necessario conoscere la struttura completa), -- assegno come tipologia quella dell'area più "vicina" nella struttura delle aree local nCurrType = GetClosestAreaChildrenType( nAreaId) if nCurrType == WIN_CHILDREN_TYPES.FILL then table.insert( vFillChildren, vStack[i]) elseif nCurrType == WIN_CHILDREN_TYPES.SASH then table.insert( vSashChildren, vStack[i]) end end -- aggiungo i suoi figli tra gli elementi da analizzare vStack = EgtJoinTables( vStack, vChildren) end -- aggiorno il contatore i = i + 1 end -- salvo i figli individuati come info della curva EgtSetInfo( nCrvId, WIN_SASH_CHILDREN, vSashChildren) EgtSetInfo( nCrvId, WIN_FILL_CHILDREN, vFillChildren) if #vFillChildren > 0 and #vSashChildren > 0 then return WIN_CHILDREN_TYPES.MIXED -- cambio profilo elseif #vFillChildren > 0 then return WIN_CHILDREN_TYPES.FILL elseif #vSashChildren > 0 then return WIN_CHILDREN_TYPES.SASH else return WIN_CHILDREN_TYPES.NULL end end --------------------------------------------------------------------- -- funzione che identifica il tipo di split ( mullion, mixed, ...) local function GetSplitType( nSplitId, nSplitLayerId) local nSplitType = EgtGetInfo( nSplitLayerId, WIN_SPLITTYPE, 'i') -- la tipologia è salvata nel layer solo se si tratta di un french split, negli altri casi va calcolata if not nSplitType then -- controllo se è dentro anta o telaio local nParentAreaId = EgtGetParent( nSplitLayerId) local nParentAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL while nParentAreaId and nParentAreaType ~= WIN_AREATYPES.SASH and nParentAreaType ~= WIN_AREATYPES.FRAME do nParentAreaId = EgtGetParent( nParentAreaId) nParentAreaType = EgtGetInfo( nParentAreaId or GDB_ID.NULL, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL end if nParentAreaType == WIN_AREATYPES.SASH then -- se dentro anta nSplitType = WIN_SPLITTYPES.INSASH else -- se dentro telaio verifico la tipologia dei figli local nChildrenType = GetChildrenType( nSplitId) if nChildrenType == WIN_CHILDREN_TYPES.MIXED then nSplitType = WIN_SPLITTYPES.MIXED elseif nChildrenType == WIN_CHILDREN_TYPES.FILL then nSplitType = WIN_SPLITTYPES.INFRAME 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, nCurrId) -- recupero l'altro child dello split local vSplitChildren = EgtGetInfo( nSplitId, WIN_CHILD, 'vi') local nAdjChild = EgtIf( vSplitChildren[1] == nCurrId, vSplitChildren[2], vSplitChildren[1]) -- recupero la sua tipologia dalla sua area local nAdjSash = EgtGetParent( EgtGetParent( nAdjChild)) local nAdjType = EgtGetInfo( nAdjSash, WIN_SASHTYPE, 'i') return nAdjType end --------------------------------------------------------------------- -- funzione che imposta i tipi di profilo in base al tipo di pezzi local function CalcProfileType( 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) -- recupero il tipo dei figli local nChildrenType = GetChildrenType( nOutlineId) -- a) se non definiti gestisco come anta o fixed if nChildrenType == WIN_CHILDREN_TYPES.NULL then local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0 if nBottomRail > 0 then -- se bottomrail gestisco come fixed bThreshold = false if sName == WIN_BOTTOM then EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_RAIL .. '_' .. sThreshold) else EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FIXED_TOP) end else -- se no bottomrail gestisco come anta if sName == WIN_BOTTOM then EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH .. '_' .. sThreshold) else EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH_TOP) end end -- b) se anta elseif nChildrenType == WIN_CHILDREN_TYPES.SASH then EgtRemoveInfo( nAreaId, WIN_BOTTOMRAIL) -- verifico tipologia di anta contro cui poggia local vChildren = EgtGetInfo( nOutlineId, WIN_SASH_CHILDREN, 'vi') local nSashArea = EgtGetParent( EgtGetParent( vChildren[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 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, #vChildren do local nSashArea = EgtGetParent( EgtGetParent( vChildren[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 EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH .. '_' .. sThreshold) else EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_SASH_TOP) end end -- c) se riempimento elseif nChildrenType == WIN_CHILDREN_TYPES.FILL then bThreshold = false 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 -- d) se cambio profilo elseif nChildrenType == WIN_CHILDREN_TYPES.MIXED then EgtRemoveInfo( nAreaId, WIN_BOTTOMRAIL) bThreshold = false EgtSetInfo( nOutlineId, WIN_PRF_CHANGE, true) if sName == WIN_BOTTOM then EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_MIXED_BOTTOM) else EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_MIXED_TOP) end end nOutlineId = EgtGetNext( nOutlineId) end -- assegno info soglia if bThreshold then EgtSetInfo( nAreaId, WIN_THRESHOLD, true) 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], nSplitLayerId) 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.INSASH then EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_SASH_SPLIT) elseif nSplitType == WIN_SPLITTYPES.INFRAME then EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_FRAME_SPLIT) elseif nSplitType == WIN_SPLITTYPES.MIXED then EgtSetInfo( vSplitIds[i], WIN_PROFILETYPE, WIN_MIXED_SPLIT) EgtSetInfo( vSplitIds[i], WIN_PRF_CHANGE, true) -- verifico se l'orientamento dello split è coerente con il cambio profilo ( vetro fisso a destra e anta a sinistra) : -- recupero il lato da cui si trova il figlio di tipo anta local nSashChild = EgtGetInfo( vSplitIds[i], WIN_SASH_CHILDREN, 'i') local nRefCrv = EgtGetNext( nSashChild) or EgtGetPrev( nSashChild) local _, _, nSide = EgtPointCurveDistSide( EgtMP( nRefCrv), vSplitIds[i], Z_AX()) -- se si trova a destra, lo split va invertito if nSide == 1 then EgtInvertCurve( vSplitIds[i]) -- scambio le info di intersezione local vStartInters = EgtGetInfo( vSplitIds[i], WIN_SPLIT_STARTINTERS, 'vi') local vEndInters = EgtGetInfo( vSplitIds[i], WIN_SPLIT_ENDINTERS, 'vi') EgtSetInfo( vSplitIds[i], WIN_SPLIT_STARTINTERS, vEndInters) EgtSetInfo( vSplitIds[i], WIN_SPLIT_ENDINTERS, vStartInters) end end -- se split di tipo french non ha profilo assegnato perchè non ha un pezzo associato end -- SASH elseif nAreaType == WIN_AREATYPES.SASH then -- verifico tipologia di anta ( battente, ricevente, alzante scorrevole) local nSashType = EgtGetInfo( nAreaId, WIN_SASHTYPE, 'i') or WIN_SASHTYPES.NULL -- verifico se bottomrail local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0 -- imposto profili sash local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_AREAOUTLINE) local nOutlineId = EgtGetFirstInGroup( nOutlineLayerId) while nOutlineId do 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 ( e quindi deve avere profilo speciale e.g. battente/ricevente) local nSouId = EgtGetInfo( nOutlineId, WIN_SOU, 'i') if EgtGetName( nSouId) == WIN_SPLIT then -- setto info sulla curva per ricordare che deriva da un french split 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 or nSashType == WIN_SASHTYPES.INACTIVE_IN then -- devo verificare il tipo dell'anta adiacente local nAdjSashType = FindAdjacentSashType( nSouId, nOutlineId) if nSashType == WIN_SASHTYPES.ACTIVE_IN then 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 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 end -- b) alzante scorrevole elseif nSashType == WIN_SASHTYPES.SLIDE_MOVABLE then local nAdjSashType = FindAdjacentSashType( nSouId, nOutlineId) 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 -- a) 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 -- b) 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 nOutlineId = EgtGetNext( nOutlineId) end end end --------------------------------------------------------------------- -- funzione che cicla ricorsivamente su aree e sottoaree per impostare i tipi di profilo local function CalculateAreaProfileType( nAreaId) -- calcolo i profili per l'area corrente CalcProfileType( nAreaId) -- 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 ---------------------------------------------------------------------------------- ------------------------------ CALCOLO OUTLINE --------------------------------- ---------------------------------------------------------------------------------- local function TrimSplitWithOutline( nSplitId) -- estendo agli estremi ( TO DO : gestire caso di split non lineare) EgtExtendCurveStartByLen( nSplitId, 50) EgtExtendCurveEndByLen( nSplitId, 50) -- lo taglio con outline local nStartIntersId = EgtGetInfo( nSplitId, WIN_SPLIT_STARTINTERS, 'i') local nOutlineId = EgtGetInfo( nStartIntersId, WIN_COPY, 'i') local ptStartInters = EgtIP( nSplitId, nOutlineId, EgtSP( nSplitId)) local dStartInters = EgtCurveParamAtPoint( nSplitId, ptStartInters) EgtTrimCurveStartAtParam( nSplitId, dStartInters) local nEndIntersId = EgtGetInfo( nSplitId, WIN_SPLIT_ENDINTERS, 'i') nOutlineId = EgtGetInfo( nEndIntersId, WIN_COPY, 'i') local ptEndInters = EgtIP( nSplitId, nOutlineId, EgtEP( nSplitId)) local dEndInters = EgtCurveParamAtPoint( nSplitId, ptEndInters) EgtTrimCurveEndAtParam( nSplitId, dEndInters) end --------------------------------------------------------------------- -- funzione che calcola l'outline per aree virtuali ausiliarie di split a griglia local function CalculateVirtualAreaOutline( nAreaId, dZmove) local nOutlineLayerId = EgtGroup( nAreaId) EgtSetName( nOutlineLayerId, WIN_OUTLINE) EgtSetStatus( nOutlineLayerId, GDB_ST.OFF) local nBaseOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_AREAOUTLINE) local nBaseOutlineId = EgtGetFirstInGroup( nBaseOutlineLayerId) while nBaseOutlineId do local nSouId = EgtGetInfo( nBaseOutlineId, WIN_SOU, 'i') local nOutlineId if EgtGetName( nSouId) == WIN_SPLIT then -- se deriva da split lo copio e lo traslo nOutlineId = EgtCopy( nSouId, nOutlineLayerId) EgtMove( nOutlineId, Z_AX() * dZmove) EgtSetName( nOutlineId, EgtGetName( nBaseOutlineId)) -- salvo riferimento dello split da cui deriva EgtSetInfo( nOutlineId, WIN_REF_SPLIT, nSouId) -- verifico orientamento local nCrvRef = EgtGetPrev( nBaseOutlineId) or EgtGetNext( nBaseOutlineId) local _, _, nSide = EgtPointCurveDistSide( EgtMP( nCrvRef), nOutlineId, Z_AX()) if nSide == 1 then EgtInvertCurve( nOutlineId) EgtSetInfo( nOutlineId, WIN_INV_SPLIT, true) end else local nCopyId = EgtGetInfo( nSouId, WIN_COPY, 'i') or GDB_ID.NULL nOutlineId = EgtCopy( nCopyId, nOutlineLayerId) end if nOutlineId then -- sistemo le info EgtSetInfo( nOutlineId, WIN_COPY, nBaseOutlineId) EgtSetInfo( nBaseOutlineId, WIN_COPY, nOutlineId) EgtRemoveInfo( nOutlineId, WIN_CHILD) end nBaseOutlineId = EgtGetNext( nBaseOutlineId) end -- taglio tutti i contorni TrimOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), 1) end --------------------------------------------------------------------- local function CalculateSplitOutline( nAreaId) -- copio il layer di base outline 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) -- se split interni ad anta ricavo quota in z dal suo profilo local dZMove = 0 local nSplitType = EgtGetInfo( vSplitIds[1], WIN_SPLITTYPE, 'i') if nSplitType == WIN_SPLITTYPES.INSASH then -- recupero area sash che lo contiene local nSashAreaId = nAreaId local nAreaType = EgtGetInfo( nSashAreaId, WIN_AREATYPE, 'i') while nAreaType ~= WIN_AREATYPES.SASH do nSashAreaId = EgtGetParent( nSashAreaId) nAreaType = EgtGetInfo( nSashAreaId, WIN_AREATYPE, 'i') end -- recupero il profilo dell'anta da una curva dell'outline local nSashBaseOutlineLayerId = EgtGetFirstNameInGroup( nSashAreaId, WIN_AREAOUTLINE) local nSashBaseOutlineId = EgtGetFirstInGroup( nSashBaseOutlineLayerId) local sSashProfile = EgtGetInfo( nSashBaseOutlineId, WIN_PROFILETYPE) local nProfileLayerId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE) local nSashProfileLayerId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_SASH) local nSashProfileId = EgtGetFirstNameInGroup( nSashProfileLayerId, sSashProfile) -- calcolo offset sulla z dell'anta dZMove = EgtGetInfo( nSashProfileId, WIN_DELTA, 'd') end -- verifico se presenti aree ausiliarie per split a griglia local vAuxAreas = EgtGetNameInGroup( nAreaId, WIN_VIRTUAL_AREA) or {} for i = 1, #vAuxAreas do CalculateVirtualAreaOutline( vAuxAreas[i], dZMove) end -- sistemo gli outline degli split for i = 1, #vSplitIds do -- sistemo le info EgtSetInfo( vBaseSplitIds[i], WIN_COPY, vSplitIds[i]) EgtSetInfo( vSplitIds[i], WIN_COPY, vBaseSplitIds[i]) -- taglio con outline TrimSplitWithOutline( vSplitIds[i]) -- aggiusto quota EgtMove( vSplitIds[i], Z_AX() * dZMove) end end --------------------------------------------------------------------- local function CalculateFillOutline( nAreaId, nAreaLayerId, nOutlineLayerId) -- recupero area parent di tipo telaio/anta che la contiene local vSplitAreas = {} local nParentArea = EgtGetParent( nAreaId) local nAreaType = EgtGetInfo( nParentArea, WIN_AREATYPE, 'i') while nAreaType ~= WIN_AREATYPES.FRAME and nAreaType ~= WIN_AREATYPES.SASH do if nAreaType == WIN_AREATYPES.SPLIT then table.insert( vSplitAreas, nParentArea) end 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 vAdjustZ = {} local nRefZ local nParentOutlineId = EgtGetFirstInGroup( nParentOutlineLayer) while nParentOutlineId do -- copio la curva di outline del parent local nOutlineId = EgtCopy( nParentOutlineId, nOutlineLayerId) EgtSetInfo( nOutlineId, WIN_REF_OUTLINE, nParentOutlineId) -- recupero il suo profilo per calcolare l'offset perpendicolare local nParentProfileId = GetOutlineProfileId( nParentOutlineId, true) local b3FrameProfile = GetProfileLocalBox( nParentProfileId) local dOverlap = EgtGetInfo( nParentProfileId, WIN_FILLOVERLAP, 'd') or 0 local dDimRef = b3FrameProfile:getMin():getX() local dFillPerpOffset = abs( dDimRef) - dOverlap if EgtGetName( nParentProfileId) == WIN_FILL_RAIL then -- se bottom rail considero la distanza necessaria per il numero di bottomrail richiesti local nBottomRails = EgtGetInfo( nParentOutlineId, WIN_BOTTOMRAIL, 'i') local dRailDelta1 = EgtGetInfo( nParentProfileId, WIN_RAILDELTA .. '1', 'd') local dRailDelta2 = EgtGetInfo( nParentProfileId, WIN_RAILDELTA .. '2', 'd') dFillPerpOffset = dFillPerpOffset + dRailDelta1 + ( nBottomRails - 1) * dRailDelta2 end EgtOffsetCurve( nOutlineId, - dFillPerpOffset) -- movimento in z : se non è definito ( come nel caso di alcuni pezzi di telaio con cambio profilo) salvo la curva per correggere la sua z in seguito, se è definito salvo -- una curva come riferimento per le curve da correggere local dFillZOffset = EgtGetInfo( nParentProfileId, WIN_FILLDELTA, 'd') if not dFillZOffset then table.insert( vAdjustZ, nOutlineId) else nRefZ = nOutlineId EgtMove( nOutlineId, Z_AX() * dFillZOffset) end nParentOutlineId = EgtGetNext( nParentOutlineId) end -- sistemo quote per tratti che non avevano movimento in z definito nel profilo for i = 1, #vAdjustZ do EgtMove( vAdjustZ[i], ( EgtSP( nRefZ):getZ() - EgtSP( vAdjustZ[i]):getZ()) * Z_AX()) end -- accorcio gli offset local vCrvs = TrimOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), 1) -- 2) taglio con split if #vSplitAreas == 0 then return end -- creo bordo complessivo dell'outline, salvando le info come temp prop della curva per non perderle local vRefOutlines = {} for i = 1, #vCrvs do vRefOutlines[i] = EgtGetInfo( vCrvs[i], WIN_REF_OUTLINE, 'i') end local nCompo = EgtCurveCompo( nOutlineLayerId, vCrvs) for i = 0, #vCrvs - 1 do EgtCurveCompoSetTempProp( nCompo, i, vRefOutlines[i+1]) end -- recupero gli split coinvolti nell'area fill local tabSplits = {} local vBaseOutlines = EgtGetAllInGroup( nAreaLayerId) for i = 1, #vBaseOutlines do -- verifico se deriva da split local nSouId = EgtGetInfo( vBaseOutlines[i], WIN_SOU, 'i') while nSouId and EgtGetName( nSouId) ~= WIN_SPLIT do nSouId = EgtGetInfo( nSouId, WIN_SOU, 'i') end if nSouId then tabSplits[nSouId] = vBaseOutlines[i] end end -- taglio con split for i = #vSplitAreas, 1, -1 do local nSplitBaseOutline = EgtGetFirstNameInGroup( vSplitAreas[i], WIN_BASESPLIT) local vSplitBaseOutlines = EgtGetAllInGroup( nSplitBaseOutline) for j = 1, #vSplitBaseOutlines do -- verifico sia uno split coinvolto nell'area fill considerata if tabSplits[vSplitBaseOutlines[j]] then -- a) creo la curva di outline corrispondente allo split local nSplitOutline = EgtGetInfo( vSplitBaseOutlines[j], WIN_COPY, 'i') local nOutlineId = EgtCopy( nSplitOutline, nOutlineLayerId) -- verifico orientamento local nRefCrv = EgtGetPrev( tabSplits[vSplitBaseOutlines[j]]) or EgtGetNext( tabSplits[vSplitBaseOutlines[j]]) local _, _, nSide = EgtPointCurveDistSide( EgtMP( nRefCrv), vSplitBaseOutlines[j], Z_AX()) if nSide == 1 then EgtInvertCurve( nOutlineId) end -- calcolo gli offset local nParentProfileId = GetOutlineProfileId( nSplitOutline, true) local b3FrameProfile = GetProfileLocalBox( nParentProfileId) local dOverlap = EgtGetInfo( nParentProfileId, WIN_FILLOVERLAP, 'd') local bMixedSplit = EgtGetInfo( nSplitOutline, WIN_PRF_CHANGE, 'b') or false local dDimRef = EgtIf( bMixedSplit, b3FrameProfile:getMax():getX(), b3FrameProfile:getMin():getX()) local dFillPerpOffset = abs( dDimRef) - dOverlap EgtOffsetCurve( nOutlineId, - dFillPerpOffset) -- movimento in z local dFillZOffset = EgtGetInfo( nParentProfileId, WIN_FILLDELTA, 'd') EgtMove( nOutlineId, Z_AX() * dFillZOffset) -- b) 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, EgtIf( nSide == 1, - nSplitOutline, nSplitOutline)) end end 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_REF_OUTLINE, vTempProps[i+1]) if vTempProps[i+1] < 0 then EgtSetInfo( nCrv + i, WIN_INV_SPLIT, true) end end end --------------------------------------------------------------------- -- funzione che calcola l'outline dall'area outline ( base outline) local function CalculateOutlineFromAreaOutline( nAreaId) local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i') -- recupero il base outline e creo gruppo per outline local nAreaOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_AREAOUTLINE) local nOutlineLayerId = EgtGroup( nAreaId) EgtSetName( nOutlineLayerId, WIN_OUTLINE) EgtSetStatus( nOutlineLayerId, GDB_ST.OFF) CopyInfo( nOutlineLayerId, nAreaOutlineLayerId, WIN_JOINTS) -- FRAME if nAreaType == WIN_AREATYPES.FRAME then -- sistemo le info local nAreaOutlineId = EgtGetFirstInGroup( nAreaOutlineLayerId) while nAreaOutlineId do local nOutlineId = EgtCopyGlob( nAreaOutlineId, nOutlineLayerId) EgtSetInfo( nAreaOutlineId, WIN_COPY, nOutlineId) EgtSetInfo( nOutlineId, WIN_COPY, nAreaOutlineId) -- se bottom riporto informazione dei bottomrail e soglia if EgtGetName( nOutlineId) == WIN_BOTTOM then CopyInfo( nOutlineId, nAreaId, WIN_BOTTOMRAIL) CopyInfo( nOutlineId, nAreaId, WIN_THRESHOLD) end nAreaOutlineId = EgtGetNext( nAreaOutlineId) end -- SPLIT elseif nAreaType == WIN_AREATYPES.SPLIT or nAreaType == WIN_AREATYPES.NULL then -- a) outline dell'area local nBaseOutlineId = EgtGetFirstInGroup( nAreaOutlineLayerId) while nBaseOutlineId do -- recupero la curva di outline corrispondente alla curva del base outline da cui deriva e la copio local nSouId = EgtGetInfo( nBaseOutlineId, WIN_SOU, 'i') local nCopyId = EgtGetInfo( nSouId, WIN_COPY, 'i') or GDB_ID.NULL local nOutlineId = EgtCopy( nCopyId, nOutlineLayerId) if nOutlineId then -- se deriva da split devo aggiornare il nome, controllare l'orientamento e settare il riferimento local sSouName = EgtGetName( nSouId) if sSouName == WIN_SPLIT then local sBaseName = EgtGetName( nBaseOutlineId) EgtSetName( nOutlineId, sBaseName) EgtSetInfo( nOutlineId, WIN_REF_SPLIT, nSouId) -- verifico orientamento local nCrvRef = EgtGetPrev( nBaseOutlineId) or EgtGetNext( nBaseOutlineId) local _, _, nSide = EgtPointCurveDistSide( EgtMP( nCrvRef), nOutlineId, Z_AX()) if nSide == 1 then EgtInvertCurve( nOutlineId) EgtSetInfo( nOutlineId, WIN_INV_SPLIT, true) end end -- sistemo le info EgtSetInfo( nOutlineId, WIN_COPY, nBaseOutlineId) EgtSetInfo( nBaseOutlineId, WIN_COPY, nOutlineId) EgtRemoveInfo( nOutlineId, WIN_CHILD) end nBaseOutlineId = EgtGetNext( nBaseOutlineId) end -- taglio tutti i contorni TrimOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), 1) -- b) split if nAreaType == WIN_AREATYPES.SPLIT then CalculateSplitOutline( nAreaId) end -- SASH elseif nAreaType == WIN_AREATYPES.SASH then -- recupero se anta battente ricevente local nSashType = EgtGetInfo( nAreaId, WIN_SASHTYPE, 'i') or WIN_SASHTYPES.NULL -- recupero gruppo profili anta e telaio local nProfileLayerId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE) local nSashProfileLayerId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_SASH) local nFrameProfileLayerId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_FRAME) -- ciclo su profilo disegnato anta local nBaseOutlineId = EgtGetFirstInGroup( nAreaOutlineLayerId) while nBaseOutlineId do -- recupero la curva di outline del base outline da cui deriva e la copio local nSouId = EgtGetInfo( nBaseOutlineId, WIN_SOU, 'i') local nCopyId = EgtGetInfo( nSouId, WIN_COPY, 'i') or GDB_ID.NULL local nOutlineId = EgtCopy( nCopyId, nOutlineLayerId) if nOutlineId then -- recupero profilo local sSashProfile = EgtGetInfo( nBaseOutlineId, WIN_PROFILETYPE) local nSashProfileId = EgtGetFirstNameInGroup( nSashProfileLayerId, sSashProfile) -- calcolo offset sulla z dell'anta local dSashZOffset = EgtGetInfo( nSashProfileId, WIN_DELTA, 'd') -- sposto anta in Z EgtMove( nOutlineId, Z_AX() * dSashZOffset) -- sistemo le info EgtSetInfo( nBaseOutlineId, WIN_COPY, nOutlineId) EgtSetInfo( nOutlineId, WIN_COPY, nBaseOutlineId) EgtSetInfo( nOutlineId, WIN_PROFILETYPE, sSashProfile) if EgtGetName( nOutlineId) == WIN_BOTTOM then CopyInfo( nOutlineId, nAreaId, WIN_BOTTOMRAIL) end EgtRemoveInfo( nOutlineId, WIN_PRF_CHANGE) EgtRemoveInfo( nOutlineId, WIN_REF_SPLIT) EgtRemoveInfo( nOutlineId, WIN_INV_SPLIT) EgtRemoveInfo( nOutlineId, WIN_THRESHOLD) -- verifico se outline e' segmento battente o ricevente ( che quindi deriva da split di tipo french) local bOnFrenchSplit = EgtGetInfo( nBaseOutlineId, WIN_CRV_ON_FRENCH_SPLIT, 'b') or false if not bOnFrenchSplit then -- se outline non è segmento battente o ricevente necessita di offset -- recupero a ritroso il profilo dell'elemento del frame su cui poggia local nFrameBaseOutlineId = nSouId local sFrameProfile = EgtGetInfo( nFrameBaseOutlineId, WIN_PROFILETYPE) while not sFrameProfile and nFrameBaseOutlineId do nFrameBaseOutlineId = EgtGetInfo( nFrameBaseOutlineId, WIN_SOU , 'i') sFrameProfile = EgtGetInfo( nFrameBaseOutlineId or GDB_ID.NULL, WIN_PROFILETYPE) end local nFrameProfileId = EgtGetFirstNameInGroup( nFrameProfileLayerId, sFrameProfile) -- calcolo il box del riferimento del profilo del frame local b3FrameProfile = GetProfileLocalBox( nFrameProfileId) -- calcolo offset perpendicolare local sOverlapInfo = EgtIf( EgtGetName( nOutlineId) == WIN_BOTTOM, WIN_SASH_BOTTOM_OVERLAP, WIN_SASH_TOP_OVERLAP) local dOverlap = EgtGetInfo( nFrameProfileId, sOverlapInfo, 'd') local dSashPerpOffset = abs( b3FrameProfile:getMin():getX()) - dOverlap -- faccio offset EgtOffsetCurve( nOutlineId, - dSashPerpOffset) else -- se deriva da french split sistemo il nome local sBaseName = EgtGetName( nBaseOutlineId) EgtSetName( nOutlineId, sBaseName) -- controllo l'orientamento local nCrvRef = EgtGetPrev( nBaseOutlineId) or EgtGetNext( nBaseOutlineId) local _, _, nSide = EgtPointCurveDistSide( EgtMP( nCrvRef), nOutlineId, Z_AX()) if nSide == 1 then EgtInvertCurve( nOutlineId) end end end nBaseOutlineId = EgtGetNext( nBaseOutlineId) end -- accorcio gli offset TrimOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), 1) -- FILL elseif nAreaType == WIN_AREATYPES.FILL then CalculateFillOutline( nAreaId, nAreaOutlineLayerId, nOutlineLayerId) end end --------------------------------------------------------------------- -- funzione che cicla ricorsivamente su aree e sottaree per calcolare gli outlines local function CalculateAreaOutline( nAreaId) -- calcolo outlines per l'area corrente CalculateOutlineFromAreaOutline( nAreaId) -- calcolo outlines per le eventuali sottoaree local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*') while nChildAreaId do CalculateAreaOutline( nChildAreaId) nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*') end end ---------------------------------------------------------------------------------- ------------------------ FUNZIONI AUX PER CALCOLO PEZZI ------------------------ ---------------------------------------------------------------------------------- -- funzione che restituisce il WIN_PRF in base al nome della curva local function GetOutlineProfileType( nOutlineId, bForceBottomRail, nBottomRail) -- ricavo tipo dal nome local sName = EgtGetName( nOutlineId) local nProfileType = WIN_PRF.NULL if sName == WIN_TOP then nProfileType = WIN_PRF.TOP elseif sName == WIN_BOTTOM then local nBottomRailTot = EgtGetInfo( nOutlineId, WIN_BOTTOMRAIL, 'i') or 0 if bForceBottomRail and nBottomRailTot > 0 then nProfileType = WIN_PRF.BOTTOMRAIL_FINAL elseif nBottomRail then -- verifico se bottomrail intermedio o finale if nBottomRail == nBottomRailTot then nProfileType = WIN_PRF.BOTTOMRAIL_FINAL else nProfileType = WIN_PRF.BOTTOMRAIL end else nProfileType = WIN_PRF.BOTTOM end elseif sName == WIN_LEFT then nProfileType = WIN_PRF.LEFT elseif sName == WIN_RIGHT then nProfileType = WIN_PRF.RIGHT elseif sName == WIN_SPLIT then nProfileType = WIN_PRF.SPLIT end return nProfileType end --------------------------------------------------------------------- -- funzione che restituisce il tipo di controprofilo dell'outline adiacente local function GetProfileCtrIn( nPrevOutlineId, nOutlineId, nPrevProfileId) local sPrevCtrIn = WIN_CTRIN -- gestione particolare del caso di split o cambio profilo if not EgtGetFirstNameInGroup( nPrevProfileId, sPrevCtrIn) then local nRefSplitId = EgtGetInfo( nPrevOutlineId, WIN_REF_SPLIT, 'i') if nRefSplitId or EgtGetName( nPrevOutlineId) == WIN_SPLIT then -- 1) split -- verifico da quale lato dello split originale si trova l'outline per decidere quale controprofilo considerare local _, _, nSide = EgtPointCurveDistSide( EgtMP( nOutlineId), nRefSplitId or nPrevOutlineId, Z_AX()) if nSide == 1 then sPrevCtrIn = WIN_CTRIN .. '1' -- dx else sPrevCtrIn = WIN_CTRIN .. '2' -- sx end else -- 2) pezzo del telaio con cambio profilo -- il profilo da usare dipende dal pezzo corrente: se ha figli di tipo fill allora è legato alla parte fill del cambio profilo, se ha figli di tipo sash è legato alla parte sash, -- se ha entrambe le tipologie di figli allora è mixed split e va considerata la parte sash ( perchè è quella utilizzata per tagliare il pezzo) local vSashChildren = EgtGetInfo( nOutlineId, WIN_SASH_CHILDREN, 'vi') if vSashChildren then sPrevCtrIn = WIN_SASH .. WIN_CTRIN else sPrevCtrIn = WIN_FILL .. WIN_CTRIN end end end return sPrevCtrIn 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_PRF_TYPE) if sProfileType == WIN_RAIL or sProfileType == WIN_FILL_RAIL then local dOffs = EgtGetInfo( nProfileId, WIN_RAILDELTA, 'd') EgtOffsetCurve( nGuideId, - dOffs) end -- verifico se necessaria inversione della guida nel caso sia curva "virtuale" ( ovvero in area null o split) che deriva da pezzo di split if EgtExistsInfo( nOutlineId, WIN_INV_SPLIT) then EgtInvertCurve( nGuideId) 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 --------------------------------------------------------------------- -- funzione che verifica gli outlines prev/next per lo split controllando l'interferenza tra i profili local function TestSplitTrimOutlines( nOutlineId, vTrimOutlines, nMainProfile, b3Profile, nGrpTmp, bPrevOrNext) local vRealTrimOutlines = {} -- 1) recupero le curve da testare local vTestOutlines = {} -- a) curve individuate dalle intersezioni degli outlines for i = 1, #vTrimOutlines do vTestOutlines[i] = vTrimOutlines[i] end -- b) curve vicine a quelle individuate dalle intersezioni che interferiscono con l'outline ( guardando interferenza grossolana dei pezzi) -- recupero le curve di bordo del pezzo di split local nOutlineCopyId = EgtCopyGlob( nOutlineId, nGrpTmp) if bPrevOrNext then EgtTrimCurveEndAtParam( nOutlineCopyId, 0.5) else EgtTrimCurveStartAtParam( nOutlineCopyId, 0.5) end local nOutId = EgtOffsetCurveAdv( nOutlineCopyId, b3Profile:getMax():getX()) local nInId = EgtOffsetCurveAdv( nOutlineCopyId, b3Profile:getMin():getX()) -- curve precedenti local nTestCurve = EgtGetPrev( vTrimOutlines[1]) or EgtGetLastInGroup( EgtGetParent( vTrimOutlines[1])) local bInters = true while bInters and nTestCurve ~= vTrimOutlines[#vTrimOutlines] do local nRefPart = FindAssociatedPart( nTestCurve, true) local nRefGeo = EgtGetFirstNameInGroup( nRefPart, WIN_GEO) local nRefSurf = EgtGetFirstNameInGroup( nRefGeo, WIN_GEO_SURF) local nClassOut = EgtCurveWithRegionClassify( nOutId, nRefSurf) if nClassOut == GDB_CRC.OUT then local nClassIn = EgtCurveWithRegionClassify( nInId, nRefSurf) -- se non c'è interferenza interrompo la ricerca if nClassIn == GDB_CRC.OUT then bInters = false end end -- se interferenza lo aggiungo tra le curve da controllare if bInters then table.insert( vTestOutlines, 1, nTestCurve) nTestCurve = EgtGetPrev( nTestCurve) or EgtGetLastInGroup( EgtGetParent( nTestCurve)) end end -- curve successive nTestCurve = EgtGetNext( vTrimOutlines[#vTrimOutlines]) or EgtGetFirstInGroup( EgtGetParent( vTrimOutlines[1])) bInters = true while bInters and nTestCurve ~= vTrimOutlines[1] do local nRefPart = FindAssociatedPart( nTestCurve, true) local nRefGeo = EgtGetFirstNameInGroup( nRefPart, WIN_GEO) local nRefSurf = EgtGetFirstNameInGroup( nRefGeo, WIN_GEO_SURF) local nClassOut = EgtCurveWithRegionClassify( nOutId, nRefSurf) if nClassOut == GDB_CRC.OUT then local nClassIn = EgtCurveWithRegionClassify( nInId, nRefSurf) if nClassIn == GDB_CRC.OUT then bInters = false end end if bInters then table.insert( vTestOutlines, nTestCurve) nTestCurve = EgtGetNext( nTestCurve) or EgtGetFirstInGroup( EgtGetParent( nTestCurve)) end end -- 2) testo le curve controllando intersezione tra le superfici dei pezzi -- creo il solido principale local dExtraLen = b3Profile:getDimX() local nMainSurf = CreateProfileSurf( nOutlineId, nMainProfile, WIN_SECTION, 4 * dExtraLen, nGrpTmp) EgtCutSurfTmPlane( nMainSurf, EgtMP( nOutlineId), EgtIf( bPrevOrNext, 1, -1) * EgtSV( nOutlineId)) -- recupero profili per i conti local vProfiles = {} local vsCtrIn = {} for i = 1, #vTestOutlines do vProfiles[i] = GetOutlineProfileId( vTestOutlines[i], true) vsCtrIn[i] = GetProfileCtrIn( vTestOutlines[i], nOutlineId, vProfiles[i]) end -- testo le curve for i = 1, #vTestOutlines do -- creo la superficie di test limitandola con le sue vicine local nTestSurf = CreateProfileSurf( vTestOutlines[i], vProfiles[i], vsCtrIn[i], 4 * dExtraLen, nGrpTmp) if i > 1 then if AreSameVectorApprox( EgtEV( vTestOutlines[i-1]), EgtSV( vTestOutlines[i])) then EgtCutSurfTmPlane( nTestSurf, EgtEP( vTestOutlines[i-1]), - EgtEV( vTestOutlines[i-1]), false) else local nTrimSurf = CreateProfileSurf( vTestOutlines[i-1], 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( vTestOutlines[i]), EgtSV( vTestOutlines[i+1])) then EgtCutSurfTmPlane( nTestSurf, EgtEP( vTestOutlines[i]), EgtEV( vTestOutlines[i]), false) else local nTrimSurf = CreateProfileSurf( vTestOutlines[i+1], 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( vRealTrimOutlines, vTestOutlines[i]) end end return vRealTrimOutlines end --------------------------------------------------------------------- -- funzione che recupera gli outline precedenti e successivi local function GetPrevNextOutline( nProfileType, nOutlineId, nOutlineLayerId) local vPrevOutlineId = {} local vNextOutlineId = {} if nProfileType ~= WIN_PRF.SPLIT then vPrevOutlineId = { EgtGetPrev( nOutlineId) or EgtGetLastInGroup( nOutlineLayerId)} vNextOutlineId = { EgtGetNext( nOutlineId) or EgtGetFirstInGroup( nOutlineLayerId)} else -- se split recupero tutte le curve di base outline che lo tagliano dalle info local vPrevBaseOutlineId = EgtGetInfo( nOutlineId, WIN_SPLIT_STARTINTERS, 'vi') local vNextBaseOutlineId = EgtGetInfo( nOutlineId, WIN_SPLIT_ENDINTERS, 'vi') -- recupero gli outlines associati for i = 1, #vPrevBaseOutlineId do vPrevOutlineId[i] = EgtGetInfo( vPrevBaseOutlineId[i], WIN_COPY, 'i') end for i = 1, #vNextBaseOutlineId do vNextOutlineId[i] = EgtGetInfo( vNextBaseOutlineId[i], WIN_COPY, 'i') end -- controllo validità delle curve trovate verificando l'interferenza tra i profili local nGrpTmp = EgtGroup( GDB_ID.ROOT) local nMainProfile = GetOutlineProfileId( nOutlineId) local b3Profile = GetProfileLocalBox( nMainProfile) vPrevOutlineId = TestSplitTrimOutlines( nOutlineId, vPrevOutlineId, nMainProfile, b3Profile, nGrpTmp, true) vNextOutlineId = TestSplitTrimOutlines( nOutlineId, vNextOutlineId, nMainProfile, b3Profile, nGrpTmp, false) EgtErase( nGrpTmp) -- considero come curve prev e next quelle associate ad un pezzo e non curve virtuali per rendere più solidi i conti successivi -- verifico la coerenza dell'orientamento e la indico con il segno ( > 0 concorde, < 0 discorde e va invertita) for i = 1, #vPrevOutlineId do local nPart = FindAssociatedPart( vPrevOutlineId[i], true) local bInvert = EgtGetInfo( vPrevOutlineId[i], WIN_INV_SPLIT, 'b') or false vPrevOutlineId[i] = EgtGetInfo( nPart, WIN_REF_OUTLINE, 'i') if bInvert then vPrevOutlineId[i] = - vPrevOutlineId[i] end end for i = 1, #vNextOutlineId do local nPart = FindAssociatedPart( vNextOutlineId[i], true) local bInvert = EgtGetInfo( vNextOutlineId[i], WIN_INV_SPLIT, 'b') or false vNextOutlineId[i] = EgtGetInfo( nPart, WIN_REF_OUTLINE, 'i') if bInvert then vNextOutlineId[i] = - vNextOutlineId[i] end end end return vPrevOutlineId, vNextOutlineId end ---------------------------------------------------------------------------------- -------------------------------- GEO ------------------------------------------- ---------------------------------------------------------------------------------- -- funzione che dato il tipo di pezzo e di giunzione, restituisce se e' corto, lungo o angolato local function CalcPartJointType( nProfileType, JointType) if JointType == WIN_JNT.ANGLED then return WIN_PART_JNT.ANGLED end if nProfileType == WIN_PRF.BOTTOMRAIL or nProfileType == WIN_PRF.BOTTOMRAIL_FINAL or nProfileType == WIN_PRF.SPLIT then return WIN_PART_JNT.SHORT elseif nProfileType == WIN_PRF.BOTTOM or nProfileType == WIN_PRF.TOP then if JointType == WIN_JNT.FULL_H then return WIN_PART_JNT.FULL elseif JointType == WIN_JNT.FULL_V then return WIN_PART_JNT.SHORT end elseif nProfileType == WIN_PRF.LEFT or nProfileType == WIN_PRF.RIGHT then if JointType == WIN_JNT.FULL_V then return WIN_PART_JNT.FULL elseif JointType == WIN_JNT.FULL_H then return WIN_PART_JNT.SHORT end end end --------------------------------------------------------------------- -- funzione che calcola e salva nel profilo il delta del bottomrail corrente rispetto alla sua curva di outline local function SaveRailDelta( nProfileId, nBottomRail) local dDelta1 = EgtGetInfo( nProfileId, WIN_RAILDELTA .. '1', 'd') local dDelta2 = EgtGetInfo( nProfileId, WIN_RAILDELTA .. '2', 'd') local dOffs = dDelta1 + ( nBottomRail - 1) * dDelta2 EgtSetInfo( nProfileId, WIN_RAILDELTA, dOffs) end --------------------------------------------------------------------- -- funzione che crea il gruppo con i profili di un pezzo local function CalcProfiles( nPartId, nOutlineId, vPrevOutlineId, vNextOutlineId, nProfileType, nBottomRail) -- creo gruppo per i profili local nProfileLayerId = EgtGroup( nPartId) EgtSetName( nProfileLayerId, WIN_PROFILE) EgtSetStatus( nProfileLayerId, GDB_ST.OFF) -- recupero profilo principale e ne creo copia local nOrigMainProfileId = GetOutlineProfileId( nOutlineId, false, nProfileType) local nMainProfileId = EgtCopy( nOrigMainProfileId, nProfileLayerId) local sMainProfileType = EgtGetName( nMainProfileId) EgtSetInfo( nMainProfileId, WIN_PRF_TYPE, sMainProfileType) EgtSetName( nMainProfileId, WIN_PRF_MAIN) -- se bottomrail salvo info per scostamento dall'outline if sMainProfileType == WIN_FILL_RAIL or sMainProfileType == WIN_RAIL then SaveRailDelta( nMainProfileId, nBottomRail) end -- recupero profili start e ne creo copia -- se il tipo corrente è split il pezzo va tagliato con il bottomrail, altrimenti con il bottom for i = 1, #vPrevOutlineId do local nOrigStartProfileId = GetOutlineProfileId( abs( vPrevOutlineId[i]), nProfileType == WIN_PRF.SPLIT) local nStartProfileId = EgtCopy( nOrigStartProfileId, nProfileLayerId) local sStartProfileType = EgtGetName( nStartProfileId) EgtSetInfo( nStartProfileId, WIN_PRF_TYPE, sStartProfileType) EgtSetName( nStartProfileId, WIN_PRF_START) if sStartProfileType == WIN_FILL_RAIL then local nBottomRailTot = EgtGetInfo( abs( vPrevOutlineId[i]), WIN_BOTTOMRAIL, 'i') SaveRailDelta( nStartProfileId, nBottomRailTot) end end -- recupero profili end e ne creo copia for i = 1, #vNextOutlineId do local nOrigEndProfileId = GetOutlineProfileId( abs( vNextOutlineId[i]), nProfileType == WIN_PRF.SPLIT) local nEndProfileId = EgtCopy( nOrigEndProfileId, nProfileLayerId) local sEndProfileType = EgtGetName( nEndProfileId) EgtSetInfo( nEndProfileId, WIN_PRF_TYPE, sEndProfileType) EgtSetName( nEndProfileId, WIN_PRF_END) if sEndProfileType == WIN_FILL_RAIL then local nBottomRailTot = EgtGetInfo( abs( vNextOutlineId[i]), WIN_BOTTOMRAIL, 'i') SaveRailDelta( nEndProfileId, nBottomRailTot) end end -- recupero le info di pinzaggio dal profilo di estrusione CopyInfo( nPartId, nMainProfileId, WIN_PRC_OFFY_1, 0) CopyInfo( nPartId, nMainProfileId, WIN_PRC_OFFZ_1, 0) CopyInfo( nPartId, nMainProfileId, WIN_PRC_OFFY_2, 0) CopyInfo( nPartId, nMainProfileId, WIN_PRC_OFFZ_2, 0) CopyInfo( nPartId, nMainProfileId, WIN_PRC_CLAMPV_1, 0) CopyInfo( nPartId, nMainProfileId, WIN_PRC_CLAMPV_2, 0) return nProfileLayerId end --------------------------------------------------------------------- local function GetDeltaProfile( nProfileId, sCtrIn) 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 sCtrIn == WIN_CTRIN .. 1 then dCPDelta = abs( b3CP:getMin():getX()) else dCPDelta = abs( b3CP:getMax():getX()) end -- se bottomrail considero anche scostamento dall'outline local sProfileType = EgtGetInfo( nProfileId, WIN_PRF_TYPE) if sProfileType == WIN_FILL_RAIL then local dDelta = EgtGetInfo( nProfileId, WIN_RAILDELTA, 'd') dCPDelta = dCPDelta + dDelta end return dCPDelta end --------------------------------------------------------------------- -- funzione che crea le curve del geo local function CreateFrameGeo( nOutlineId, vPrevOutlineId, vNextOutlineId, nStartPartJointType, nEndPartJointType, 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_PRF_TYPE) if sProfileType == WIN_FILL_RAIL or sProfileType == WIN_RAIL then -- scostamento extra legato al bottomrail local dDelta = EgtGetInfo( nCurrProfileId, WIN_RAILDELTA, '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) or EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN .. '1') EgtSetInfo( nOutId, WIN_SEMI_PROFILE, nSemiProfileOut) EgtSetInfo( nOutId, WIN_REF_OUTLINE, nOutlineId) -- 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) or EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN .. '2') or EgtGetFirstNameInGroup( nCurrProfileId, WIN_MIXED_COMMON .. WIN_IN) EgtSetInfo( nInId, WIN_SEMI_PROFILE, nSemiProfileIn) EgtSetInfo( nInId, WIN_REF_OUTLINE, nOutlineId) -- curve left local vPrevProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_START) for i = 1, #vPrevOutlineId do local nPrevCurveId local nPrevSemiProfile if nStartPartJointType == WIN_PART_JNT.ANGLED then -- calcolo la bisettrice local vtMedia = ( ( EgtSV( nOutlineId) - EgtEV( abs( vPrevOutlineId[i]))) / 2) if not vtMedia:normalize() then vtMedia = EgtSV( nOutlineId) vtMedia:rotate( Z_AX(), 90) end nPrevCurveId = EgtLinePVL( nGeoLayerId, EgtSP( nOutlineId), vtMedia, 3 * b3CurrProfileFrame:getDimX()) EgtInvertCurve( nPrevCurveId) else nPrevCurveId = EgtCopy( abs( vPrevOutlineId[i]), nGeoLayerId) if vPrevOutlineId[i] < 0 then EgtInvertCurve( nPrevCurveId) end if nStartPartJointType == WIN_PART_JNT.SHORT then local sCtrIn = GetProfileCtrIn( abs( vPrevOutlineId[i]), nOutlineId, vPrevProfileId[i]) local dCPDelta = GetDeltaProfile( vPrevProfileId[i], sCtrIn) EgtOffsetCurve( nPrevCurveId, - dCPDelta) -- ricavo il semiprofilo associato nPrevSemiProfile = EgtGetFirstNameInGroup( vPrevProfileId[i], sCtrIn) else nPrevSemiProfile = EgtGetFirstNameInGroup( vPrevProfileId[i], WIN_OUT) end end EgtSetName( nPrevCurveId, WIN_GEO_LEFT) EgtSetInfo( nPrevCurveId, WIN_SEMI_PROFILE, nPrevSemiProfile) EgtSetInfo( nPrevCurveId, WIN_REF_OUTLINE, vPrevOutlineId[i]) EgtRelocateGlob( nPrevCurveId, nGeoLayerId, GDB_IN.LAST_SON) end -- curve right local vNextProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_END) for i = 1, #vNextOutlineId do local nNextCurveId local nNextSemiProfile if nEndPartJointType == WIN_PART_JNT.ANGLED then -- calcolo la bisettrice local vtMedia = ( ( EgtSV( abs( vNextOutlineId[i])) - EgtEV( nOutlineId)) / 2) if not vtMedia:normalize() then vtMedia = EgtEV( nOutlineId) vtMedia:rotate( Z_AX(), 90) end nNextCurveId = EgtLinePVL( nGeoLayerId, EgtEP( nOutlineId), vtMedia, 3 * b3CurrProfileFrame:getDimX()) else nNextCurveId = EgtCopy( abs( vNextOutlineId[i]), nGeoLayerId) if vNextOutlineId[i] < 0 then EgtInvertCurve( nNextCurveId) end if nEndPartJointType == WIN_PART_JNT.SHORT then local sCtrIn = GetProfileCtrIn( abs( vNextOutlineId[i]), nOutlineId, vNextProfileId[i]) local dCPDelta = GetDeltaProfile( vNextProfileId[i], sCtrIn) EgtOffsetCurve( nNextCurveId, - dCPDelta) -- ricavo il semiprofilo associato nNextSemiProfile = EgtGetFirstNameInGroup( vNextProfileId[i], sCtrIn) else nNextSemiProfile = EgtGetFirstNameInGroup( vNextProfileId[i], WIN_OUT) end end EgtSetName( nNextCurveId, WIN_GEO_RIGHT) EgtSetInfo( nNextCurveId, WIN_SEMI_PROFILE, nNextSemiProfile) EgtSetInfo( nNextCurveId, WIN_REF_OUTLINE, vNextOutlineId[i]) EgtRelocateGlob( nNextCurveId, nInId, GDB_IN.BEFORE) end -- trim delle curve local vIds = EgtGetAllInGroup( nGeoLayerId) local vMainCrvs = TrimOrderedCurves( vIds, 2) -- costruisco la regione local nCompoId = EgtCurveCompo( nGeoLayerId, vMainCrvs, false) local nAreaId = EgtSurfFlatRegion( nGeoLayerId, nCompoId) EgtSetName( nAreaId, WIN_GEO_SURF) EgtSetStatus( nAreaId, GDB_ST.OFF) EgtErase( nCompoId) -- 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 end --------------------------------------------------------------------- -- funzione che calcola l'ingombro dei pezzi del telaio local function CalcFrameGeo( nPartId, nOutlineId, nOutlineCrvNbr, nOutlineLayerId, nProfileType, nBottomRail) -- creo layer per ingombro local nGeoLayerId = EgtGroup( nPartId) EgtSetName( nGeoLayerId, WIN_GEO) -- recupero outline precedenti e successivi ( solo nel caso di split possono essere più di uno) local vPrevOutlineId, vNextOutlineId = GetPrevNextOutline( nProfileType, nOutlineId, nOutlineLayerId) EgtSetInfo( nOutlineId, WIN_PREV_OUTLINES, vPrevOutlineId) EgtSetInfo( nOutlineId, WIN_NEXT_OUTLINES, vNextOutlineId) -- recupero il tipo di giunzioni local nStartJointType local nEndJointType local nProfileTypeS = nProfileType local nProfileTypeE = nProfileType if nProfileType == WIN_PRF.SPLIT or nProfileType == WIN_PRF.BOTTOMRAIL or nProfileType == WIN_PRF.BOTTOMRAIL_FINAL then -- non serve settare dei valori per StartJointType ed EndJointType perchè in CalcPartJointType la loro giunzione viene settata a short else -- recupero i joints opportuni dal vettore local vJoints = EgtGetInfo( nOutlineLayerId, WIN_JOINTS, 'vi') if EgtGetName( nOutlineId) == WIN_BOTTOM then nStartJointType = vJoints[1] nEndJointType = vJoints[2] elseif EgtGetName( nOutlineId) == WIN_RIGHT then nStartJointType = vJoints[2] nEndJointType = vJoints[3] elseif EgtGetName( nOutlineId) == WIN_TOP then nStartJointType = vJoints[3] nEndJointType = vJoints[4] -- correzioni per caso a triangolo if EgtGetName( abs( vPrevOutlineId[#vPrevOutlineId])) == WIN_BOTTOM then nStartJointType = vJoints[2] nEndJointType = vJoints[3] -- il lato top deve essere trattato come un left/right nel calcolo della giunzione nProfileTypeS = WIN_PRF.LEFT end if EgtGetName( abs( vNextOutlineId[1])) == WIN_BOTTOM then nStartJointType = vJoints[3] nEndJointType = vJoints[1] nProfileTypeE = WIN_PRF.LEFT end elseif EgtGetName( nOutlineId) == WIN_LEFT then nStartJointType = vJoints[4] or vJoints[3] -- ( vJoints[3] per gestire caso a triangolo) nEndJointType = vJoints[1] end -- se giunzione diversa da bisettrice e arco a tutto sesto oppure elementi entrambi dello stesso tipo, forzo il tipo a bisettrice if nStartJointType ~= WIN_JNT.ANGLED and ( AreSameVectorApprox( EgtEV( abs( vPrevOutlineId[1])), EgtSV( nOutlineId)) or EgtGetName( nOutlineId) == EgtGetName( abs( vPrevOutlineId[1]))) then nStartJointType = WIN_JNT.ANGLED end if nEndJointType ~= WIN_JNT.ANGLED and ( AreSameVectorApprox( EgtEV( nOutlineId), EgtSV( abs( vNextOutlineId[1]))) or EgtGetName( nOutlineId) == EgtGetName( abs( vNextOutlineId[1]))) then nEndJointType = WIN_JNT.ANGLED end end -- calcolo il tipo di giunzione per la parte local nStartPartJointType = CalcPartJointType( nProfileTypeS, nStartJointType) local nEndPartJointType = CalcPartJointType( nProfileTypeE, nEndJointType) -- nel caso di incontro con soglia la giunzione deve essere full if EgtGetInfo( abs( vPrevOutlineId[1]), WIN_THRESHOLD, 'b') then nStartPartJointType = WIN_JNT.FULL end if EgtGetInfo( abs( vNextOutlineId[1]), WIN_THRESHOLD, 'b') then nEndPartJointType = WIN_JNT.FULL end -- salvo il valore dei joints su outline -- se bottomrail è sicuramente short quindi non salvo il valore che sovrascriverebbe quello del pezzo bottom ( che potrebbe essere short o full) if nProfileType ~= WIN_PRF.BOTTOMRAIL and nProfileType ~= WIN_PRF.BOTTOMRAIL_FINAL then EgtSetInfo( nOutlineId, WIN_STARTJOINT, nStartPartJointType) EgtSetInfo( nOutlineId, WIN_ENDJOINT, nEndPartJointType) end -- creo il gruppo con i profili del pezzo local nProfileLayerId = CalcProfiles( nPartId, nOutlineId, vPrevOutlineId, vNextOutlineId, nProfileType, nBottomRail) -- creo lati dell'outline CreateFrameGeo( nOutlineId, vPrevOutlineId, vNextOutlineId, nStartPartJointType, nEndPartJointType, nGeoLayerId, nProfileLayerId) 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 ----------------------------- ---------------------------------------------------------------------------------- -- funzione che individua e crea i diversi tratti uniformi della curva di outline local function CalcMixedOutlines( nPartId, nOutlineId) -- creo gruppo dove salvare i sottotratti local nGrp = EgtGroup( nPartId) EgtSetName( nGrp, WIN_MIXED_OUTLINES) EgtSetStatus( nGrp, GDB_ST.OFF) -- recupero i tratti di tipo sash e li concateno local vSashChildren = EgtGetInfo( nOutlineId, WIN_SASH_CHILDREN, 'vi') local vSash = {} for i = 1, #vSashChildren do local nCrv = EgtCopyGlob( vSashChildren[i], nGrp) table.insert( vSash, nCrv) end local nCrvS, nCntS = EgtCurveCompoByReorder( nGrp, vSash, EgtSP( nOutlineId)) for nId = nCrvS, nCrvS + nCntS - 1 do -- da curva compo ricavo la curva linea/arco corrispondente EgtMergeCurvesInCurveCompo( nId) local nNewId = EgtExplodeCurveCompo( nId) EgtSetName( nNewId, WIN_SASH) end -- recupero i tratti di tipo fill e li concateno local vFillChildren = EgtGetInfo( nOutlineId, WIN_FILL_CHILDREN, 'vi') local vFill = {} for i = 1, #vFillChildren do local nCrv = EgtCopyGlob( vFillChildren[i], nGrp) table.insert( vFill, nCrv) end local nCrvF, nCntF = EgtCurveCompoByReorder( nGrp, vFill, EgtSP( nOutlineId)) for nId = nCrvF, nCrvF + nCntF - 1 do EgtMergeCurvesInCurveCompo( nId) local nNewId = EgtExplodeCurveCompo( nId) EgtSetName( nNewId, WIN_FILL) end -- riordino le curve nel gruppo per ricostruire l'outline EgtReorderCurvesInGroup( nGrp, EgtSP( nOutlineId)) -- creo associazione tra le sottocurve di outline e gli split che le separano : -- recupero tutti gli split coinvolti local nBaseOutline = EgtGetInfo( nOutlineId, WIN_COPY, 'i') local vStack = { nBaseOutline} local vSplitIds = {} local i = 1 while vStack[i] do -- recupero il tipo di area local nAreaId = EgtGetParent( EgtGetParent( vStack[i])) local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i') if nAreaType ~= WIN_AREATYPES.SASH and nAreaType ~= WIN_AREATYPES.FILL then -- salvo i suo eventuali split mixed local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) if nSplitLayerId then local vCurrSplits = EgtGetAllInGroup( nSplitLayerId) for j = 1, #vCurrSplits do if EgtGetInfo( vCurrSplits[j], WIN_SPLITTYPE, 'i') == WIN_SPLITTYPES.MIXED then table.insert( vSplitIds, vCurrSplits[j]) end end end -- analizzo eventuali figli local vChildren = EgtGetInfo( vStack[i], WIN_CHILD, 'vi') or {} vStack = EgtJoinTables( vStack, vChildren) end i = i + 1 end -- associo le curve con lo split che le taglia nel loro punto finale local vCrvs = EgtGetAllInGroup( nGrp) for i = 1, #vSplitIds do local ptS = EgtSP( vSplitIds[i]) local ptE = EgtEP( vSplitIds[i]) for j = 1, #vCrvs - 1 do local ptTest = EgtEP( vCrvs[j]) if AreSamePointApprox( ptS, ptTest) then EgtSetInfo( vSplitIds[i], WIN_MIXED_REF_START, vCrvs[j]) EgtSetInfo( vCrvs[j], WIN_MIXED_SPLIT_REF, vSplitIds[i]) break elseif AreSamePointApprox( ptE, ptTest) then EgtSetInfo( vSplitIds[i], WIN_MIXED_REF_END, vCrvs[j]) EgtSetInfo( vCrvs[j], WIN_MIXED_SPLIT_REF, vSplitIds[i]) break end end end return nGrp end --------------------------------------------------------------------- -- funzione che crea la curva di riferimento sulla giunzione tra il pezzo di split e il pezzo di telaio con cambio profilo local function CalcMixedIntersections( nPartId, nOutline, vOutlines) local nGrp = EgtGroup( nPartId) EgtSetName( nGrp, WIN_MIXED_INTERSECTIONS) EgtSetStatus( nGrp, GDB_ST.OFF) -- recupero il profilo dell'outline local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE) local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN) for i = 1, #vOutlines - 1 do -- recupero la curva di split che separa i due tratti di outline local nSplitId = EgtGetInfo( vOutlines[i], WIN_MIXED_SPLIT_REF, 'i') local nSplitProfileId = GetOutlineProfileId( nSplitId, false) -- verifico ordinamento local bSashFill = ( EgtGetName( vOutlines[i]) == WIN_SASH) -- ricavo il punto di incontro tra le due parti dei profili che vanno contro il vetro local nCrv1 = EgtCopyGlob( nSplitId, nGrp) local dDeltaFixedSplit = EgtGetInfo( nSplitProfileId, WIN_FIXED_REF, 'd') EgtOffsetCurve( nCrv1, dDeltaFixedSplit) local nCrv2 = EgtCopyGlob( nOutline, nGrp) local dDeltaFixedFrame = EgtGetInfo( nMainProfileId, WIN_FIXED_REF, 'd') EgtOffsetCurve( nCrv2, - dDeltaFixedFrame) local ptRef1 = EgtIP( nCrv1, nCrv2, ORIG()) -- ricavo il punto di incontro tra il taglio a 45° e la parte del telaio contro anta -- TO DO : capire come gestire correttamente la rotazione nel caso di arco local dParRef = EgtCurveParamAtPoint( nCrv2, ptRef1) local vtDir45 = EgtUV( nCrv2, dParRef, -1) vtDir45:rotate( Z_AX(), EgtIf( bSashFill, 225, -45)) local nCrv3 = EgtLinePVL( nGrp, ptRef1, vtDir45, 100) local nCrv4 = EgtCopyGlob( nOutline, nGrp) local dDeltaSashFrame = EgtGetInfo( nMainProfileId, WIN_SASH_REF .. '1', 'd') EgtOffsetCurve( nCrv4, - dDeltaSashFrame) local ptRef2 = EgtIP( nCrv3, nCrv4, ORIG()) -- curva di intersezione da usare come riferimento per i conti successivi local nCrv = EgtCurveCompoFromPoints( nGrp, { ptRef1, ptRef2}) -- calcolo il raccordo local dRad = EgtGetInfo( nMainProfileId, WIN_RAD_REF .. '1', 'd') local dParFillet = EgtCurveParamAtPoint( nCrv4, ptRef2) dParFillet = dParFillet + EgtIf( bSashFill, -10, 10) * GEO.EPS_SMALL local nFillet = EgtCurveFillet( nGrp, nCrv, EgtUP( nCrv1, 0.9), nCrv4, EgtUP( nCrv4, dParFillet), dRad, true) or GDB_ID.NULL EgtAddCurveCompoCurve( nCrv, nFillet) -- cancello curve di costruzione EgtErase( { nCrv1, nCrv2, nCrv3, nCrv4}) -- assegno riferimento EgtSetInfo( vOutlines[i], WIN_MIXED_INTERS_REF, nCrv) end end --------------------------------------------------------------------- -- funzione che calcola curve ausiliarie per la gestione del cambio profilo local function CalcMixedFrameCurves( nPartId, nOutlineId) -- calcolo i sottotratti uniformi della curva di outline local nOutlinesGrp = CalcMixedOutlines( nPartId, nOutlineId) local vCrvs = EgtGetAllInGroup( nOutlinesGrp) -- calcolo le curve di intersezione con gli split CalcMixedIntersections( nPartId, nOutlineId, vCrvs) 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 else -- se non ha semiprofilo associato è un taglio EgtSetInfo( nCrv, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.CUT) end end --------------------------------------------------------------------- -- funzione che calcola la prima lavorazione per l'innesto dello split sul telaio nel caso di cambio profilo local function CalcMixedFrameMilling1( nIntersCrv, nOutlineId, nMainProfileId, nSplitRef, bSashFill, nProcLayerId, nSurfGeoId) local dOffs = EgtGetInfo( nMainProfileId, WIN_SASH_REF .. '1', 'd') local dDepth = EgtGetInfo( nMainProfileId, WIN_SASH_DEPTH .. '1', 'd') local dFilletRad = EgtGetInfo( nMainProfileId, WIN_RAD_REF .. '1', 'd') -- primo tratto : taglio a 45° e fillet local nCrv1 = EgtCopyGlob( nIntersCrv, nProcLayerId) EgtExtendCurveStartByLen( nCrv1, 100) -- calcolo il tratto di outline local nCrv2 = EgtCopyGlob( nOutlineId, nProcLayerId) EgtOffsetCurve( nCrv2, - dOffs) if bSashFill then EgtInvertCurve( nCrv2) end local dParS = EgtCurveParamAtPoint( nCrv2, EgtEP( nCrv1)) local ptEnd = EgtIP( nCrv2, nSplitRef, ORIG()) local dParE = EgtCurveParamAtPoint( nCrv2, ptEnd) EgtTrimCurveStartEndAtParam( nCrv2, dParS, dParE) -- tratto di uscita a 45° local vtDir2 = EgtEV( nCrv2) vtDir2:rotate( Z_AX(), EgtIf( bSashFill, - 45, 45)) local nCrv3 = EgtLinePVL( nProcLayerId, ptEnd, vtDir2, 100) -- creo fillet local nFillet = EgtCurveFillet( nProcLayerId, nCrv2, EgtUP( nCrv2, 0.9), nCrv3, EgtUP( nCrv3, 0.1), dFilletRad, true) -- creo curva di lavorazione local nMillingCrv = EgtCurveCompo( nProcLayerId, {nCrv1, nCrv2, nFillet, nCrv3}) if bSashFill then EgtInvertCurve( nMillingCrv) end EgtModifyCurveThickness( nMillingCrv, - dDepth) -- setto info di lavorazione EgtSetInfo( nMillingCrv, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING) EgtSetInfo( nMillingCrv, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC) EgtSetInfo( nMillingCrv, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.IN) EgtTrimCurveWithRegion( nMillingCrv, nSurfGeoId, true, false) end --------------------------------------------------------------------- -- funzione che calcola la seconda lavorazione per l'innesto dello split sul telaio nel caso di cambio profilo local function CalcMixedFrameMilling2( nIntersCrv, nOutlineId, nMainProfileId, nSplitProfileId, nSplitRef, bSashFill, nProcLayerId, nSurfGeoId) local dOffs = EgtGetInfo( nMainProfileId, WIN_SASH_REF .. '2', 'd') local dDepth = EgtGetInfo( nMainProfileId, WIN_SASH_DEPTH .. '2', 'd') local dFilletRad = EgtGetInfo( nMainProfileId, WIN_RAD_REF .. '2', 'd') local dExtraDist = EgtGetInfo( nMainProfileId, WIN_EXTRA_DIST, 'd') local nCrv1 = EgtCopyGlob( nIntersCrv, nProcLayerId) EgtExtendCurveStartByLen( nCrv1, 100) -- calcolo il primo tratto di outline local nCrv2 = EgtCopyGlob( nOutlineId, nProcLayerId) EgtOffsetCurve( nCrv2, - dOffs + dExtraDist) if bSashFill then EgtInvertCurve( nCrv2) end -- taglio i due tratti per unirli local pt1 = EgtIP( nCrv1, nCrv2, ORIG()) local dParE1 = EgtCurveParamAtPoint( nCrv1, pt1) EgtTrimCurveEndAtParam( nCrv1, dParE1) local dParS2 = EgtCurveParamAtPoint( nCrv2, pt1) EgtTrimCurveStartAtParam( nCrv2, dParS2) -- calcolo fillet local nFillet1 = EgtCurveFillet( nProcLayerId, nCrv1, EgtUP( nCrv1, 0.9), nCrv2, EgtUP( nCrv2, 0.1), dFilletRad, true) -- calcolo il secondo tratto di outline local nCrv3 = EgtCopyGlob( nOutlineId, nProcLayerId) EgtOffsetCurve( nCrv3, - dOffs) if bSashFill then EgtInvertCurve( nCrv3) end local nSplitRef2 = EgtCopyGlob( nSplitRef, nProcLayerId) local dOffs1 = EgtGetInfo( nSplitProfileId, WIN_SASH_REF .. '1', 'd') local dOffs2 = EgtGetInfo( nSplitProfileId, WIN_SASH_REF .. '2', 'd') EgtOffsetCurve( nSplitRef2, dOffs2 - dOffs1) local pt2 = EgtIP( nCrv3, nSplitRef2, ORIG()) local pt3 = EgtIP( nCrv3, nSplitRef, ORIG()) local dParS3 = EgtCurveParamAtPoint( nCrv3, pt2) local dParE3 = EgtCurveParamAtPoint( nCrv3, pt3) EgtTrimCurveStartEndAtParam( nCrv3, dParS3, dParE3) EgtErase( nSplitRef2) -- calcolo il raccordo tra i due tratti di outline : è arco di raggio dFilletRad, tangente a nCrv2 e con punto finale pt2 -- calcolo il centro dell'arco local nCircleTmp = EgtCircle( nProcLayerId, pt2, dFilletRad) local nCrvTmp = EgtCopyGlob( nOutlineId, nProcLayerId) EgtOffsetCurve( nCrvTmp, - dOffs + dExtraDist - dFilletRad) local ptC = EgtIP( nCircleTmp, nCrvTmp, EgtIf( bSashFill, EgtEP( nCrvTmp), EgtSP( nCrvTmp))) EgtErase( {nCircleTmp, nCrvTmp}) local nFillet2 = EgtArcC2PEx( nProcLayerId, ptC, EgtSP( nCrv2), GDB_PT.TG, nCrv2, pt2) -- taglio il primo tratto di outline per collegarlo al raccordo local dParE2 = EgtCurveParamAtPoint( nCrv2, EgtSP( nFillet2)) EgtTrimCurveEndAtParam( nCrv2, dParE2) -- tratto di uscita a 45° local vtDir2 = EgtEV( nCrv3) vtDir2:rotate( Z_AX(), EgtIf( bSashFill, - 45, 45)) local nCrv4 = EgtLinePVL( nProcLayerId, EgtEP( nCrv3), vtDir2, 100) -- creo fillet local nFillet3 = EgtCurveFillet( nProcLayerId, nCrv3, EgtUP( nCrv3, 0.9), nCrv4, EgtUP( nCrv4, 0.1), dFilletRad, true) or GDB_ID.NULL -- creo curva di lavorazione local nMillingCrv = EgtCurveCompo( nProcLayerId, {nCrv1, nFillet1, nCrv2, nFillet2, nCrv3, nFillet3, nCrv4}) if bSashFill then EgtInvertCurve( nMillingCrv) end EgtModifyCurveThickness( nMillingCrv, - dDepth) -- setto info di lavorazione EgtSetInfo( nMillingCrv, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING) EgtSetInfo( nMillingCrv, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC) EgtSetInfo( nMillingCrv, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.IN) EgtTrimCurveWithRegion( nMillingCrv, nSurfGeoId, true, false) 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 vGeoCrvs = EgtGetAllInGroup( nGeoLayerId) for i = 1, #vGeoCrvs - 1 do -- copio curva local nCrv = EgtCopyGlob( vGeoCrvs[i], nProcLayerId) EgtModifyCurveThickness( nCrv, 0) -- recupero il semiprofilo associato local nSemiProfile = EgtGetInfo( nCrv, WIN_SEMI_PROFILE, 'i') GetProcessingInfoFromSemiProfile( nCrv, nSemiProfile) end -- lavorazioni dei sottotratti in di sash e fill local nOutlinesGrp = EgtGetFirstNameInGroup( nPartId, WIN_MIXED_OUTLINES) local vCrvs = EgtGetAllInGroup( nOutlinesGrp) local b3Profile = GetProfileLocalBox( nMainProfileId) local dOffs = b3Profile:getMin():getX() for i = #vCrvs, 1, -1 do -- calcolo la curva di lavorazione local nCrv = EgtCopyGlob( vCrvs[i], nProcLayerId) EgtOffsetCurve( nCrv, dOffs) EgtInvertCurve( nCrv) nCrv = EgtTrimCurveWithRegion( nCrv, nSurfGeoId, true, true) -- setto le info di lavorazione dal semiprofilo local nSemiProfile = EgtGetFirstNameInGroup( nMainProfileId, EgtGetName( vCrvs[i]) .. WIN_IN) GetProcessingInfoFromSemiProfile( nCrv, nSemiProfile) -- sistemo info di lavorazione EgtSetInfo( nCrv, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.MIXED) EgtSetInfo( nCrv, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.IN) -- TO DO : calcolo di AddLen ? end -- b) lavorazioni sulle intersezioni con gli split local nIntersGrp = EgtGetFirstNameInGroup( nPartId, WIN_MIXED_INTERSECTIONS) local vInters = EgtGetAllInGroup( nIntersGrp) local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i') for i = 1, #vInters do local bSashFill = ( EgtGetName( vCrvs[i]) == WIN_SASH) -- recupero lo split associato e creo la curva di riferimento per le fresature local nSplitId = EgtGetInfo( vCrvs[i], WIN_MIXED_SPLIT_REF, 'i') local nSplitProfileId = GetOutlineProfileId( nSplitId, false) local dRefSplit = EgtGetInfo( nSplitProfileId, WIN_SASH_REF .. '2', 'd') local nSplitRef = EgtCopyGlob( nSplitId, nProcLayerId) EgtOffsetCurve( nSplitRef, - dRefSplit) -- Fresatura 1 CalcMixedFrameMilling1( vInters[i], nOutlineId, nMainProfileId, nSplitRef, bSashFill, nProcLayerId, nSurfGeoId) -- Fresatura 2 CalcMixedFrameMilling2( vInters[i], nOutlineId, nMainProfileId, nSplitProfileId, nSplitRef, bSashFill, nProcLayerId, nSurfGeoId) EgtErase( nSplitRef) end end --------------------------------------------------------------------- -- funzione che calcola le lavorazioni di profiling nel caso di uno split coinvolto da cambio profilo local function CalcMixedSplitProfilingProcessings( nSplitId, nProcLayerId, nGeoLayerId) -- a) lavorazione dei profili local vGeoCrvs = EgtGetAllInGroup( nGeoLayerId) for i = 1, #vGeoCrvs - 1 do -- copio la curva local nCrvId = EgtCopyGlob( vGeoCrvs[i], nProcLayerId) EgtModifyCurveThickness( nCrvId, 0) -- recupero il semiprofilo associato ( per left e right è stato salvato il profilo di tipo sash) local nSemiProfileId = EgtGetInfo( nCrvId, WIN_SEMI_PROFILE, 'i') -- setto le info dal semiprofilo GetProcessingInfoFromSemiProfile( nCrvId, nSemiProfileId) end -- b) tagli a 45° -- left local nMixedLeft = EgtGetInfo( nSplitId, WIN_MIXED_REF_START, 'i') local nIntersLeft = EgtGetInfo( nMixedLeft, WIN_MIXED_INTERS_REF, 'i') local nMillingLeft = EgtCopyGlob( nIntersLeft, nProcLayerId) -- recupero profondità local vOutlineLeft = EgtGetInfo( nSplitId, WIN_PREV_OUTLINES, 'vi') local nProfileLeft = GetOutlineProfileId( abs( vOutlineLeft[1]), false) local dDepthLeft = EgtGetInfo( nProfileLeft, WIN_SASH_DEPTH .. '2', 'd') EgtModifyCurveThickness( nMillingLeft, - dDepthLeft) -- setto info di lavorazione EgtSetInfo( nMillingLeft, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING) EgtSetInfo( nMillingLeft, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC) EgtSetInfo( nMillingLeft, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.LEFT) -- right local nMixedRight = EgtGetInfo( nSplitId, WIN_MIXED_REF_END, 'i') local nIntersRight = EgtGetInfo( nMixedRight, WIN_MIXED_INTERS_REF, 'i') local nMillingRight = EgtCopyGlob( nIntersRight, nProcLayerId) -- recupero profondità local vOutlineRight = EgtGetInfo( nSplitId, WIN_NEXT_OUTLINES, 'vi') local nProfileRight = GetOutlineProfileId( abs( vOutlineRight[1]), false) local dDepthRight = EgtGetInfo( nProfileRight, WIN_SASH_DEPTH .. '2', 'd') EgtModifyCurveThickness( nMillingRight, - dDepthRight) EgtInvertCurve( nMillingRight) -- setto info di lavorazione EgtSetInfo( nMillingRight, WIN_PRC_FEATURE_TYPE, WIN_PRC_TYPE.PROFILING) EgtSetInfo( nMillingRight, WIN_PRC_PROFILE_INFO, WIN_PRC_PROFILE_TYPE.GENERIC) EgtSetInfo( nMillingRight, WIN_PRC_SIDE, WIN_PRC_SIDETYPE.RIGHT) end --------------------------------------------------------------------- -- funzione che aggiusta le lunghezze delle lavorazioni per garantire lavorazione completa del profilo local function AdjustProcessingLength( nCrvId, nSemiProfileId, nGeoAreaId, nPrevGeo, nNextGeo) -- se giunzione angled non serve allungamento if not nSemiProfileId then return end -- calcolo la curva di lavorazione interna 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, GDB_RT.GLOB) local dOffs = b3SemiProfile:getDimX() local nInnerProcId = EgtCopyGlob( nCrvId, EgtGetParent( nCrvId)) EgtOffsetCurve( nInnerProcId, - dOffs) -- adatto la curva di lavorazione interna al pezzo if EgtGetType( nInnerProcId) == GDB_TY.CRV_LINE then EgtExtendCurveStartByLen( nInnerProcId, 10000) EgtExtendCurveEndByLen( nInnerProcId, 10000) else local dAng = EgtArcAngCenter( nInnerProcId) EgtModifyArcAngCenter( nInnerProcId, EgtIf( dAng > 0, 1, -1) * 360) end local nNewId, nCnt = EgtTrimCurveWithRegion( nInnerProcId, nGeoAreaId, true, false) if nCnt == 0 then return end if nCnt > 1 then -- nel caso di archi possono generarsi più intersezioni quindi va conservata solo quella corretta -- TODO può capitare anche nel caso in/out? if AreSamePointApprox( EgtSP( nNewId), EgtEP( nNewId + nCnt - 1)) then EgtModifyCurveStartPoint( nNewId, EgtSP( nNewId + nCnt - 1)) EgtErase( nNewId + nCnt - 1) nCnt = nCnt - 1 end local nPrcOutId = EgtGetFirstNameInGroup( EgtGetParent( nGeoAreaId), WIN_GEO_OUT) local ptRef = EgtIf( EgtGetName( nCrvId) == WIN_LEFT, EgtSP( nPrcOutId), EgtEP( nPrcOutId)) local nIdRef local dSqMinDist = GEO.INFINITO for nId = nNewId, nNewId + nCnt - 1 do local ptTest = EgtIf( EgtGetName( nCrvId) == WIN_LEFT, EgtEP( nId), EgtSP( nId)) local dSqDist = sqdist( ptTest, ptRef) if dSqDist < dSqMinDist then dSqMinDist = dSqDist nIdRef = nId end end for nId = nNewId, nNewId + nCnt - 1 do if nId ~= nIdRef then EgtErase( nId) end end nNewId = nIdRef end -- la allineo alla curva di lavoro EgtOffsetCurve( nNewId, dOffs) -- aggiusto la curva di lavoro local ptS = EgtSP( nNewId) local ptE = EgtEP( nNewId) local bExtra = EgtGetInfo( nCrvId, WIN_GEO_EXTRA, 'b') or false if bExtra then -- se è una curva speciale del geo va modificata su entrambi gli estremi EgtModifyCurveStartPoint( nCrvId, ptS) EgtModifyCurveEndPoint( nCrvId, ptE) else -- se è una curva standard va modificata solo in allungamento se non è in tangenza con quella vicina local dParS = EgtCurveParamAtPoint( nCrvId, ptS) local bTang = AreSameVectorApprox( EgtSV( nCrvId), EgtEV( nPrevGeo)) if not dParS and not bTang then EgtModifyCurveStartPoint( nCrvId, ptS) end bTang = AreSameVectorApprox( EgtEV( nCrvId), EgtSV( nNextGeo)) local dParE = EgtCurveParamAtPoint( nCrvId, ptE) if not dParE and not bTang then EgtModifyCurveEndPoint( nCrvId, ptE) end end EgtErase( nNewId) 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 creo la superficie associata per limitare le lavorazioni local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO) local nSurfGeo = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_SURF) -- 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 bChangeProfile = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'b') or false if bChangeProfile then -- 1) caso cambio profilo : telaio o split if EgtGetName( nOutlineId) == WIN_SPLIT then CalcMixedSplitProfilingProcessings( nOutlineId, nProcLayerId, nGeoLayerId) else CalcMixedFrameProfilingProcessings( nPartId, nProcLayerId, nGeoLayerId, nMainProfileId, nSurfGeo) end else -- 2) caso standard -- recupero tutte le curve del geo e le copio nel gruppo processings local vGeoCrvs = EgtGetAllInGroup( nGeoLayerId) for i = 1, #vGeoCrvs - 1 do -- copio curva local nCrvId = EgtCopyGlob( vGeoCrvs[i], nProcLayerId) EgtModifyCurveThickness( nCrvId, 0) -- recupero il semiprofilo associato local nSemiProfileId = EgtGetInfo( nCrvId, WIN_SEMI_PROFILE, 'i') -- aggiusto la lunghezza della lavorazione local nPrevIdx = EgtIf( i == 1, #vGeoCrvs - 1, i - 1) local nNextIdx = EgtIf( i == #vGeoCrvs - 1, 1, i + 1) AdjustProcessingLength( nCrvId, nSemiProfileId, nSurfGeo, vGeoCrvs[nPrevIdx], vGeoCrvs[nNextIdx]) -- setto le info dal semiprofilo GetProcessingInfoFromSemiProfile( nCrvId, nSemiProfileId) end end -- calcolo eventuali lavorazioni per strip local vStripDist = EgtGetInfo( nMainProfileId, WIN_STRIP_DIST, 'vi') or {} for i = 1, #vStripDist do local nStripCut = EgtCopyGlob( nOutlineId, nProcLayerId) EgtOffsetCurve( nStripCut, vStripDist[i]) -- modifico la curva in modo che sia a filo del geo EgtExtendCurveStartByLen( nStripCut, 1000) EgtExtendCurveEndByLen( nStripCut, 1000) nStripCut = EgtTrimCurveWithRegion( nStripCut, nSurfGeo, true, false) -- 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 nBaseOutlineId = EgtGetInfo( nOutlineId, WIN_COPY, 'i') local bOnFrenchSplit = EgtGetInfo( nBaseOutlineId, 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) 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 local bExtra = EgtGetInfo( vRight[i], WIN_GEO_EXTRA, 'b') or false if bExtra then EgtErase( vRight[i]) else if not EgtOffsetCurve( vRight[i], dOvermatRight) then EgtErase( vRight[i]) end end end local vLeft = EgtGetNameInGroup( nGeoRawLayerId, WIN_GEO_LEFT) for i = 1, #vLeft do local bExtra = EgtGetInfo( vLeft[i], WIN_GEO_EXTRA, 'b') or false if bExtra then EgtErase( vLeft[i]) else if not EgtOffsetCurve( vLeft[i], dOvermatLeft) then EgtErase( vLeft[i]) end end end -- creo la composita del grezzo a partire dalle curve local vCrvs = EgtGetAllInGroup( nGeoRawLayerId) vCrvs = TrimOrderedCurves( vCrvs) local nCompo = EgtCurveCompo( nGeoRawLayerId, vCrvs) -- aggiungo spessore local dDimH = EgtGetInfo( nGeoLayerId, WIN_GEOHEIGHT, 'd') EgtModifyCurveThickness( nCompo, - dDimH) -- creo 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 ---------------------------------------------------------------------------------- ---------------------------------- SOLIDO ---------------------------------------- ---------------------------------------------------------------------------------- -- funzione che crea la superficie di trim per il solido local function CreateTrimSurf( nGeoId, nOutlineId, dGeoWidth, nLayerId) -- recupero profilo di riferimento dalla curva geo local nOrigTrimProfileId = EgtGetInfo( nGeoId, WIN_SEMI_PROFILE, 'i') -- 1) minizinken if not nOrigTrimProfileId then local nGuideId = EgtCopy( nGeoId, nLayerId) EgtExtendCurveStartByLen( nGuideId, 4 * dGeoWidth) EgtExtendCurveEndByLen( nGuideId, 4 * dGeoWidth) EgtMove( nGuideId, Z_AX()) local nTrimSurf = EgtSurfTmByExtrusion( nLayerId, nGuideId, - Z_AX() * dGeoWidth * 2, WIN_SURF_APPROX) EgtInvertSurf( nTrimSurf) EgtErase( nGuideId) return nTrimSurf -- 2) controprofilo else -- recupero il controprofilo da estrudere local sTrimProfileName = EgtGetName( nOrigTrimProfileId) sTrimProfileName = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_OFST .. sTrimProfileName -- calcolo la superficie di estrusione return CreateProfileSurf( nOutlineId, EgtGetParent( nOrigTrimProfileId), sTrimProfileName, 4 * dGeoWidth, nLayerId) end end --------------------------------------------------------------------- -- funzione che crea le superfici di trim per uno split coinvolto da cambio profilo ( controprofilo della parte sash del telaio e taglio a 45°) local function CreateMixedSplitTrimSurf( nMixedOutlineId, nProfileId, dExtraLen, nLayerId) -- estrudo il controprofilo di tipo sash local nPartId = EgtGetParent( EgtGetParent( nMixedOutlineId)) local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i') local sTrimProfile = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_OFST .. WIN_SASH .. WIN_CTRIN local nTrimStmId = CreateProfileSurf( nOutlineId, nProfileId, sTrimProfile, dExtraLen, nLayerId) -- creo il solido da intersecare con il controprofilo per il taglio a 45° local nIntersCrvId = EgtGetInfo( nMixedOutlineId, WIN_MIXED_INTERS_REF, 'i') local nGuideId = EgtCopyGlob( nIntersCrvId, nLayerId) local bSashFill = ( EgtGetName( nMixedOutlineId) ~= WIN_SASH) local vtDirH = EgtSV( nGuideId) vtDirH:rotate( Z_AX(), EgtIf( bSashFill, -135, 135)) local vtDirV = EgtSV( nGuideId) vtDirV:rotate( Z_AX(), EgtIf( bSashFill, -45, 45)) EgtAddCurveCompoLine( nGuideId, EgtEP( nGuideId) + dExtraLen * vtDirV) EgtAddCurveCompoLine( nGuideId, EgtSP( nGuideId) + dExtraLen * vtDirH, false) EgtAddCurveCompoLine( nGuideId, EgtSP( nGuideId) + dExtraLen * vtDirV, false) EgtCloseCurveCompo( nGuideId) EgtMove( nGuideId, 0.01 * Z_AX()) if bSashFill then EgtInvertCurve( nGuideId) end local dDepth = EgtGetInfo( nProfileId, WIN_SASH_DEPTH .. '2', 'd') local nCutStmId = EgtSurfTmByRegionExtrusion( nLayerId, nGuideId, - ( dDepth + 2) * Z_AX()) -- creo una superficie di trim unica EgtSurfTmSubtract( nTrimStmId, nCutStmId) EgtErase( { nGuideId, nCutStmId}) return nTrimStmId end --------------------------------------------------------------------- -- funzione che crea il solido di estrusione principale local function CreateMainSurf( nOutlineId, dExtraLen, nProfileId, sSectionName, nLayerId) -- curva guida local nGuideId = EgtCopy( nOutlineId, nLayerId) EgtSetName( nGuideId, WIN_MAINGUIDE) EgtSetStatus( nGuideId, GDB_ST.OFF) EgtExtendCurveStartByLen( nGuideId, dExtraLen) EgtExtendCurveEndByLen( nGuideId, dExtraLen) -- se bottomrail sposto opportunamente l'outline local sProfileType = EgtGetInfo( nProfileId, WIN_PRF_TYPE) if sProfileType == WIN_RAIL or sProfileType == WIN_FILL_RAIL then local dOffs = EgtGetInfo( nProfileId, WIN_RAILDELTA, 'd') EgtOffsetCurve( nGuideId, -dOffs) end -- posiziono il profilo sulla curva guida : -- recupero il frame del profilo local nProfileFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME) local frInvert = EgtFR( nProfileFrameId) frInvert:invert() -- lo applico a tutte le geometrie del profilo EgtTransform( EgtGetAllInGroup( nProfileId), frInvert) -- assegno come riferimento del profilo il punto start dell'outline EgtChangeGroupFrame( nProfileId, Frame3d( EgtSP( nGuideId), - EgtSV( nGuideId))) -- recupero outline del profilo Main e lo estrudo local nSectionId = EgtGetFirstNameInGroup( nProfileId, sSectionName) local nMainExtrusionId = EgtSurfTmSwept( nLayerId, nSectionId, nGuideId, false, WIN_SURF_APPROX) EgtSetName( nMainExtrusionId, WIN_SRF_MAIN) return nMainExtrusionId end --------------------------------------------------------------------- -- funzione che crea il solido di un pezzo di telaio con cambio profilo local function CalcMixedFrameSolid( nOutlineId, nSolidLayerId, nProfileLayerId, nGeoLayerId, dGeoWidth) -- a) SOLIDO PRINCIPALE local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN) -- creo i solidi corrispondenti ai diversi sottotratti uniformi del pezzo local nMixedOutlinesGrp = EgtGetFirstNameInGroup( EgtGetParent( nSolidLayerId), WIN_MIXED_OUTLINES) local vMixedOutlines = EgtGetAllInGroup( nMixedOutlinesGrp) local vMainExtrusions = {} for i = 1, #vMixedOutlines do local sSection = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. EgtGetName( vMixedOutlines[i]) .. WIN_SECTION local nMainExtrusionId = CreateMainSurf( vMixedOutlines[i], 2 * dGeoWidth, nMainProfileId, sSection, nSolidLayerId) table.insert( vMainExtrusions, nMainExtrusionId) end -- taglio i sottopezzi nei punti di intersezione per unirli local nMixedIntersectionsGrp = EgtGetFirstNameInGroup( EgtGetParent( nSolidLayerId), WIN_MIXED_INTERSECTIONS) local vIntersections = EgtGetAllInGroup( nMixedIntersectionsGrp) for i = 1, #vIntersections do -- creo la superficie di separazione tra i due sottopezzi local bSashFill = ( EgtGetName( vMixedOutlines[i]) == WIN_SASH) local vtDirS = EgtSV( vIntersections[i]) vtDirS:rotate( Z_AX(), EgtIf( bSashFill, -135, 135)) local vtDirE = EgtSV( vIntersections[i]) vtDirE:rotate( Z_AX(), EgtIf( bSashFill, 45, -45)) local nCrvTrim = EgtCurveCompo( nSolidLayerId, vIntersections[i], false) EgtAddCurveCompoLine( nCrvTrim, EgtSP( nCrvTrim) + dGeoWidth * vtDirS, false) EgtAddCurveCompoLine( nCrvTrim, EgtEP( nCrvTrim) + dGeoWidth * vtDirE) EgtMove( nCrvTrim, Z_AX()) local nStmTrim = EgtSurfTmByExtrusion( nSolidLayerId, nCrvTrim, - 2 * dGeoWidth * Z_AX()) -- taglio i due sottopezzi EgtSurfTmSubtract( vMainExtrusions[i+1], nStmTrim) EgtInvertSurf( nStmTrim) EgtSurfTmSubtract( vMainExtrusions[i], nStmTrim) EgtErase( nCrvTrim) EgtErase( nStmTrim) end -- unisco i sottopezzi in una sola superficie for i = 2, #vMainExtrusions do EgtSurfTmAdd( vMainExtrusions[1], vMainExtrusions[i]) EgtErase( vMainExtrusions[i]) end -- creo una copia dell'estrusione principale ( usata per ferramenta) local nOrigMainExtrusionId = EgtCopy( vMainExtrusions[1], nSolidLayerId) EgtSetName( nOrigMainExtrusionId, WIN_SRF_ORIGMAIN) EgtSetStatus( nOrigMainExtrusionId, GDB_ST.OFF) -- come guida tengo solo una copia della curva di outline local vMainGuideIds = EgtGetNameInGroup( nSolidLayerId, WIN_MAINGUIDE) EgtErase( vMainGuideIds) local nMainGuideId = EgtCopyGlob( nOutlineId, nSolidLayerId) EgtSetName( nMainGuideId, WIN_MAINGUIDE) EgtSetStatus( nMainGuideId, GDB_ST.OFF) -- b) TRIM START local nPrevGeoId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_LEFT) local nStartOutlineId = EgtGetInfo( nPrevGeoId, WIN_REF_OUTLINE, 'i') local nTrimSurfStart = CreateTrimSurf( nPrevGeoId, nStartOutlineId, dGeoWidth, nSolidLayerId) EgtSetStatus( nTrimSurfStart, GDB_ST.OFF) EgtSurfTmIntersect( vMainExtrusions[1], nTrimSurfStart) EgtSetInfo( nPrevGeoId, WIN_REF_SURF, nTrimSurfStart) -- c) TRIM END local nNextGeoId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_RIGHT) local nEndOutlineId = EgtGetInfo( nNextGeoId, WIN_REF_OUTLINE, 'i') local nTrimSurfEnd = CreateTrimSurf( nNextGeoId, nEndOutlineId, dGeoWidth, nSolidLayerId) EgtSetStatus( nTrimSurfEnd, GDB_ST.OFF) EgtSurfTmIntersect( vMainExtrusions[1], nTrimSurfEnd) EgtSetInfo( nNextGeoId, WIN_REF_SURF, nTrimSurfEnd) return vMainExtrusions[1] end --------------------------------------------------------------------- -- funzione che crea il solido di un pezzo di split coinvolto da cambio profilo local function CalcMixedSplitSolid( nOutlineId, nSolidLayerId, nProfileLayerId, dGeoWidth) -- a) creo il solido di estrusione principale local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN) local sSection = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_SECTION local nMainExtrusionId = CreateMainSurf( nOutlineId, 2 * dGeoWidth, nMainProfileId, sSection, nSolidLayerId) -- creo una copia local nOrigMainExtrusionId = EgtCopy( nMainExtrusionId, nSolidLayerId) EgtSetName( nOrigMainExtrusionId, WIN_SRF_ORIGMAIN) EgtSetStatus( nOrigMainExtrusionId, GDB_ST.OFF) -- b) trim start local nPrevProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_START) local nPrevMixedOutline = EgtGetInfo( nOutlineId, WIN_MIXED_REF_START, 'i') local nStmTrimStart = CreateMixedSplitTrimSurf( nPrevMixedOutline, nPrevProfileId, dGeoWidth, nSolidLayerId) EgtSetStatus( nStmTrimStart, GDB_ST.OFF) EgtSurfTmIntersect( nMainExtrusionId, nStmTrimStart) local nGeoLayerId = EgtGetFirstNameInGroup( EgtGetParent( nSolidLayerId), WIN_GEO) local nPrevGeoId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_LEFT) EgtSetInfo( nPrevGeoId, WIN_REF_SURF, nStmTrimStart) -- c) trim end local nNextProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_END) local nNextMixedOutline = EgtGetInfo( nOutlineId, WIN_MIXED_REF_END, 'i') local nStmTrimEnd = CreateMixedSplitTrimSurf( nNextMixedOutline, nNextProfileId, dGeoWidth, nSolidLayerId) EgtSetStatus( nStmTrimEnd, GDB_ST.OFF) EgtSurfTmIntersect( nMainExtrusionId, nStmTrimEnd) local nNextGeoId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_RIGHT) EgtSetInfo( nNextGeoId, WIN_REF_SURF, nStmTrimEnd) return nMainExtrusionId end --------------------------------------------------------------------- -- funzione che verifica se due curve del geo sono concatenabili, ovvero se hanno lo stesso profilo e i corrispondenti outline coincidono o sono in tangenza local function CheckChainability( nGeoCrv1, nGeoCrv2) -- verifico profili local sProfile1 = EgtGetInfo( nGeoCrv1, WIN_PROFILETYPE) local sProfile2 = EgtGetInfo( nGeoCrv2, WIN_PROFILETYPE) local nSemiProfileId1 = EgtGetInfo( nGeoCrv1, WIN_SEMI_PROFILE, 'i') local nSemiProfileId2 = EgtGetInfo( nGeoCrv2, WIN_SEMI_PROFILE, 'i') if sProfile1 == sProfile2 and nSemiProfileId1 and nSemiProfileId2 and EgtGetName( nSemiProfileId1) == EgtGetName( nSemiProfileId2) then -- verifico outlines local nRefOutline1 = EgtGetInfo( nGeoCrv1, WIN_REF_OUTLINE, 'i') local nRefOutline2 = EgtGetInfo( nGeoCrv2, WIN_REF_OUTLINE, 'i') if nRefOutline1 == nRefOutline2 or AreSameVectorApprox( EgtEV( nRefOutline1), EgtSV( nRefOutline2)) then return true end end return false 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) -- 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 bChangeProfile = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'b') or false if bChangeProfile then if EgtGetName( nOutlineId) == WIN_SPLIT then return CalcMixedSplitSolid( nOutlineId, nSolidLayerId, nProfileLayerId, dGeoWidth) else return CalcMixedFrameSolid( nOutlineId, nSolidLayerId, nProfileLayerId, nGeoLayerId, dGeoWidth) end end -- a) creo il solido di estrusione principale local nMainProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN) local sSection = EgtIf( s_bSimplSolid, WIN_SIMPLIFIED, '') .. WIN_SECTION local nMainExtrusionId = CreateMainSurf( nOutlineId, 4 * dGeoWidth, nMainProfileId, sSection, nSolidLayerId) -- 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 e su end local vGeoId = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_RIGHT) local vPrevGeoId = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_LEFT) EgtJoinTables( vGeoId, vPrevGeoId) -- verifico quali curve di trim conviene concatenare per evitare booleane problematiche con tratti sovrapposti local vChains = {{ vGeoId[1]}} for i = 2, #vGeoId do if CheckChainability( vGeoId[i-1], vGeoId[i]) then -- aggiugno alla catena corrente table.insert( vChains[#vChains], vGeoId[i]) else -- creo una nuova catena table.insert( vChains, { vGeoId[i]}) end end -- calcolo le superfici di trim for i = 1, #vChains do local nTrimSurf if #vChains[i] == 1 then local nRefOutlineId = EgtGetInfo( vChains[i][1], WIN_REF_OUTLINE, 'i') nTrimSurf = CreateTrimSurf( vChains[i][1], abs( nRefOutlineId), dGeoWidth, nSolidLayerId) -- assegno alla curva del geo la superficie di trim creata EgtSetInfo( vChains[i][1], WIN_REF_SURF, nTrimSurf) else -- costruisco la guida a partire dagli outlines local vRefOutlineIds = {} for j = 1, #vChains[i] do local nCurrOutline = EgtGetInfo( vChains[i][j], WIN_REF_OUTLINE, 'i') -- verifico di non inserire un outline doppio if j == 1 or nCurrOutline ~= vRefOutlineIds[#vRefOutlineIds] then table.insert( vRefOutlineIds, abs( nCurrOutline)) end end local nGuideId = EgtCurveCompo( nSolidLayerId, vRefOutlineIds, false) nTrimSurf = CreateTrimSurf( vChains[i][1], nGuideId, dGeoWidth, nSolidLayerId) -- assegno ad ogni curva del geo la superficie di trim creata for j = 1, #vChains[i] do EgtSetInfo( vChains[i][j], WIN_REF_SURF, nTrimSurf) end EgtErase( nGuideId) end EgtSetStatus( nTrimSurf, GDB_ST.OFF) EgtSurfTmIntersect( nMainExtrusionId, nTrimSurf) 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 UpdateSolidWithProcessingSurf( 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 * 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( nRefProfileType, nPrevGeo, nGeo, nRefOutline, bCurrFullOrShort, bSashOrFrame) -- 1) la direzione z è determinata dal pezzo short local vtZ if EgtGetType( nRefOutline) == GDB_TY.CRV_LINE then vtZ = EgtEV( nRefOutline) else -- se pezzo ad arco, recupero la direzione dalla curva nel punto estremo del geo local nGeoRefCrv if bCurrFullOrShort then nGeoRefCrv = EgtGetFirstNameInGroup( nPrevGeo, WIN_RIGHT) else nGeoRefCrv = EgtGetFirstNameInGroup( nGeo, WIN_LEFT) end local ptInt = EgtIP( nGeoRefCrv, nRefOutline, ORIG()) local dPar = EgtCurveParamAtPoint( nRefOutline, ptInt, 100 * GEO.EPS_SMALL) vtZ = EgtUV( nRefOutline, dPar, -1) end local frDest = Frame3d( ORIG(), - vtZ) -- 2) punto di origine local nPrevRight = EgtGetFirstNameInGroup( nPrevGeo, WIN_GEO_RIGHT) local ptRef1 = EgtIf( bCurrFullOrShort, EgtSP( nPrevRight), EgtEP( nPrevRight)) local nLeft = EgtGetFirstNameInGroup( nGeo, WIN_GEO_LEFT) local ptRef2 = EgtIf( bCurrFullOrShort, EgtSP( nLeft), EgtEP( nLeft)) -- riporto i punti sulla curva di outline su cui va posizionato il profilo con le spine local _, ptInt1 = EgtPointCurveDist( ptRef1, nRefOutline) local _, ptInt2 = EgtPointCurveDist( ptRef2, nRefOutline) -- nel caso di telaio conviene tenere il punto più "interno" visto che la correzione sarà fatta verso l'esterno -- nel caso di anta conviene tenere quello più "esterno" visto che la correzione sarà fatta verso l'interno ptInt1:toLoc( frDest) ptInt2:toLoc( frDest) local ptInt if ptInt1:getX() > ptInt2:getX() then ptInt = EgtIf( bSashOrFrame, Point3d( ptInt1), Point3d( ptInt2)) else ptInt = EgtIf( bSashOrFrame, Point3d( ptInt2), Point3d( ptInt1)) end ptInt:toGlob( frDest) -- modifico il punto di origine del frame nel punto individuato frDest:move( ptInt - ORIG()) 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, 300 * 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 UpdateSolidWithProcessingSurf( nDowelId, nMainExtrusionId, nLayerId) end return nDowelId end --------------------------------------------------------------------- -- funzione che calcola la correzione da applicare al frame dei dowels per evitare che fuoriescano dal pezzo da un lato visibile ( esterno per ante ed interno per telaio) local function CalcDowelFrameCorrection( nOutlineId, nPrevOutlineId, nDowelRef, frOrig, frDest, nTestSurfPos, nTestSurfPosPrev, nTestSurf, vtMove, nLayerId, dLen, dPrevLen) local dMove = 0 -- se le curve sono due linee non serve correzione if EgtGetType( nOutlineId) == GDB_TY.CRV_LINE and EgtGetType( nPrevOutlineId) == GDB_TY.CRV_LINE then return dMove end -- 1) verifico posizione per il pezzo corrente -- posiziono il dowel local nDowel1 = EgtCopyGlob( nDowelRef, nLayerId) PositionDowel( nDowel1, frOrig, frDest, - frDest:getVersZ(), nTestSurfPos) -- verifico se la faccia di fondo fuoriesce dalla superficie di test local dMove1 = EgtCAvToolPosStm( EgtCP( nDowel1) - frDest:getVersZ() * dLen, frDest:getVersZ(), nTestSurf, vtMove) -- 2) verifico posizione per il pezzo precedente -- posiziono il dowel local nDowel2 = EgtCopyGlob( nDowelRef, nLayerId) PositionDowel( nDowel2, frOrig, frDest, frDest:getVersZ(), nTestSurfPosPrev) -- verifico se la faccia di fondo fuoriesce dalla superficie di test local dMove2 = EgtCAvToolPosStm( EgtCP( nDowel2) + frDest:getVersZ() * dPrevLen, - frDest:getVersZ(), nTestSurf, vtMove) EgtErase( nDowel1) EgtErase( nDowel2) -- calcolo la correzione complessiva dMove = max( dMove1, dMove2) + s_dDowelTol return dMove end --------------------------------------------------------------------- -- funzione che calcola i dowels tra due pezzi local function CalcDowels( nOrigOutlineId, nOrigPrevOutlineId, bSashOrFrame, nBottomRail) -- 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_RAILDELTA, 'd') else nRefCrv = nPrevOutlineId dOffs = EgtGetInfo( nPrevProfileId, WIN_RAILDELTA, 'd') end EgtOffsetCurve( nRefCrv, - dOffs) end -- recupero i geo local nGeo = EgtGetFirstNameInGroup( nPart, WIN_GEO) local nPrevGeo = EgtGetFirstNameInGroup( nPrevPart, WIN_GEO) -- recupero i tipi di profilo local nPrevProfileType = GetOutlineProfileType( nPrevOutlineId, false, nBottomRail) local nProfileType = GetOutlineProfileType( nOutlineId, false, nBottomRail) -- caso particolare del triangolo : se lato top contro bottom il top deve essere gestito come un left/right if nProfileType == WIN_PRF.TOP and nPrevProfileType == WIN_PRF.BOTTOM then nProfileType = WIN_PRF.RIGHT elseif nProfileType == WIN_PRF.BOTTOM and nPrevProfileType == WIN_PRF.TOP then nPrevProfileType = WIN_PRF.LEFT 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 = EgtGetInfo( nOutlineId, WIN_STARTJOINT, 'i') if nBottomRail then if EgtGetName( nOutlineId) == WIN_BOTTOM then nJointType = WIN_PART_JNT.SHORT else nJointType = WIN_PART_JNT.FULL 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( nPrevProfileType, nPrevGeo, nGeo, nPrevOutlineId, true, bSashOrFrame) -- 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 nProfileType == WIN_PRF.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) -- 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 nGeoCrv = EgtGetFirstNameInGroup( nPrevGeo, WIN_GEO_RIGHT) local nOrigSurf = EgtGetInfo( nGeoCrv, WIN_REF_SURF, 'i') nTestSurf = EgtCopyGlob( nOrigSurf, nLayerId) end local nTestSurfInverted = EgtCopyGlob( nTestSurf, nLayerId) EgtInvertSurf( nTestSurfInverted) -- superficie test per la traslazione dei dowels local nTestSurf2 if bSashOrFrame then -- se anta la superficie da cui non fuoriuscire è quella esterna del pezzo short, ovvero la superficie usata per trimmare lo start del pezzo corrente if not s_bCalcSolid or s_bSimplSolid then nTestSurf2 = CreateProfileSurf( nOrigPrevOutlineId, nPrevProfileId, WIN_OFST .. WIN_OUT, 100, nLayerId) else local nGeoCrv = EgtGetFirstNameInGroup( nGeo, WIN_GEO_LEFT) local nOrigSurf = EgtGetInfo( nGeoCrv, WIN_REF_SURF, 'i') nTestSurf2 = EgtCopyGlob( nOrigSurf, nLayerId) end EgtInvertSurf( nTestSurf2) else -- se telaio la superficie da cui non fuoriuscire è quella interna del pezzo short local sCtrIn2 = WIN_OFST .. GetProfileCtrIn( nOrigPrevOutlineId, nOutlineId, nPrevProfileId) nTestSurf2 = CreateProfileSurf( nOrigPrevOutlineId, nPrevProfileId, sCtrIn2, 100, nLayerId) end -- direzione per la traslazione dei dowels local vtMove = EgtIf( bSashOrFrame, - frDest:getVersX(), frDest:getVersX()) -- 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 -- recupero il dowel nella posizione più problematica ( per le ante è quello più esterno, per il telaio quello più interno) local nDowelRef = EgtIf( bSashOrFrame, vDowels[1], vDowels[#vDowels]) -- calcolo correzione da applicare al frame affinchè i dowels non fuoriescano da un lato visibile ( esterno per ante ed interno per telaio) local dLenCurr = CalcDowelLen( nDowelRef, sLenKey, true) local dLenPrev = CalcDowelLen( nDowelRef, sPrevLenKey, false) local dMove = CalcDowelFrameCorrection( nOutlineId, nPrevOutlineId, nDowelRef, frOrig, frDest, nTestSurfInverted, nTestSurf, nTestSurf2, vtMove, nLayerId, dLenCurr, dLenPrev) local frDestDowel = Frame3d( frDest) frDestDowel:move( dMove * vtMove) for i = 1, #vDowels do -- dowels per pezzo corrente ( full) local dLenFull = CalcDowelLen( vDowels[i], sLenKey, true) CreateDowel( vDowels[i], nLayerId, frOrig, frDestDowel, - frDestDowel: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, frDestDowel, frDestDowel:getVersZ(), nTestSurf, dLenShort, WIN_PRC_SIDETYPE.RIGHT, nPrevSolidId) end end end EgtErase( nTestSurf) EgtErase( nTestSurfInverted) EgtErase( nTestSurf2) 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( nProfileType, nPrevGeo, nGeo, nOutlineId, false, bSashOrFrame) -- 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 nPrevProfileType == WIN_PRF.BOTTOM then sLenKey = WIN_DWL_BOTTOM_PARA_LEN sPrevLenKey = WIN_DWL_BOTTOM_PERP_LEN elseif nPrevProfileType == WIN_PRF.BOTTOMRAIL or nPrevProfileType == WIN_PRF.BOTTOMRAIL_FINAL then sLenKey = WIN_DWL_BOTTOMRAIL_PARA_LEN sPrevLenKey = WIN_DWL_BOTTOMRAIL_PERP_LEN 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) -- controprofilo del pezzo full nTestSurf = CreateProfileSurf( nOrigPrevOutlineId, nPrevProfileId, sCtrIn, 100, nLayerId) else local nGeoCrv = EgtGetFirstNameInGroup( nGeo, WIN_GEO_LEFT) local nOrigSurf = EgtGetInfo( nGeoCrv, WIN_REF_SURF, 'i') nTestSurf = EgtCopyGlob( nOrigSurf, nLayerId) end local nTestSurfInverted = EgtCopyGlob( nTestSurf, nLayerId) EgtInvertSurf( nTestSurfInverted) -- superficie test per la traslazione dei dowels local nTestSurf2 if bSashOrFrame then if not s_bCalcSolid or s_bSimplSolid then nTestSurf2 = CreateProfileSurf( nOrigOutlineId, nProfileId, WIN_OFST .. WIN_OUT, 100, nLayerId) else local nGeoCrv = EgtGetFirstNameInGroup( nPrevGeo, WIN_GEO_RIGHT) local nOrigSurf = EgtGetInfo( nGeoCrv, WIN_REF_SURF, 'i') nTestSurf2 = EgtCopyGlob( nOrigSurf, nLayerId) end EgtInvertSurf( nTestSurf2) else local sCtrIn2 = WIN_OFST .. GetProfileCtrIn( nOutlineId, nPrevOutlineId, nProfileId) -- controprofilo del pezzo short nTestSurf2 = CreateProfileSurf( nOrigOutlineId, nProfileId, sCtrIn2, 100, nLayerId) end -- direzione per la traslazione dei dowels local vtMove = EgtIf( bSashOrFrame, - frDest:getVersX(), frDest:getVersX()) -- 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 -- recupero il dowel nella posizione più problematica ( per le ante è quello più esterno, per il telaio quello più interno) local nDowelRef = EgtIf( bSashOrFrame, vDowels[1], vDowels[#vDowels]) -- calcolo correzione da applicare al frame affinchè i dowels non fuoriescano da un lato visibile ( esterno per ante ed interno per telaio) local dLenCurr = CalcDowelLen( nDowelRef, sLenKey, false) local dLenPrev = CalcDowelLen( nDowelRef, sPrevLenKey, true) local dMove = CalcDowelFrameCorrection( nOutlineId, nPrevOutlineId, nDowelRef, frOrig, frDest, nTestSurf, nTestSurfInverted, nTestSurf2, vtMove, nLayerId, dLenCurr, dLenPrev) local frDestDowel = Frame3d( frDest) frDestDowel:move( dMove * vtMove) for i = 1, #vDowels do -- dowels per pezzo corrente ( short) local dLenShort = CalcDowelLen( vDowels[i], sLenKey, false) CreateDowel( vDowels[i], nLayerId, frOrig, frDestDowel, - frDestDowel: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, frDestDowel, frDestDowel:getVersZ(), nTestSurfInverted, dLenFull, WIN_PRC_SIDETYPE.IN, nPrevSolidId) end end end EgtErase( nTestSurf) EgtErase( nTestSurfInverted) EgtErase( nTestSurf2) 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 -- 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 = WIN_PRC_SIDETYPE.RIGHT if bStartOrEnd then sSplitDowelSide = WIN_PRC_SIDETYPE.LEFT end -- recupero la superficie del pezzo per verificare se dowel interno local nSplitGeo = EgtGetFirstNameInGroup( nSplitPart, WIN_GEO) local nSplitSurf = EgtGetFirstNameInGroup( nSplitGeo, WIN_GEO_SURF) local vGeoCrvs = EgtGetNameInGroup( nSplitGeo, EgtIf( bStartOrEnd, WIN_LEFT, WIN_RIGHT)) local ptRef = EgtIf( bStartOrEnd, EgtSP( nSplitId), EgtEP( nSplitId)) for i = 1, #vGeoCrvs do 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 nProfileType = GetOutlineProfileType( nOutlineId, true) -- calcolo il frame di destinazione -- trovo intersezione dello split con lato In o Out del geo local nGeoLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO) local nGeoCrvId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_IN) local ptInters = EgtIP( nGeoCrvId, nSplitId, ptRef) local sDowelSide = WIN_PRC_SIDETYPE.IN if not ptInters and nProfileType == WIN_PRF.SPLIT then nGeoCrvId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_OUT) ptInters = EgtIP( nGeoCrvId, nSplitId, ptRef) sDowelSide = WIN_PRC_SIDETYPE.OUT end -- se non trovo intersezione passo al successivo if ptInters then -- TO DO : gestione split non lineare local frDest = Frame3d( ptInters, - 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) local sSplitProfileType = EgtGetName( nSplitProfile) EgtSetInfo( nSplitProfileCopyId, WIN_PRF_TYPE, sSplitProfileType) 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 nProfileType == WIN_PRF.BOTTOM then sSplitLenKey = WIN_DWL_BOTTOM_PARA_LEN sLenKey = WIN_DWL_BOTTOM_PERP_LEN elseif nProfileType == WIN_PRF.BOTTOMRAIL_FINAL then sSplitLenKey = WIN_DWL_RAILBOTTOM_PARA_LEN sLenKey = WIN_DWL_RAILBOTTOM_PERP_LEN elseif nProfileType == WIN_PRF.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 nProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN) local nTestSurf if not s_bCalcSolid or s_bSimplSolid then local bChangeProfile = EgtGetInfo( nSplitId, WIN_PRF_CHANGE, 'b') or false if bChangeProfile then local nMixedOutline = EgtGetInfo( nSplitId, EgtIf( bStartOrEnd, WIN_MIXED_REF_START, WIN_MIXED_REF_END), 'i') nTestSurf = CreateMixedSplitTrimSurf( nMixedOutline, nProfileId, 100, nLayerId) else local sCtr = WIN_OFST .. GetProfileCtrIn( nOutlineId, nSplitId, nProfileId) nTestSurf = CreateProfileSurf( nOutlineId, nProfileId, sCtr, 100, nLayerId) end else -- è la stessa superficie utilizzata per il trim del solido local nTrimSurf = EgtGetInfo( vGeoCrvs[i], WIN_REF_SURF, 'i') nTestSurf = EgtCopyGlob( nTrimSurf, nSplitLayerId) end local nTestSurfInverted = EgtCopyGlob( nTestSurf, nSplitLayerId) EgtInvertSurf( nTestSurfInverted) -- calcolo le direzioni entranti nei pezzi local vtSplitDir = EgtIf( bStartOrEnd, - frDest:getVersZ(), frDest:getVersZ()) local vtDir = frDest:getVersZ() local _, _, nSide = EgtPointCurveDistSide( ptInters + vtDir, nGeoCrvId, Z_AX()) if nSide == 1 then -- se a destra della curva significa che la direzione è uscente dal pezzo e va invertita vtDir = - vtDir end -- 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 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 nOutline do -- 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 nOutline = EgtGetNext( nOutline) end elseif nAreaType == WIN_AREATYPES.SPLIT then local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) local nSplitType = EgtGetInfo( nSplitLayerId, 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 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 local bInverted = EgtGetInfo( nOutlineId, WIN_INV_SPLIT, 'b') or false if bInverted 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, nRefOutlineId, 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, GDB_RT.GLOB) -- calcolo offset per strip local dDelta = EgtGetInfo( nProfileId, WIN_RAILDELTA, 'd') or 0 local dMinOffs = b3MainStrip:getMin():getX() - dDelta local dMaxOffs = b3MainStrip:getMax():getX() - dDelta local nMinOffsetId = EgtCopy( nOutlineId, nSolidLayerId) EgtOffsetCurve( nMinOffsetId, dMinOffs) local nMaxOffsetId = EgtCopy( nOutlineId, nSolidLayerId) EgtOffsetCurve( nMaxOffsetId, dMaxOffs) -- verifico se le curve vanno invertite nel caso di split local bInverted = EgtGetInfo( nRefOutlineId, WIN_INV_SPLIT, 'b') or false if bInverted 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( nGeoFillId) 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 vGeoCrvs = EgtGetAllInGroup( nGeoFillId) local tabStrip = {} for i = 1, #vGeoCrvs do local nCrvId = abs( EgtGetInfo( vGeoCrvs[i], WIN_REF_OUTLINE, 'i')) local nOutlineId = abs( EgtGetInfo( nCrvId, WIN_REF_OUTLINE, 'i')) local nPartId = FindAssociatedPart( nOutlineId, true) -- recupero profilo local nProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE) local nProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_MAIN) local nStripId = GetStripNearestToOutline( nProfileId, nCrvId) -- recupero layer per solido local nSolidLayerId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID) -- estrusione del fermavetro : -- creazione della giuda local nGuideId = EgtCurveCompo( nSolidLayerId, nOutlineId, false) local sProfileType = EgtGetInfo( nProfileId, WIN_PRF_TYPE) if sProfileType == WIN_FILL_RAIL then local dOffs = EgtGetInfo( nProfileId, WIN_RAILDELTA, 'd') EgtOffsetCurve( nGuideId, - dOffs) end -- estensione : se in tangenza con le vicine estensione in tangenza altrimenti estensione standard local nPrev = EgtGetPrev( vGeoCrvs[i]) or EgtGetLastInGroup( nGeoFillId) local nNext = EgtGetNext( vGeoCrvs[i]) or EgtGetLastInGroup( nGeoFillId) 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) local nStripExtrusionId = EgtSurfTmSwept( nSolidLayerId, nSectionId, nGuideId, false, WIN_SURF_APPROX) EgtSetName( nStripExtrusionId, WIN_SRF_STRIP) EgtErase( nSectionId) EgtErase( nGuideId) -- curve limite del fermavetro local nOffs1, nOffs2 = CreateStripGuideLines( nOutlineId, nCrvId, nStripId, nProfileId, nGrp) EgtSetInfo( nOffs1, WIN_REF_GEO, vGeoCrvs[i]) EgtSetInfo( nOffs2, WIN_REF_GEO, vGeoCrvs[i]) tabStrip[vGeoCrvs[i]] = { OrigOffs1 = nOffs1, OrigOffs2 = nOffs2, Offs1 = GDB_ID.NULL, Offs2 = GDB_ID.NULL, StripId = nStripExtrusionId} EgtCopyGlob( nOffs1, nGrp1) EgtCopyGlob( nOffs2, nGrp2) end -- taglio le curve limite dei fermavetri per individuare correttamente i pezzi con cui verranno tagliati TrimOrderedCurves( EgtGetAllInGroup( nGrp1)) TrimOrderedCurves( EgtGetAllInGroup( nGrp2)) -- associo le curve trimmate alle curve geo corrispondenti local nCrvId = EgtGetFirstInGroup( nGrp1) while nCrvId do local nGeoRef = EgtGetInfo( nCrvId, WIN_REF_GEO, 'i') tabStrip[nGeoRef].Offs1 = nCrvId nCrvId = EgtGetNext( nCrvId) end nCrvId = EgtGetFirstInGroup( nGrp2) while nCrvId do local nGeoRef = EgtGetInfo( nCrvId, WIN_REF_GEO, 'i') tabStrip[nGeoRef].Offs2 = nCrvId nCrvId = EgtGetNext( nCrvId) end -- trim dei solidi fermavetro for i = 1, #vGeoCrvs do -- recupero solido del fermavetro local nGeoCrv = vGeoCrvs[i] local nStripId = tabStrip[nGeoCrv].StripId local nSolidLayerId = EgtGetParent( nStripId) -- recupero le corrispondenti curve limite trimmate local nCrvOffs1 = tabStrip[nGeoCrv].Offs1 local nCrvOffs2 = tabStrip[nGeoCrv].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_GEO, 'i') local nPrevCrv2 = EgtGetInfo( nPrev2, WIN_REF_GEO, '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 nStartCrv = tabStrip[nPrevCrv1].Offs2 nStartCrv = EgtGetNext( nStartCrv) or EgtGetFirstInGroup( EgtGetParent( nStartCrv)) local vIds = {} while nStartCrv ~= nCrvOffs2 do table.insert( vIds, nStartCrv) nStartCrv = EgtGetNext( nStartCrv) or EgtGetFirstInGroup( EgtGetParent( nStartCrv)) end local nCrvRef2 = EgtCurveCompo( nGrp, vIds, false) -- taglio TrimStripSurfByCurve( nCrvRef2, nStripId, nSolidLayerId) -- b) taglio che separa da pezzo 1 TrimStripSurfByPoints( EgtCP( nCrvRef2), EgtSP( nCrvOffs1), nStripId, nSolidLayerId, true) EgtErase( nCrvRef2) 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_GEO, 'i') local nNextCrv2 = EgtGetInfo( nNext2, WIN_REF_GEO, 'i') if nNextCrv1 == nNextCrv2 then TrimStripSurfByPoints( EgtEP( nCrvOffs1), EgtEP( nCrvOffs2), nStripId, nSolidLayerId) else local nStartCrv = nCrvOffs2 nStartCrv = EgtGetNext( nStartCrv) or EgtGetFirstInGroup( EgtGetParent( nStartCrv)) local vIds = {} while nStartCrv ~= tabStrip[nNextCrv1].Offs2 do table.insert( vIds, nStartCrv) nStartCrv = EgtGetNext( nStartCrv) or EgtGetFirstInGroup( EgtGetParent( nStartCrv)) end local nCrvRef2 = EgtCurveCompo( nGrp, vIds, false) TrimStripSurfByCurve( nCrvRef2, nStripId, nSolidLayerId) TrimStripSurfByPoints( EgtEP( nCrvOffs1), EgtCP( nCrvRef2), nStripId, nSolidLayerId) EgtErase( nCrvRef2) end else -- il pezzo scompare EgtErase( nStripId) end end EgtErase( nGrp) EgtErase( nGrp1) EgtErase( nGrp2) end ---------------------------------------------------------------------------------- ----------------------------- CALCOLO 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.FRAME and nParentType ~= WIN_AREATYPES.SASH do nParentId = EgtGetParent( nParentId) nParentType = EgtGetInfo( nParentId, WIN_AREATYPE, 'i') end sName = EgtGetInfo( nParentId, WIN_AREA_NAME, sName) end return sName end --------------------------------------------------------------------- -- 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 = GetOutlineProfileId( vCrvs[i], true) local b3FrameProfile = GetProfileLocalBox( nProfileId) local dOffs = b3FrameProfile:getMin():getX() local nBottomRail = EgtGetInfo( nCrv, WIN_BOTTOMRAIL, 'i') or 0 if nBottomRail > 0 then -- aggiusto offset per bottomrail local dDelta1 = EgtGetInfo( nProfileId, WIN_RAILDELTA .. '1', 'd') local dDelta2 = EgtGetInfo( nProfileId, WIN_RAILDELTA .. '2', 'd') dOffs = dOffs - dDelta1 - ( nBottomRail - 1) * dDelta2 end EgtOffsetCurve( nCrv, dOffs) end vCrvs = TrimOrderedCurves( vCrvs) 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 calcola l'ingombro dei pezzi del telaio e i loro solidi local function CreatePartFromOutline( nAreaLayerId, sName, nOutlineId, nOutlineCrvNbr, 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) -- inserisco riferimento alla sua area EgtSetInfo( nPartId, WIN_AREA, nAreaLayerId) local nAreaType = EgtGetInfo( nAreaLayerId, WIN_AREATYPE, 'i') local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaLayerId, WIN_OUTLINE) -- a) Telaio, anta o split if nAreaType == WIN_AREATYPES.FRAME or nAreaType == WIN_AREATYPES.SASH or nAreaType == WIN_AREATYPES.SPLIT then -- creo riferimenti tra pezzo e outline EgtSetInfo( nPartId, WIN_REF_OUTLINE, nOutlineId) if nBottomRail then -- aggiorno i riferimenti del bottomrail local vBottomRailParts = EgtGetInfo( nOutlineId, WIN_REF_BOTTOMRAIL_PART, 'vi') or {} table.insert( vBottomRailParts, nPartId) EgtSetInfo( nOutlineId, WIN_REF_BOTTOMRAIL_PART, vBottomRailParts) EgtSetInfo( nPartId, WIN_PART_TYPE, WIN_PART_TYPES.BOTTOMRAIL) else EgtSetInfo( nOutlineId, WIN_REF_PART, nPartId) end -- imposto nome del pezzo local sOutlineName = EgtIf( nBottomRail, WIN_BOTTOMRAIL .. '_' .. tostring( nBottomRail), EgtGetName( nOutlineId)) local sPartName = sName .. '_' .. sOutlineName EgtSetName( nPartId, sPartName) -- imposto il 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 -- ricavo il tipo di profilo local nProfileType = GetOutlineProfileType( nOutlineId, false, nBottomRail) -- disegno ingombro CalcFrameGeo( nPartId, nOutlineId, nOutlineCrvNbr, nOutlineLayerId, nProfileType, nBottomRail) -- calcolo eventuali curve ausiliarie per cambio profilo local bChangeProfile = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'b') or false if bChangeProfile and nProfileType ~= WIN_PRF.SPLIT then CalcMixedFrameCurves( nPartId, nOutlineId) end -- calcolo le lavorazioni associate ai profili CalcProfilingProcessings( nPartId, nOutlineId) -- calcolo il georaw per automatismo lavorazioni CalcGeoRaw( nPartId) -- disegno solido if s_bCalcSolid then CalcSolid( nPartId, nOutlineId) end -- b) Fill elseif nAreaType == WIN_AREATYPES.FILL then -- imposto nome del pezzo EgtSetName( nPartId, sName .. '_' .. WIN_FILL) EgtSetInfo( nPartId, WIN_PART_TYPE, WIN_PART_TYPES.FILL) -- ricavo tipo local nFillType = EgtGetInfo( nAreaLayerId, WIN_FILLTYPE, 'i') -- imposto colore e tipologia di riempimento 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 -- disegno ingombro local nGeoLayerId = CalcFillGeo( nPartId, nOutlineLayerId) -- disegno solido if s_bCalcSolid then CalcFillSolid( nPartId, nGeoLayerId) end -- calcolo fermavetro CalcAreaStrip( nGeoLayerId) end return nPartId end --------------------------------------------------------------------- -- funzione che cicla ricorsivamente su aree e sottoaree per calcolare i pezzi local function CalculateAreaParts( nAreaId) local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i') -- recupero nome dei pezzi in quest'area local sName = CalcPartName( nAreaId, nAreaType) if nAreaType == WIN_AREATYPES.FRAME or nAreaType == WIN_AREATYPES.SASH then -- creo pezzi per ogni outline local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE) local vOutlines = EgtGetAllInGroup( nOutlineLayerId) for i = 1, #vOutlines do -- creo pezzo CreatePartFromOutline( nAreaId, sName, vOutlines[i], i) -- se di tipo bottom verifico se ha bottomrail if EgtGetName( vOutlines[i]) == WIN_BOTTOM then local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0 for j = 1, nBottomRail do CreatePartFromOutline( nAreaId, sName, vOutlines[i], i, j) end end end -- se anta disegno apertura if nAreaType == WIN_AREATYPES.SASH then DrawOpening( nAreaId) end elseif nAreaType == WIN_AREATYPES.FILL then -- creo riempimento CreatePartFromOutline( nAreaId, sName) elseif nAreaType == WIN_AREATYPES.SPLIT then local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) local nSplitType = EgtGetInfo( nSplitLayerId, WIN_SPLITTYPE, 'i') or WIN_SPLITTYPES.NULL -- se split non è di tipo french ha un pezzo associato if nSplitType ~= WIN_SPLITTYPES.FRENCH then -- creo gruppo per area di selezione per programma local nSelectionLayerId = EgtGroup( nAreaId) EgtSetName( nSelectionLayerId, WIN_SPLITSELECTION) EgtSetStatus( nSelectionLayerId, GDB_ST.OFF) EgtSetColor( nSelectionLayerId, 'YELLOW') EgtSetAlpha( nSelectionLayerId, 10) local nSelectionArea local vSplitIds = EgtGetAllInGroup( nSplitLayerId) for i = 1, #vSplitIds do -- creo pezzo split local nSplitPartId = CreatePartFromOutline( nAreaId, sName, vSplitIds[i]) -- aggiorno area di selezione local nSplitPartGeoId = EgtGetFirstNameInGroup( nSplitPartId, WIN_GEO) local nSplitArea = EgtGetFirstNameInGroup( nSplitPartGeoId, WIN_GEO_SURF) if not nSelectionArea then nSelectionArea = EgtCopyGlob( nSplitArea, nSelectionLayerId) EgtSetStatus( nSelectionArea, GDB_ST.ON) else EgtSurfFrAdd( nSelectionArea, nSplitArea) end end EgtMove( nSelectionArea, 10 * Z_AX()) end end -- disegno area di selezione per programma local nSelectionLayerId = EgtGroup( nAreaId) EgtSetName( nSelectionLayerId, WIN_SELECTION) EgtSetStatus( nSelectionLayerId, GDB_ST.OFF) local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE) local vOutlineList = EgtGetAllInGroup( nOutlineLayerId) local nCompoId = EgtCurveCompo( nSelectionLayerId, vOutlineList, false) local nSelectionArea = EgtSurfFlatRegion( nSelectionLayerId, nCompoId) EgtSetColor( nSelectionArea, 'YELLOW') EgtSetAlpha( nSelectionArea, 10) EgtMove( nSelectionArea, 10 * Z_AX()) EgtErase( nCompoId) -- calcolo i pezzi delle sottoaree local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*') while nChildAreaId do CalculateAreaParts( nChildAreaId) nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*') end 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 nSouId = EgtGetInfo( nOutlineId, WIN_COPY, 'i') local nAreaType = WIN_AREATYPES.NULL while nSouId and nAreaType ~= WIN_AREATYPES.FRAME do nSouId = EgtGetInfo( nSouId, WIN_SOU, 'i') or GDB_ID.NULL local nParentArea = EgtGetParent( EgtGetParent( nSouId)) or GDB_ID.NULL nAreaType = EgtGetInfo( nParentArea, WIN_AREATYPE, 'i') end if not nSouId then return end local nFrameOutlineId = EgtGetInfo( nSouId, WIN_COPY, '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) -- 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 = EgtGetInfo( nInfoGrp, WIN_DWL_DIAM, 'd') local dDowelLen = 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 UpdateSolidWithProcessingSurf( 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) -- svuoto il GeoRaw per ricalcolarlo local nGeoRawLayerId = EgtGetFirstNameInGroup( nPartId, WIN_GEO_RAW) EgtEmptyGroup( nGeoRawLayerId) -- 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 nBaseOutlineId = EgtGetInfo( nOutlineId, WIN_COPY, 'i') local dDelta = ( EgtSP( nOutlineId) - EgtSP( nBaseOutlineId)) * 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 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 = 0.5 * b3Profile:getDimX() -- 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]) return dVal 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 sHandleSide = 'Sx' local nOutlineId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_RIGHT) for i = 1, #vOptions do local vString = EgtSplitString( vOptions[i], '=') if vString[1] == 'PosizioneManiglia' then if vString[2] == 'destra' then sHandleSide = 'Dx' nOutlineId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_LEFT) elseif vString[2] == 'sopra' then nOutlineId = EgtGetFirstNameInGroup( nOutlineLayId, WIN_TOP) end break end 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 nBaseOutlineId = EgtGetInfo( nLeftId, WIN_COPY, 'i') local bLeftInactive = EgtGetInfo( nBaseOutlineId, 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) -- recupero gruppi dei profili local nProfileId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_PROFILE) local nSashProfileLayerId = EgtGetFirstNameInGroup( nProfileId, WIN_SASH) local nFrameProfileLayerId = EgtGetFirstNameInGroup( nProfileId, WIN_FRAME) -- 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 sProfileType = EgtGetInfo( nOutlineId, WIN_PROFILETYPE) local nSashProfileId = EgtGetFirstNameInGroup( nSashProfileLayerId, sProfileType) 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) -- costruisco i riferimenti local tFrame = {} for nIndex = 1, #vOutlineCopy do -- 1) Riferimenti ANTA local ptOrig = EgtEP( vOutlineCopy[nIndex]) local sOrigName = string.char( string.byte( 'A') + #vOutlineCopy - nIndex) local vtDir = EgtEV( vOutlineCopy[nIndex]) 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[nIndex], WIN_GAPDELTAZ, 'd') local nFA2Id = EgtFrame( nHdwSashLayerId, Frame3d( ptOrig - dGapDeltaZ * Z_AX(), - vtDir, vtDir ^ vtIn, vtIn)) EgtSetName( nFA2Id, sOrigName .. '.FA2') local dGapDeltaZ2 = EgtGetInfo( vOutlineCopy[nIndex], 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 ( è il primo parent con un profilo associato. Potrebbe essere uno split in sottoarea del telaio o potrebbe non -- esistere nel caso di french split) local nOrigOutlineId = EgtGetInfo( vOutlineCopy[nIndex], 'ORIG', 'i') local nBaseOutlineId = EgtGetInfo( nOrigOutlineId, WIN_COPY, 'i') local nSouId = EgtGetInfo( nBaseOutlineId, WIN_SOU, 'i') local sProfileFrame = EgtGetInfo( nSouId, WIN_PROFILETYPE) while nSouId and not sProfileFrame do nSouId = EgtGetInfo( nSouId, WIN_SOU, 'i') sProfileFrame = EgtGetInfo( nSouId or GDB_ID.NULL, WIN_PROFILETYPE) end if nSouId then -- ricavo aria lato telaio local nFrameProfileId = EgtGetFirstNameInGroup( nFrameProfileLayerId, sProfileFrame, 'i') local dGapDeltaOut = EgtGetInfo( nFrameProfileId, WIN_GAPDELTA, 'd') -- se deriva da split verifico il lato if EgtGetName( nSouId) == WIN_SPLIT then local bSameDir = AreSameVectorApprox( EgtSV( nSouId), EgtSV( nBaseOutlineId)) -- recupero informazione dal lato corretto ( split orizzontale) if not dGapDeltaOut then if bSameDir then dGapDeltaOut = EgtGetInfo( nFrameProfileId, WIN_GAPDELTA .. '2', 'd') else dGapDeltaOut = EgtGetInfo( nFrameProfileId, WIN_GAPDELTA .. '1', 'd') end end -- verifico il segno dell'offset if not bSameDir then dGapDeltaOut = - dGapDeltaOut end end local nOutlineOutId = EgtCopy( 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 nSashBaseOutlineId = EgtGetInfo( nOutlineId, WIN_COPY, 'i') local nSouId = EgtGetInfo( nSashBaseOutlineId, WIN_SOU, 'i') local sSouProfile = EgtGetInfo( nSouId, WIN_PROFILETYPE) while nSouId and not sSouProfile do nSouId = EgtGetInfo( nSouId, WIN_SOU, 'i') sSouProfile = EgtGetInfo( nSouId or GDB_ID.NULL, WIN_PROFILETYPE) end local nFrameOutlineId = EgtGetInfo( nSouId, WIN_COPY, '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 UpdateSolidWithProcessingSurf( 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 UpdateSolidWithProcessingSurf( 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 bSlide = EgtGetInfo( nFrameId, WIN_SLIDE_WINDOW, 'b') or false if bSlide then -- le dimensioni per alzante scorrevole sono quelle del telaio local nOutlineLayId = EgtGetFirstInGroup( 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 nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) or GDB_ID.NULL local nSplitType = EgtGetInfo( nSplitLayerId, 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 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 vChildren = EgtGetInfo( nOutlineId, WIN_SASH_CHILDREN, 'vi') for i = 1, #vChildren do local nSashAreaId = EgtGetParent( EgtGetParent( vChildren[i])) local nSashType = EgtGetInfo( nSashAreaId, WIN_SASHTYPE, 'i') if nSashType == WIN_SASHTYPES.SLIDE_FIXED then local nGuideId = EgtCopyGlob( vChildren[i], nAuxGrp) EgtExtendCurveStartByLen( nGuideId, 1000) EgtExtendCurveEndByLen( nGuideId, 1000) -- trim della guida con il geo dei pezzi vicini local nOutlineId = EgtGetInfo( vChildren[i], WIN_COPY, 'i') local nPrevCrv = EgtGetInfo( nOutlineId, WIN_PREV_OUTLINES, 'i') local dParS = GetTrimParamByGeo( nGuideId, nPrevCrv, WIN_GEO_OUT) local nNextCrv = EgtGetInfo( nOutlineId, WIN_NEXT_OUTLINES, 'i') local dParE = GetTrimParamByGeo( nGuideId, nNextCrv, 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 -- recupero tutti gli split che possono creare interruzioni nel gocciolatoio 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 nSplitId = EgtGetFirstNameInGroup( vStack[i], WIN_SPLIT) local nSplitType = EgtGetInfo( nSplitId, WIN_SPLITTYPE, 'i') if nSplitType ~= WIN_SPLITTYPES.FRENCH then local vCurrSplits = EgtGetAllInGroup( nSplitId) 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 table.insert( vSplits, vCurrSplits[j]) end end end end -- se non è anta o vetro ( che interrompono la cascata di pezzi relativi al telaio) salvo le sottaree per analizzarle if nAreaType ~= WIN_AREATYPES.SASH and nAreaType ~= WIN_AREATYPES.FILL then local vChildren = EgtGetNameInGroup( vStack[i], WIN_AREA .. '*') or {} vStack = EgtJoinTables( vStack, vChildren) end -- passo all'area successiva i = i + 1 end end -- recupero le curve sulle quali costruire il gocciolatoio: in generale è solo l'outline bottom, nel caso di cambio profilo sono solo i suoi sottotratti che poggiano -- contro le ante local vBottomOutlines = { nOutlineId} local bProfileChange = EgtGetInfo( nOutlineId, WIN_PRF_CHANGE, 'b') or false if bProfileChange then local nMixedOutlinesLay = EgtGetFirstNameInGroup( nPartId, WIN_MIXED_OUTLINES) local vSashOutlines = EgtGetNameInGroup( nMixedOutlinesLay, WIN_SASH) vBottomOutlines = vSashOutlines end -- recupero curve vicine local nPrevCrv = EgtGetLastInGroup( EgtGetParent( nOutlineId)) local nNextCrv = EgtGetNext( nOutlineId) for i = 1, #vBottomOutlines do local vParams = {} -- verifico se interruzioni per i pezzi vicini del telaio if AreSamePointApprox( EgtSP( vBottomOutlines[i]), EgtEP( nPrevCrv)) then local dPar = GetTrimParamByGeo( vBottomOutlines[i], nPrevCrv, WIN_GEO_IN) table.insert( vParams, dPar) end if AreSamePointApprox( EgtEP( vBottomOutlines[i]), EgtSP( nNextCrv)) then local dPar = GetTrimParamByGeo( vBottomOutlines[i], nNextCrv, WIN_GEO_IN) table.insert( vParams, dPar) end -- verifico se interruzioni per split for j = 1, #vSplits do -- verifico se lo split poggia sulla curva local dDist1 = EgtPointCurveDist( EgtSP( vSplits[j]), vBottomOutlines[i]) local dDist2 = EgtPointCurveDist( EgtEP( vSplits[j]), vBottomOutlines[i]) if dDist1 < GEO.EPS_SMALL or dDist2 < GEO.EPS_SMALL then -- recupero i parametri di intersezione con il geo dello split local dParIn = GetTrimParamByGeo( vBottomOutlines[i], vSplits[j], WIN_GEO_IN) if dParIn then table.insert( vParams, dParIn) end local dParOut = GetTrimParamByGeo( vBottomOutlines[i], vSplits[j], WIN_GEO_OUT) if dParOut then table.insert( vParams, dParOut) end end end -- riordino i parametri ( non dovrebbero mai capitare parametri coincidenti) table.sort( vParams) for j = 1, #vParams, 2 do -- creo la guida di estrusione per il gocciolatoio local nGuideId = EgtCopyGlob( vBottomOutlines[i], nSolidLayId) -- trim della curva EgtTrimCurveStartEndAtParam( nGuideId, vParams[j], vParams[j+1]) -- aggiorno la lunghezza dLenTot = dLenTot + EgtCurveLength( nGuideId) -- disegno 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 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) -- 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( nAreaId, 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, nProfileGrp, nGeoGrp, color) -- 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]) local vNextOutlines = EgtGetInfo( nOutlineId, WIN_NEXT_OUTLINES, 'vi') local vEndProfiles = EgtGetNameInGroup( nProfileGrp, WIN_PRF_END) local b3ProfileEnd = GetProfileLocalBox( vEndProfiles[1]) vCrvs[2] = EgtCopyGlob( abs( vNextOutlines[1]), nPreviewGrp) EgtOffsetCurve( vCrvs[2], b3ProfileEnd:getMin():getX()) -- 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) local vPrevOutlines = EgtGetInfo( nOutlineId, WIN_PREV_OUTLINES, 'vi') local vStartProfiles = EgtGetNameInGroup( nProfileGrp, WIN_PRF_START) local b3ProfileStart = GetProfileLocalBox( vStartProfiles[1]) vCrvs[4] = EgtCopyGlob( abs( vPrevOutlines[1]), nPreviewGrp) EgtOffsetCurve( vCrvs[4], b3ProfileStart:getMin():getX()) -- creo la regione e ne estraggo il bordo local nAreaId = CalcIntersectionRegion( vCrvs, nPreviewGrp) EgtSetColor( nAreaId, color) 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 dStep = b3Surf:getDimY() / nBottomRail for i = 1, nBottomRail - 1 do local pt = b3Surf:getMin() + i * dStep * 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 nAreaId local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i') local nGeoGrp = EgtGetFirstNameInGroup( nPartId, WIN_GEO) local nProfileGrp = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE) -- verifico se è sash active/inactive per gestione speciale local nBaseOutlineId = EgtGetInfo( nOutlineId, WIN_COPY, 'i') local bOnSplit = EgtGetInfo( nBaseOutlineId, WIN_CRV_ON_FRENCH_SPLIT, 'b') -- recupero il tipo di giunzione local nStartJoint = EgtGetInfo( nOutlineId, WIN_STARTJOINT, 'i') local nEndJoint = EgtGetInfo( nOutlineId, WIN_ENDJOINT, 'i') -- se non ha giunzioni short e non è active/inactive come preview posso considerare direttamente la regione del geo if nStartJoint ~= WIN_PART_JNT.SHORT and nEndJoint ~= WIN_PART_JNT.SHORT and not bOnSplit then local nGeoSurf = EgtGetFirstNameInGroup( nGeoGrp, WIN_GEO_SURF) nAreaId = EgtCopyGlob( nGeoSurf, nPreviewGrp) EgtSetStatus( nAreaId, GDB_ST.ON) -- altrimenti devi calcolare le curve che delimitano la regione else -- gruppo temporaneo per i conti local nGrpTmp = EgtGroup( nPreviewGrp) -- curva out è il geo out tranne nel caso di sash active/inactive per le quali considero l'outline per evitare sovrapposizioni if bOnSplit then EgtCopyGlob( nOutlineId, nGrpTmp) else local nGeoOut = EgtGetFirstNameInGroup( nGeoGrp, WIN_GEO_OUT) EgtCopyGlob( nGeoOut, nGrpTmp) end -- curva right local vGeoRight = EgtGetNameInGroup( nGeoGrp, WIN_GEO_RIGHT) if nEndJoint == WIN_PART_JNT.SHORT then -- se giunzione short per evitare sovrapposizioni devo fermarla al box del pezzo adiacente local vEndProfiles = EgtGetNameInGroup( nProfileGrp, WIN_PRF_END) for i = 1, #vGeoRight do local nNextOutline = EgtGetInfo( vGeoRight[i], WIN_REF_OUTLINE, 'i') local nCrv = EgtCopyGlob( abs( nNextOutline), nGrpTmp) local b3Profile = GetProfileLocalBox( vEndProfiles[i]) local dRailDelta = EgtGetInfo( vEndProfiles[i], WIN_RAILDELTA, 'd') or 0 local dOffs = b3Profile:getMin():getX() - dRailDelta if nNextOutline < 0 then EgtInvertCurve( nCrv) dOffs = - ( b3Profile:getMax():getX() - dRailDelta) end EgtOffsetCurve( nCrv, dOffs) end else -- altrimenti posso utilizzare direttamente la curva del geo for i = 1, #vGeoRight do EgtCopyGlob( vGeoRight[i], nGrpTmp) end end -- curva in local nGeoIn = EgtGetFirstNameInGroup( nGeoGrp, WIN_GEO_IN) EgtCopyGlob( nGeoIn, nGrpTmp) -- curva left local vGeoLeft = EgtGetNameInGroup( nGeoGrp, WIN_LEFT) if nStartJoint == WIN_PART_JNT.SHORT then local vStartProfiles = EgtGetNameInGroup( nProfileGrp, WIN_PRF_START) for i = 1, #vGeoLeft do local nPrevOutline = EgtGetInfo( vGeoLeft[i], WIN_REF_OUTLINE, 'i') local nCrv = EgtCopyGlob( abs( nPrevOutline), nGrpTmp) local b3Profile = GetProfileLocalBox( vStartProfiles[i]) local dRailDelta = EgtGetInfo( vStartProfiles[i], WIN_RAILDELTA, 'd') or 0 local dOffs = b3Profile:getMin():getX() - dRailDelta if nPrevOutline < 0 then EgtInvertCurve( nCrv) dOffs = - ( b3Profile:getMax():getX() - dRailDelta) end EgtOffsetCurve( nCrv, dOffs) end else for i = 1, #vGeoLeft do EgtCopyGlob( vGeoLeft[i], nGrpTmp) end end -- creo la regione nAreaId = CalcIntersectionRegion( EgtGetAllInGroup( nGrpTmp), nPreviewGrp) EgtErase( nGrpTmp) end -- sistemo la regione local color = EgtGetColor( nPartId) EgtSetColor( nAreaId, color) -- estraggo il contorno local nCompoId = EgtExtractSurfFrChunkLoops( nAreaId, 0, nPreviewGrp) EgtSetColor( nCompoId, EgtStdColor( 'BLACK')) EgtModifyCurveThickness( nCompoId, 0) -- 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, nProfileGrp, nGeoGrp, color) 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 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 nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) or GDB_ID.NULL local nSplitType = EgtGetInfo( nSplitLayerId, 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 -- 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) -- assegno il tipo di profilo alle curve del base outline CalculateAreaProfileType( nFrameId) -- calcolo outline a partire dal base outline CalculateAreaOutline( nFrameId) -- creo pezzi s_nSashNbr = 0 -- resetto il numero di ante del progetto CalculateAreaParts( nFrameId) -- calcolo le spine CalculateAreaDowels( nFrameId) -- calcolo preview 2d se richiesta if s_bCalcPreview then CalcPreview( nFrameId) end end --------------------------------------------------------------------- -- funzione che ricalcola i solidi ( per cambio modalità visualizzazione) function WinCalculate.RecalcSolids( nFrameId) -- scorro tutti i pezzi local nPartId = EgtGetFirstPart() while nPartId do -- se solidi non vanno calcolati elimino semplicemente il gruppo dei solidi da ogni pezzo if not s_bCalcSolid then local nSolidLayId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID) or GDB_ID.NULL EgtErase( nSolidLayId) -- ricalcolo dei solidi else -- se fill, lo uso per ricalcolare strip local nPartType = EgtGetInfo( nPartId, WIN_PART_TYPE, 'i') if nPartType == WIN_PART_TYPES.FILL then local nAreaId = EgtGetInfo( nPartId, WIN_AREA, 'i') local nParentAreaId = EgtGetParent( nAreaId) local nParentOutlineLayId = EgtGetFirstNameInGroup( nParentAreaId, WIN_OUTLINE) local vParentOutlines = EgtGetAllInGroup( nParentOutlineLayId) for i = 1, #vParentOutlines do CreateStripFromOutline( nParentAreaId, vParentOutlines[i]) end -- verifico se solido da calcolare local nSolidLayId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID) if not nSolidLayId then local nOutlineLayId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE) local nGeoLayId = EgtGetFirstNameInGroup( nPartId, WIN_GEO) CalcFillSolid( nPartId, nOutlineLayId, nGeoLayId) end -- se pezzo, ricalcolo il suo solido else -- elimino gruppo dei solidi local nSolidLayId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID) or GDB_ID.NULL EgtErase( nSolidLayId) -- ricalcolo il solido principale local nOutlineId = EgtGetInfo( nPartId, WIN_REF_OUTLINE, 'i') local nSolidId = CalcSolid( nPartId, nOutlineId) -- aggiungo lavorazioni local nProcLayId = EgtGetFirstNameInGroup( nPartId, WIN_PRC) local vProc = EgtGetAllInGroup( nProcLayId) for i = 1, #vProc do local nType = EgtGetInfo( vProc[i], WIN_PRC_FEATURE_TYPE) local nProfilingType = EgtGetInfo( vProc[i], WIN_PRC_PROFILE_INFO) if nType == WIN_PRC_TYPE.HOLE or ( nType == WIN_PRC_TYPE.PROFILING and nProfilingType == WIN_PRC_PROFILE_TYPE.GENERIC) then UpdateSolidWithProcessingSurf( vProc[i], nSolidId, nProcLayId) end end end end nPartId = EgtGetNextPart( nPartId) end -- accessori e ferramenta local nAuxGrp = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AUX) if not s_bCalcSolid then EgtErase( nAuxGrp or GDB_ID.NULL) elseif not nAuxGrp then nAuxGrp = GetAuxLayer() -- ferramenta DrawHardware( nFrameId, nAuxGrp) -- accessori WinCalculate.AddAccessories( nFrameId, true) end end --------------------------------------------------------------------- return WinCalculate