-- -- 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') local s_dDowelTol = 1 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 --------------------------------------------------------------------- -- 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 punto di intersezione fra due curve eventualmente estendendole local function FindIntersectionPoint( nCrv1, nCrv2, ptRef) local ptInt -- se archi, cerco intersezioni tra le circonferenze if EgtGetType( nCrv1) == GDB_TY.CRV_ARC and EgtGetType( nCrv2) == GDB_TY.CRV_ARC then -- trovo intersezione tra le due circonferenze local nCircle1 = EgtCircle( GDB_ID.ROOT, EgtCP( nCrv1), EgtArcRadius( nCrv1)) local nCircle2 = EgtCircle( GDB_ID.ROOT, EgtCP( nCrv2), EgtArcRadius( nCrv2)) ptInt = EgtIP( nCircle1, nCircle2, ptRef) EgtModifyCurveStartPoint( nCrv1, ptInt) EgtModifyCurveEndPoint( nCrv2, ptInt) EgtErase( nCircle1) EgtErase( nCircle2) elseif EgtGetType( nCrv1) == GDB_TY.CRV_ARC or EgtGetType( nCrv2) == GDB_TY.CRV_ARC then local nLine = EgtIf( EgtGetType( nCrv1) == GDB_TY.CRV_LINE, nCrv1, nCrv2) local nArc = EgtIf( nLine == nCrv1, nCrv2, nCrv1) -- creo circonferenza corrispondente all'arco local nCircle = EgtCircle( GDB_ID.ROOT, EgtCP( nArc), EgtArcRadius( nArc)) -- prolungo la linea dal lato opportuno local dDist1 = dist( EgtSP( nLine), ptRef) local dDist2 = dist( EgtEP( nLine), ptRef) if dDist1 < dDist2 then EgtExtendCurveStartByLen( nLine, 10000) else EgtExtendCurveEndByLen( nLine, 10000) end -- trovo le intersezioni tra retta e circonferenza local nId1, nPoints = EgtCurveCurveInters( nCircle, nLine, GDB_ID.ROOT) if nPoints == 1 then ptInt = EgtSP( nId1) EgtErase( nId1) else -- conservo quello più vicino al punto di riferimento local ptInt1 = EgtSP( nId1) local ptInt2 = EgtSP( nId1 + 1) local ptNewRef = EgtIf( nArc == nCrv2, EgtEP( nArc), EgtSP( nArc)) local dDist1 = dist( ptNewRef, ptInt1) local dDist2 = dist( ptNewRef, ptInt2) if dDist1 < dDist2 + GEO.EPS_SMALL then ptInt = ptInt1 else ptInt = ptInt2 end EgtErase( nId1) EgtErase( nId1 + 1) end EgtErase( nCircle) -- allungo l'arco per arrivare al punto di intersezione if nArc == nCrv2 then EgtModifyCurveEndPoint( nArc, ptInt) else EgtModifyCurveStartPoint( nArc, ptInt) end else ptInt = EgtIP( nCrv1, nCrv2, ORIG()) if not ptInt then -- tento estendendo le curve EgtExtendCurveStartByLen( nCrv1, 10000) EgtExtendCurveEndByLen( nCrv1, 10000) EgtExtendCurveStartByLen( nCrv2, 10000) EgtExtendCurveEndByLen( nCrv2, 10000) ptInt = EgtIP( nCrv1, nCrv2, ORIG()) end end return ptInt end --------------------------------------------------------------------- -- funzione che data una lista di curve ordinate che creano una curva chiusa, -- ne estende/taglia i contorni per ottenere una curva chiusa continua local function TrimAndOrientOrderedCurves( vCrvs, bOrient) local IntersCurveList = {} local LastCurveInters -- ciclo sulle curve per ottenere lista intersezioni for i = 1, #vCrvs do -- recupero la precedente local nPrevIndex = EgtIf( i == 1, #vCrvs, i - 1) -- calcolo intersezione local ptInters = FindIntersectionPoint( vCrvs[i], vCrvs[ nPrevIndex], EgtSP( vCrvs[i])) if LastCurveInters then LastCurveInters.EndInters = Point3d( ptInters) end local NewCurveInters = { CurveId = vCrvs[i], StartInters = Point3d( ptInters)} table.insert( IntersCurveList, NewCurveInters) LastCurveInters = NewCurveInters end IntersCurveList[#IntersCurveList].EndInters = IntersCurveList[1].StartInters -- ciclo per tagliare ed orientare for nIntersCurveIndex = 1, #IntersCurveList do local CurveInters = IntersCurveList[nIntersCurveIndex] local dStartParam = EgtCurveParamAtPoint( CurveInters.CurveId, CurveInters.StartInters, 100 * GEO.EPS_SMALL) local dEndParam = EgtCurveParamAtPoint( CurveInters.CurveId, CurveInters.EndInters, 100 * GEO.EPS_SMALL) EgtTrimCurveStartEndAtParam( CurveInters.CurveId, min( dStartParam, dEndParam), max( dStartParam, dEndParam)) if bOrient and dStartParam > dEndParam then EgtInvertCurve( CurveInters.CurveId) end end end --------------------------------------------------------------------- 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, EgtSP( nSplitId)) local dEndInters = EgtCurveParamAtPoint( nSplitId, ptEndInters) EgtTrimCurveEndAtParam( nSplitId, dEndInters) 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 local nBaseOutline = EgtGetInfo( nOutlineId, WIN_COPY, 'i') while not nPartId do -- recupero il base outline da cui deriva nBaseOutline = EgtGetInfo( nBaseOutline, WIN_SOU, 'i') -- 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 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 ( null, mullion, french, mixed) local function GetSplitType( nSplitLayerId) local nSplitType = EgtGetInfo( nSplitLayerId, WIN_SPLITTYPE, 'i') -- se non ha split specifico impostato verifico se ha sash prima o dopo per capire se è di tipo mullion if not nSplitType or nSplitType == WIN_SPLITTYPES.NULL then local nParentAreaId = EgtGetParent( nSplitLayerId) local nParentAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL while nParentAreaId and nParentAreaType ~= WIN_AREATYPES.SASH do nParentAreaId = EgtGetParent( nParentAreaId) nParentAreaType = EgtGetInfo( nParentAreaId or GDB_ID.NULL, WIN_AREATYPE, 'i') or WIN_AREATYPES.NULL end -- se dentro anta è di tipo null, se non è dentro anta devo verificare le tipologie dei figli if not nParentAreaId or nParentAreaType ~= WIN_AREATYPES.SASH then local nSplitId = EgtGetFirstInGroup( nSplitLayerId) local nChildrenType = GetChildrenType( nSplitId) if nChildrenType == WIN_CHILDREN_TYPES.MIXED then nSplitType = WIN_SPLITTYPES.MIXED elseif nChildrenType == WIN_CHILDREN_TYPES.SASH or nChildrenType == WIN_CHILDREN_TYPES.NULL then nSplitType = WIN_SPLITTYPES.MULLION end end end if not nSplitType then nSplitType = WIN_SPLITTYPES.NULL end EgtSetInfo( nSplitLayerId, WIN_SPLITTYPE, nSplitType) return nSplitType end --------------------------------------------------------------------- -- funzione che imposta i tipi di profilo per gli split local function CalcSplitProfileType( nSplitLayerId, nAreaId) local nSplitId = EgtGetFirstInGroup( nSplitLayerId) -- verifico il tipo di split local nSplitType = GetSplitType( nSplitLayerId) if nSplitType == WIN_SPLITTYPES.MULLION then -- verifico direzione per dare nome local vtMedia = ( ( EgtEV( nSplitId) - EgtSV( nSplitId)) / 2) if not vtMedia:normalize() then vtMedia = EgtSV( nSplitId) end if abs( vtMedia:getX()) > abs( vtMedia:getY()) then EgtSetInfo( nSplitId, WIN_PROFILETYPE, WIN_SASH_HORIZONTAL) else EgtSetInfo( nSplitId, WIN_PROFILETYPE, WIN_SASH_VERTICAL) end elseif nSplitType == WIN_SPLITTYPES.NULL then -- verifico se interno ad anta o a frame local nParentAreaId = nAreaId local nParentAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i') while nParentAreaType ~= WIN_AREATYPES.FRAME and nParentAreaType ~= WIN_AREATYPES.SASH do nParentAreaId = EgtGetParent( nParentAreaId) nParentAreaType = EgtGetInfo( nParentAreaId, WIN_AREATYPE, 'i') end -- assegno tipo di profilo allo split if nParentAreaType == WIN_AREATYPES.SASH then EgtSetInfo( nSplitId, WIN_PROFILETYPE, WIN_SASH_SPLIT) else EgtSetInfo( nSplitId, WIN_PROFILETYPE, WIN_FRAME_SPLIT) end elseif nSplitType == WIN_SPLITTYPES.MIXED then EgtSetInfo( nSplitId, WIN_PROFILETYPE, WIN_MIXED_SPLIT) EgtSetInfo( nSplitId, 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( nSplitId, WIN_SASH_CHILDREN, 'i') local nRefCrv = EgtGetNext( nSashChild) or EgtGetPrev( nSashChild) local _, _, nSide = EgtPointCurveDistSide( EgtMP( nRefCrv), nSplitId, Z_AX()) -- se si trova a destra, lo split va invertito if nSide == 1 then EgtInvertCurve( nSplitId) -- scambio le info di intersezione local vStartInters = EgtGetInfo( nSplitId, WIN_SPLIT_STARTINTERS, 'vi') local vEndInters = EgtGetInfo( nSplitId, WIN_SPLIT_ENDINTERS, 'vi') EgtSetInfo( nSplitId, WIN_SPLIT_STARTINTERS, vEndInters) EgtSetInfo( nSplitId, WIN_SPLIT_ENDINTERS, vStartInters) end end -- se split di tipo french non ha profilo assegnato perchè non ha un pezzo associato end --------------------------------------------------------------------- local function FindAdjacentSashType( nSplitId, nSouId) -- recupero l'altro child dello split local vSplitChildren = EgtGetInfo( nSplitId, WIN_CHILD, 'vi') local vChildren = EgtIf( vSplitChildren[1] == nSouId, {vSplitChildren[2]}, {vSplitChildren[1]}) -- cerco il suo primo figlio di tipo sash local nAreaType local nArea repeat vChildren = EgtGetInfo( vChildren[1], WIN_CHILD, 'vi') if vChildren then nArea = EgtGetParent( EgtGetParent( vChildren[1])) nAreaType = EgtGetInfo( nArea or GDB_ID.NULL, WIN_AREATYPE, 'i') end until not vChildren or nAreaType == WIN_AREATYPES.SASH -- recupero il sash type local nSashType = EgtGetInfo( nArea or GDB_ID.NULL, WIN_SASHTYPE, 'i') return nSashType 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 -- verifico se ci sono split e ne assegno il profilo local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT) if nSplitLayerId then CalcSplitProfileType( nSplitLayerId, nAreaId) end -- SPLIT elseif nAreaType == WIN_AREATYPES.SPLIT or nAreaType == WIN_AREATYPES.NULL then -- verifico se ci sono split e ne assegno il profilo local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT) if nSplitLayerId then CalcSplitProfileType( nSplitLayerId, nAreaId) 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 -- 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 -- verifico se bottomrail local nBottomRail = EgtGetInfo( nAreaId, WIN_BOTTOMRAIL, 'i') or 0 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 di tipo french ( e quindi deve avere profilo speciale e.g. battente/ricevente) local nSouId = EgtGetInfo( nOutlineId, WIN_SOU, 'i') local nSouPrevId local nSplitType repeat nSouPrevId = nSouId nSouId = EgtGetInfo( nSouId, WIN_SOU, 'i') if nSouId then local sName = EgtGetName( nSouId) if sName == WIN_SPLIT then local nParentId = EgtGetParent( nSouId) nSplitType = EgtGetInfo( nParentId, WIN_SPLITTYPE, 'i') end end until not nSouId or nSplitType == WIN_SPLITTYPES.FRENCH if nSplitType == WIN_SPLITTYPES.FRENCH then -- setto info sulla curva per ricordare che deriva da un french split ( utile nel calcolo degli outlines) 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, nSouPrevId) 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, nSouPrevId) 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 EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRAME_BOTTOM) else EgtSetInfo( nOutlineId, WIN_PROFILETYPE, WIN_FRAME_TOP) end end end end nOutlineId = EgtGetNext( nOutlineId) end -- verifico se ci sono split local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT) if nSplitLayerId then -- assegno tipo di profilo local nSplitId = EgtGetFirstInGroup( nSplitLayerId) EgtSetInfo( nSplitId, WIN_PROFILETYPE, WIN_SASH_SPLIT) 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 --------------------------------- ---------------------------------------------------------------------------------- -- 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 -- se presente, copio split local nBaseSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT) if nBaseSplitLayerId then local nSplitLayerId = EgtCopy( nBaseSplitLayerId, nAreaId) EgtSetName( nSplitLayerId, WIN_SPLIT) EgtSetStatus( nSplitLayerId, GDB_ST.OFF) local nBaseSplitId = EgtGetFirstInGroup( nBaseSplitLayerId) local nSplitId = EgtGetFirstInGroup( nSplitLayerId) EgtSetInfo( nBaseSplitId, WIN_COPY, nSplitId) EgtSetInfo( nSplitId, WIN_COPY, nBaseSplitId) end -- SPLIT elseif nAreaType == WIN_AREATYPES.SPLIT or nAreaType == WIN_AREATYPES.NULL then -- recupero outline di livello precedente e lo copio pezzo per pezzo 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') local nOutlineId = EgtCopy( nCopyId, nOutlineLayerId) -- se deriva da split devo aggiornare il nome e setto il riferimento local sSouName = EgtGetName( nSouId) if sSouName == WIN_SPLIT then local sBaseName = EgtGetName( nBaseOutlineId) EgtSetName( nOutlineId, sBaseName) EgtSetInfo( nOutlineId, WIN_REF_SPLIT, nSouId) end -- sistemo le info EgtSetInfo( nOutlineId, WIN_COPY, nBaseOutlineId) EgtSetInfo( nBaseOutlineId, WIN_COPY, nOutlineId) EgtRemoveInfo( nOutlineId, WIN_CHILD) nBaseOutlineId = EgtGetNext( nBaseOutlineId) end -- taglio tutti i contorni TrimAndOrientOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), true) -- se presente, copio split local nBaseSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT) if nBaseSplitLayerId then local nSplitLayerId = EgtCopy( nBaseSplitLayerId, nAreaId) EgtSetName( nSplitLayerId, WIN_SPLIT) EgtSetStatus( nSplitLayerId, GDB_ST.OFF) local nBaseSplitId = EgtGetFirstInGroup( nBaseSplitLayerId) local nSplitId = EgtGetFirstInGroup( nSplitLayerId) EgtSetInfo( nBaseSplitId, WIN_COPY, nSplitId) EgtSetInfo( nSplitId, WIN_COPY, nBaseSplitId) EgtRemoveInfo( nSplitId, WIN_SOU) -- lo taglio con outline TrimSplitWithOutline( nSplitId) -- recupero tipo di profilo local sSplitProfile = EgtGetInfo( nSplitId, WIN_PROFILETYPE) -- se split interno ad anta devo alzarlo in z come l'anta che lo contiene if sSplitProfile == WIN_SASH_SPLIT then -- recupero l'anta local nSashAreaId = EgtGetParent( nAreaId) local nAreaType = EgtGetInfo( nSashAreaId, WIN_AREATYPE, 'i') while nAreaType ~= WIN_AREATYPES.SASH do nSashAreaId = EgtGetParent( nSashAreaId) nAreaType = EgtGetInfo( nSashAreaId, WIN_AREATYPE, 'i') end local nSashBaseOutlineLayerId = EgtGetFirstNameInGroup( nSashAreaId, WIN_AREAOUTLINE) local nSashBaseOutlineId = EgtGetFirstInGroup( nSashBaseOutlineLayerId) -- recupero il profilo dell'anta 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 local dSashZOffset = EgtGetInfo( nSashProfileId, WIN_DELTA, 'd') -- sposto Split in Z EgtMove( nSplitId, Z_AX() * dSashZOffset) end 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') local nOutlineId = EgtCopy( nCopyId, nOutlineLayerId) -- 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_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 -- se outline non è segmento battente o ricevente necessita di offset if not bOnFrenchSplit then -- 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) end nBaseOutlineId = EgtGetNext( nBaseOutlineId) end -- accorcio gli offset TrimAndOrientOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), true) -- se presente, copio split local nBaseSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_BASESPLIT) if nBaseSplitLayerId then local nBaseSplitId = EgtGetFirstInGroup( nBaseSplitLayerId) -- creo copia local nSplitLayerId = EgtCopy( nBaseSplitLayerId, nAreaId) EgtSetName( nSplitLayerId, WIN_SPLIT) EgtSetStatus( nSplitLayerId, GDB_ST.OFF) local nSplitId = EgtGetFirstInGroup( nSplitLayerId) EgtSetInfo( nBaseSplitId, WIN_COPY, nSplitId) EgtSetInfo( nSplitId, WIN_COPY, nBaseSplitId) EgtRemoveInfo( nSplitId, WIN_SOU) -- la taglio con outline TrimSplitWithOutline( nSplitId) -- calcolo offset sulla z dal profilo dell'anta local nPrevId = EgtGetInfo( nBaseSplitId, WIN_SPLIT_STARTINTERS, 'i') local sSashProfile = EgtGetInfo( nPrevId, WIN_PROFILETYPE) local nSashProfileId = EgtGetFirstNameInGroup( nSashProfileLayerId, sSashProfile) local dSplitZOffset = EgtGetInfo( nSashProfileId, WIN_DELTA, 'd') -- sposto split in Z EgtMove( nSplitId, Z_AX() * dSplitZOffset) end -- FILL elseif nAreaType == WIN_AREATYPES.FILL then -- ciclo su BaseArea riempimento 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') local nOutlineId = EgtCopy( nCopyId, nOutlineLayerId) -- sistemo le info EgtSetInfo( nBaseOutlineId, WIN_COPY, nOutlineId) EgtSetInfo( nOutlineId, WIN_COPY, nBaseOutlineId) -- recupero a ritroso il profilo dell'elemento su cui poggia ( anta, split o frame) local nParentBaseOutlineId = nSouId local sParentProfile = EgtGetInfo( nParentBaseOutlineId, WIN_PROFILETYPE) while not sParentProfile and nParentBaseOutlineId do nParentBaseOutlineId = EgtGetInfo( nParentBaseOutlineId, WIN_SOU , 'i') sParentProfile = EgtGetInfo( nParentBaseOutlineId or GDB_ID.NULL, WIN_PROFILETYPE) end local nParentOutlineId = EgtGetInfo( nParentBaseOutlineId, WIN_COPY, 'i') local nParentProfileId = GetOutlineProfileId( nParentOutlineId, true) sParentProfile = EgtGetName( nParentProfileId) -- calcolo il box del riferimento del profilo del frame local b3FrameProfile = GetProfileLocalBox( nParentProfileId) -- calcolo offset perpendicolare e sulla z dell'anta local dOverlap = EgtGetInfo( nParentProfileId, WIN_FILLOVERLAP, 'd') local bMixedSplit = ( EgtGetInfo( nParentOutlineId, WIN_PRF_CHANGE, 'b') or false) and EgtGetName( nParentOutlineId) == WIN_SPLIT local dDimRef = EgtIf( bMixedSplit, b3FrameProfile:getMax():getX(), b3FrameProfile:getMin():getX()) local dFillPerpOffset = abs( dDimRef) - dOverlap if sParentProfile == 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 -- faccio offset EgtOffsetCurve( nOutlineId, - dFillPerpOffset) -- movimento in z local dFillZOffset = EgtGetInfo( nParentProfileId, WIN_FILLDELTA, 'd') EgtMove( nOutlineId, Z_AX() * dFillZOffset) nBaseOutlineId = EgtGetNext( nBaseOutlineId) end -- accorcio gli offset TrimAndOrientOrderedCurves( EgtGetAllInGroup( nOutlineLayerId), true) 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 calcola gli outline precedenti e successivi nel caso di split local function GetSplitOtherOutline( nSplitId, nSurfSplit, nOutlineId, bPrevOrNext) local vOutlineIds = {} -- verifico se devo controllare la curva precedente o successiva dell'outline corrente local nCrv local bPrevOutline = false local ptRef = EgtIf( bPrevOrNext, EgtSP( nSplitId), EgtEP( nSplitId)) local dPar = EgtCurveParamAtPoint( nOutlineId, ptRef) local dLenInt = EgtCurveLengthAtParam( nOutlineId, dPar) local dLenTot = EgtCurveLength( nOutlineId) -- se l'intersezione è più vicina alla fine dell'outline devo controllare il suo next, altrimenti il suo prev if abs( dLenTot - dLenInt) < dLenInt then nCrv = EgtGetNext( nOutlineId) or EgtGetFirstInGroup( EgtGetParent( nOutlineId)) else bPrevOutline = true nCrv = EgtGetPrev( nOutlineId) or EgtGetLastInGroup( EgtGetParent( nOutlineId)) end -- recupero il geo associato e costruisco superficie test local nPartId = FindAssociatedPart( nCrv, true) local nGeoId = EgtGetFirstNameInGroup( nPartId, WIN_GEO) local nGeoOut = EgtGetFirstNameInGroup( nGeoId, WIN_GEO_OUT) local nGeoIn = EgtGetFirstNameInGroup( nGeoId, WIN_GEO_IN) local nCrv1 = EgtCopyGlob( nGeoOut, nGeoId) local nCrv2 = EgtCopyGlob( nGeoIn, nGeoId) local nCompoTest = EgtCurveCompo( nGeoId, nCrv1) local dParTest = 0.2 if bPrevOutline then -- considero solo la parte finale del pezzo EgtTrimCurveStartAtParam( nCompoTest, 1 - dParTest) EgtAddCurveCompoLine( nCompoTest, EgtSP( nCrv2)) EgtTrimCurveEndAtParam( nCrv2, dParTest) else -- considero solo la parte iniziale del pezzo EgtTrimCurveEndAtParam( nCompoTest, dParTest) EgtTrimCurveStartAtParam( nCrv2, 1 - dParTest) EgtAddCurveCompoLine( nCompoTest, EgtSP( nCrv2)) end EgtAddCurveCompoCurve( nCompoTest, nCrv2) EgtCloseCurveCompo( nCompoTest) local nSurfTest = EgtSurfFlatRegion( nGeoId, { nCompoTest}) -- verifico se le due regioni interferiscono if EgtSurfFrTestExternal( nSurfSplit, nSurfTest) then vOutlineIds = { nOutlineId} else -- aggiungo la curva trovata tra le curve di outline da considerare rispettando l'ordinamento if bPrevOutline then vOutlineIds = { nCrv, nOutlineId} else vOutlineIds = { nOutlineId, nCrv} end end EgtErase( nCompoTest) EgtErase( nSurfTest) return vOutlineIds 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 local vPrevBaseOutlineId = EgtGetInfo( nOutlineId, WIN_SPLIT_STARTINTERS, 'vi') for i = 1, #vPrevBaseOutlineId do -- recupero l'outline associato al base outline che lo taglia table.insert( vPrevOutlineId, EgtGetInfo( vPrevBaseOutlineId[i], WIN_COPY, 'i')) end local vNextBaseOutlineId = EgtGetInfo( nOutlineId, WIN_SPLIT_ENDINTERS, 'vi') for i = 1, #vNextBaseOutlineId do table.insert( vNextOutlineId, EgtGetInfo( vNextBaseOutlineId[i], WIN_COPY, 'i')) end -- se lo split è tagliato da una sola curva di base outline, verifico se coinvolge altre curve if #vPrevBaseOutlineId == 1 or #vNextBaseOutlineId == 1 then -- costruisco una regione approssimata per il pezzo dello split local nGrp = EgtGetParent( nOutlineId) local nSplitProfileId = GetOutlineProfileId( nOutlineId, false) local b3Profile = GetProfileLocalBox( nSplitProfileId) local nCrvOut = EgtCopyGlob( nOutlineId, nGrp) local nCrvIn = EgtCopyGlob( nOutlineId, nGrp) EgtOffsetCurve( nCrvOut, b3Profile:getMax():getX()) EgtOffsetCurve( nCrvIn, b3Profile:getMin():getX()) EgtInvertCurve( nCrvIn) local nCompoTest = EgtCurveCompo( nGrp, nCrvOut) EgtAddCurveCompoLine( nCompoTest, EgtSP( nCrvIn)) EgtAddCurveCompoCurve( nCompoTest, nCrvIn) EgtCloseCurveCompo( nCompoTest) local nSurfTest = EgtSurfFlatRegion( nGrp, nCompoTest) -- se necessario aggiorno il prev if #vPrevBaseOutlineId == 1 and EgtGetName( vPrevBaseOutlineId[1]) ~= WIN_SPLIT then vPrevOutlineId = GetSplitOtherOutline( nOutlineId, nSurfTest, vPrevOutlineId[1], true) end -- se necessario aggiorno il next if #vNextOutlineId == 1 and EgtGetName( vNextBaseOutlineId[1]) ~= WIN_SPLIT then vNextOutlineId = GetSplitOtherOutline( nOutlineId, nSurfTest, vNextOutlineId[1], false) end EgtErase( nSurfTest) EgtErase( nCompoTest) end end return vPrevOutlineId, vNextOutlineId 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 crea la superficie corrispondente al Geo di un pezzo gestendo i casi di autointersezione local function CreateGeoArea( nGeoLayId, nDestLayId) -- recupero le curve left e right e verifico se hanno orientamento coerente ( quindi non generano autointersezioni) local bAutointers = false local vLeft = EgtGetNameInGroup( nGeoLayId, WIN_LEFT) local vRight = EgtGetNameInGroup( nGeoLayId, WIN_RIGHT) if #vLeft == 2 and not AreSamePointApprox( EgtEP( vLeft[1]), EgtSP( vLeft[2])) then bAutointers = true -- se orientamento non coerente devo ignorare la prima curva vLeft[1] = GDB_ID.NULL end if #vRight == 2 and not AreSamePointApprox( EgtEP( vRight[1]), EgtSP( vRight[2])) then bAutointers = true -- se orientamento non coerente devo ignorare la seconda curva vRight[2] = GDB_ID.NULL end local nCompoId if not bAutointers then -- se no autointersezioni costruisco il bordo del geo usando direttamente le sue curve local vCrvs = EgtGetAllInGroup( nGeoLayId) nCompoId = EgtCurveCompo( nDestLayId, vCrvs, false) else -- nel caso di autointersezione devo ignorare le curve left e right con orientamento non coerente local vGeoCrvs = {} local nOutId = EgtGetFirstNameInGroup( nGeoLayId, WIN_GEO_OUT) vGeoCrvs[1] = EgtCopyGlob( nOutId, nDestLayId) for i = 1, #vRight do if vRight[i] ~= GDB_ID.NULL then table.insert( vGeoCrvs, EgtCopyGlob( vRight[i], nDestLayId)) end end local nInId = EgtGetFirstNameInGroup( nGeoLayId, WIN_GEO_IN) table.insert( vGeoCrvs, EgtCopyGlob( nInId, nDestLayId)) for i = 1, #vLeft do if vLeft[i] ~= GDB_ID.NULL then table.insert( vGeoCrvs, EgtCopyGlob( vLeft[i], nDestLayId)) end end -- taglio le curve TrimAndOrientOrderedCurves( vGeoCrvs, false) -- creo compo nCompoId = EgtCurveCompo( nDestLayId, vGeoCrvs) end local nArea = EgtSurfFlatRegion( nDestLayId, nCompoId) EgtErase( nCompoId) return nArea 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( 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( 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( 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( vPrevOutlineId[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 nCurrCurveId = EgtCopy( nOutlineId, nGeoLayerId) EgtOffsetCurve( nCurrCurveId, dCurrOffset) EgtSetName( nCurrCurveId, WIN_GEO_OUT) local nSemiProfileOut = EgtGetFirstNameInGroup( nCurrProfileId, WIN_OUT) or EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN .. '1') EgtSetInfo( nCurrCurveId, WIN_SEMI_PROFILE, nSemiProfileOut) -- cruva in local nCurrOffsetId = EgtCopy( nOutlineId, nGeoLayerId) EgtOffsetCurve( nCurrOffsetId, dCurrOffset - b3CurrProfileFrame:getDimX()) EgtInvertCurve( nCurrOffsetId) EgtSetName( nCurrOffsetId, WIN_GEO_IN) local nSemiProfileIn = EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN) or EgtGetFirstNameInGroup( nCurrProfileId, WIN_IN .. '2') or EgtGetFirstNameInGroup( nCurrProfileId, WIN_MIXED_COMMON .. WIN_IN) EgtSetInfo( nCurrOffsetId, WIN_SEMI_PROFILE, nSemiProfileIn) -- 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( 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( vPrevOutlineId[i], nGeoLayerId) if nStartPartJointType == WIN_PART_JNT.SHORT then local sCtrIn = GetProfileCtrIn( 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( 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( vNextOutlineId[i], nGeoLayerId) if nEndPartJointType == WIN_PART_JNT.SHORT then local sCtrIn = GetProfileCtrIn( 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, nCurrOffsetId, GDB_IN.BEFORE) end local vIds = EgtGetAllInGroup( nGeoLayerId) -- trim delle curve TrimAndOrientOrderedCurves( vIds, false) -- 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) 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 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 dal vettore local vJoints = EgtGetInfo( nOutlineLayerId, WIN_JOINTS, 'vi') nStartJointType = vJoints[nOutlineCrvNbr] nEndJointType = vJoints[nOutlineCrvNbr + 1] or vJoints[1] -- 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( vPrevOutlineId[1]), EgtSV( nOutlineId)) or EgtGetName( nOutlineId) == EgtGetName( vPrevOutlineId[1])) then nStartJointType = WIN_JNT.ANGLED end if nEndJointType ~= WIN_JNT.ANGLED and ( AreSameVectorApprox( EgtEV( nOutlineId), EgtSV( vNextOutlineId[1])) or EgtGetName( nOutlineId) == EgtGetName( vNextOutlineId[1])) then nEndJointType = WIN_JNT.ANGLED end end -- correzione per caso del triangolo local nProfileTypeS = nProfileType local nProfileTypeE = nProfileType if nProfileType == WIN_PRF.TOP then -- se lato top contro lato bottom, il lato top deve essere trattato come un left/right nel calcolo della giunzione if EgtGetName( vPrevOutlineId[1]) == WIN_BOTTOM then nProfileTypeS = WIN_PRF.LEFT end if EgtGetName( vNextOutlineId[1]) == WIN_BOTTOM then nProfileTypeE = WIN_PRF.LEFT 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( vPrevOutlineId[1], WIN_THRESHOLD, 'b') then nStartPartJointType = WIN_JNT.FULL end if EgtGetInfo( vNextOutlineId[1], WIN_THRESHOLD, 'b') then nEndPartJointType = WIN_JNT.FULL end -- salvo il valore di start joint su outline per calcolo dowels -- 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) 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 nOutlineId = EgtGetFirstInGroup( nOutlineLayerId) while nOutlineId do EgtCopy( nOutlineId, nGeoLayerId) nOutlineId = EgtGetNext( nOutlineId) 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_GEOWIDTH, dGlassThickness) 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 EgtSetName( nId, 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 EgtSetName( nId, 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 il suo eventuale split local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) if nSplitLayerId then local nSplitId = EgtGetFirstInGroup( nSplitLayerId) table.insert( vSplitIds, nSplitId) 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 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 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( 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( 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 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 = CreateGeoArea( nGeoLayerId, nProcLayerId) EgtSurfFrOffset( nSurfGeo, 50 * GEO.EPS_SMALL) -- 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 local vGeoCrvs = EgtGetAllInGroup( nGeoLayerId) for i = 1, #vGeoCrvs do -- copio curva local nCrvId = EgtCopyGlob( vGeoCrvs[i], nProcLayerId) EgtModifyCurveThickness( nCrvId, 0) -- recupero il semiprofilo associato local nSemiProfileId = EgtGetInfo( nCrvId, WIN_SEMI_PROFILE, 'i') -- 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 EgtErase( nSurfGeo) -- 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) EgtSetName( nGeoRawLayerId, WIN_GEO_RAW) EgtSetStatus( nGeoRawLayerId, GDB_ST.OFF) -- recupero le curve del geo local nOut = EgtGetFirstNameInGroup( nGeoRawLayerId, WIN_GEO_OUT) local nIn = EgtGetFirstNameInGroup( nGeoRawLayerId, WIN_GEO_IN) local vRight = EgtGetNameInGroup( nGeoRawLayerId, WIN_GEO_RIGHT) local vLeft = EgtGetNameInGroup( nGeoRawLayerId, WIN_GEO_LEFT) -- verifico se le curve right e left hanno direzioni coerenti if #vRight == 2 and not AreSamePointApprox( EgtEP( vRight[1]), EgtSP( vRight[2])) then -- la seconda curva va ignorata EgtErase( vRight[2]) vRight = { vRight[1]} end if #vLeft == 2 and not AreSamePointApprox( EgtEP( vLeft[1]), EgtSP( vLeft[2])) then -- la prima curva va ignorata EgtErase( vLeft[1]) vLeft = { vLeft[2]} end -- 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') -- applico i sovramateriali EgtOffsetCurve( nOut, dOvermatOut) for i = 1, #vRight do EgtOffsetCurve( vRight[i], dOvermatRight) end EgtOffsetCurve( nIn, dOvermatIn) for i = 1, #vLeft do EgtOffsetCurve( vLeft[i], dOvermatLeft) end -- creo la composita del grezzo a partire dalle curve local vCrvs = EgtGetAllInGroup( nGeoRawLayerId) TrimAndOrientOrderedCurves( vCrvs, false) 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 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 local nRefSplitId = EgtGetInfo( nOutlineId, WIN_REF_SPLIT, 'i') if nRefSplitId then -- recupero base outline per confrontarlo con lo split da cui deriva local nBaseOutlineId = EgtGetInfo( nOutlineId, WIN_COPY, 'i') -- recupero vettore tangente nel punto medio del base outline local ptM = EgtMP( nBaseOutlineId) local vtM = EgtMV( nBaseOutlineId) -- recupero vettore tangente nello stesso punto della curva di split da cui deriva local dRefSplitPar = EgtCurveParamAtPoint( nRefSplitId, ptM) local vtMRefSplit = EgtUV( nRefSplitId, dRefSplitPar, -1) -- se i due vettori non sono orientati nella stessa direzione inverto la guida if not AreSameVectorApprox( vtM, vtMRefSplit) then EgtInvertCurve( nGuideId) end 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 crea la superficie di trim per il solido local function CreateTrimSurf( nGeoId, nProfileId, 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 b3Profile = GetProfileLocalBox( nProfileId) local nTrimSurf = EgtSurfTmByExtrusion( nLayerId, nGuideId, - Z_AX() * ( b3Profile:getDimY() + 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 -- recupero la curva di outline associata alla curva di geo local nRefOutline = EgtGetInfo( nGeoId, WIN_REF_OUTLINE, 'i') -- calcolo la superficie di estrusione return CreateProfileSurf( nRefOutline, nProfileId, 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 nStartProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_START) local nTrimSurfStart = CreateTrimSurf( nPrevGeoId, nStartProfileId, dGeoWidth, nSolidLayerId) EgtSetName( nTrimSurfStart, WIN_SRF_START) EgtSetStatus( nTrimSurfStart, GDB_ST.OFF) EgtSurfTmIntersect( vMainExtrusions[1], nTrimSurfStart) -- c) TRIM END local nNextGeoId = EgtGetFirstNameInGroup( nGeoLayerId, WIN_GEO_RIGHT) local nEndProfileId = EgtGetFirstNameInGroup( nProfileLayerId, WIN_PRF_END) local nTrimSurfEnd = CreateTrimSurf( nNextGeoId, nEndProfileId, dGeoWidth, nSolidLayerId) EgtSetName( nTrimSurfEnd, WIN_SRF_END) EgtSetStatus( nTrimSurfEnd, GDB_ST.OFF) EgtSurfTmIntersect( vMainExtrusions[1], nTrimSurfEnd) 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) EgtSetName( nStmTrimStart, WIN_SRF_START) EgtSetStatus( nStmTrimStart, GDB_ST.OFF) EgtSurfTmIntersect( nMainExtrusionId, 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) EgtSetName( nStmTrimEnd, WIN_SRF_END) EgtSetStatus( nStmTrimEnd, GDB_ST.OFF) EgtSurfTmIntersect( nMainExtrusionId, nStmTrimEnd) 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, 2 * 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 sullo start local vPrevGeoId = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_LEFT) local vStartProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_START) for i = 1, #vPrevGeoId do -- creo la superficie di trim local nTrimSurf = CreateTrimSurf( vPrevGeoId[i], vStartProfileId[i], dGeoWidth, nSolidLayerId) EgtSetStatus( nTrimSurf, GDB_ST.OFF) EgtSetName( nTrimSurf, WIN_SRF_START) -- eseguo intersezione per ottenere un solido unico ( tagliare le due superfici con EgtSurfTmCut e poi unirle potrebbe creare piccoli buchi legati alle diverse approssimazioni) EgtSurfTmIntersect( nMainExtrusionId, nTrimSurf) end -- c) trim con i controprofili sull'end local vNextGeoId = EgtGetNameInGroup( nGeoLayerId, WIN_GEO_RIGHT) local vEndProfileId = EgtGetNameInGroup( nProfileLayerId, WIN_PRF_END) for i = 1, #vNextGeoId do -- creo la superficie di trim local nTrimSurf = CreateTrimSurf( vNextGeoId[i], vEndProfileId[i], dGeoWidth, nSolidLayerId) EgtSetStatus( nTrimSurf, GDB_ST.OFF) EgtSetName( nTrimSurf, WIN_SRF_END) -- eseguo intersezione per ottenere un solido unico EgtSurfTmIntersect( nMainExtrusionId, nTrimSurf) end end --------------------------------------------------------------------- -- funzione che crea il solido del Fill local function CalcFillSolid( nPartId, nOutlineLayerId, nGeoLayerId) -- creo layer per solido local nSolidLayerId = EgtGroup( nPartId) EgtSetName( nSolidLayerId, WIN_SOLID) -- creo compo di outline local vOutlineList = EgtGetAllInGroup( nOutlineLayerId) local nCompoOutlineId = EgtCurveCompoByChain( nSolidLayerId, vOutlineList, EgtSP( vOutlineList[1]), false) -- recupero spessore vetro local dGlassThickness = EgtGetInfo( nGeoLayerId, WIN_GEOWIDTH, 'd') local nSurfId = EgtSurfTmByRegionExtrusion( nSolidLayerId, nCompoOutlineId, Z_AX() * dGlassThickness) EgtErase( nCompoOutlineId) end ---------------------------------------------------------------------------------- ---------------------------------- DOWELS ---------------------------------------- ---------------------------------------------------------------------------------- -- funzione che sottrae il dowel al solido local function UpdateSolidWithDowel( nDowelId, nSolidId, vtDir, dLen, nLayerId) -- creo il solido del dowel a partire dalla circonferenza che lo definisce local nDowelSolidId if s_bSimplSolid then -- se solidi semplificati creo foro grossolano per velocizzare operazioni di subtract local nDowelApprox = EgtCopyGlob( nDowelId, nLayerId) EgtApproxCurve( nDowelApprox, GDB_CA.LINES, 0.2) nDowelSolidId = EgtSurfTmByRegionExtrusion( nLayerId, nDowelApprox, vtDir * dLen) EgtErase( nDowelApprox) else nDowelSolidId = EgtSurfTmByRegionExtrusion( nLayerId, nDowelId, vtDir * dLen) end -- sottraggo il dowel al solido EgtSurfTmSubtract( nSolidId, nDowelSolidId) EgtErase( nDowelSolidId) end --------------------------------------------------------------------- -- 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 UpdateSolidWithDowel( nDowelId, nMainExtrusionId, vtDir, dLen, 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 nOrigSurf = EgtGetFirstNameInGroup( nPrevSolidLay, WIN_SRF_END) 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 nOrigSurf = EgtGetFirstNameInGroup( nSolidLay, WIN_SRF_START) 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 nOrigSurf = EgtGetFirstNameInGroup( nSolidLay, WIN_SRF_START) 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 nOrigSurf = EgtGetFirstNameInGroup( nPrevSolidLay, WIN_SRF_END) 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, vOutlines, 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, vTestSurf if s_bCalcSolid then local nSplitSolidLayerId = EgtGetFirstNameInGroup( nSplitPart, WIN_SOLID) nSplitSolidId = EgtGetFirstNameInGroup( nSplitSolidLayerId, WIN_SRF_MAIN) vTestSurf = EgtGetNameInGroup( nSplitSolidLayerId, EgtIf( bStartOrEnd, WIN_SRF_START, WIN_SRF_END)) end -- indviduo il lato su cui andranno i dowels local sSplitDowelSide = WIN_PRC_SIDETYPE.RIGHT if bStartOrEnd then sSplitDowelSide = WIN_PRC_SIDETYPE.LEFT end -- creo la superficie di test per verificare se dowel interno al pezzo local nSplitGeo = EgtGetFirstNameInGroup( nSplitPart, WIN_GEO) local nSplitSurf = CreateGeoArea( nSplitGeo, nSplitLayerId) local ptRef = EgtIf( bStartOrEnd, EgtSP( nSplitId), EgtEP( nSplitId)) -- se il bottom è soglia va ignorato local nStartIdx = EgtIf( EgtGetInfo( vOutlines[1], WIN_THRESHOLD, 'b'), 2, 1) for i = nStartIdx, #vOutlines do -- recupero il pezzo associato e il suo outline di riferimento local nPartId = FindAssociatedPart( vOutlines[i], 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 nTestSurf = EgtCopyGlob( vTestSurf[i], 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 -- creo la superficie di test per verificare se dowel interno al pezzo local nGeo = EgtGetFirstNameInGroup( nPartId, WIN_GEO) local nSurf = CreateGeoArea( nGeo, nLayerId) -- 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) EgtErase( nSurf) end end EgtErase( nSplitSurf) 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 end -- verifico se c'e' uno split local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) if nSplitLayerId then 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 nSplitId = EgtGetFirstInGroup( nSplitLayerId) -- start local vPrevOutlineId = EgtGetInfo( nSplitId, WIN_PREV_OUTLINES, 'vi') CalcSplitDowels( nSplitId, vPrevOutlineId, true) -- end local vNextOutlineId = EgtGetInfo( nSplitId, WIN_NEXT_OUTLINES, 'vi') CalcSplitDowels( nSplitId, vNextOutlineId, false) 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 -- ( analoga a GetProfileCtrIn) local function GetStripNearestToOutline( nPrevProfileId, nPrevOutlineId, nOutlineId) local sStripName = WIN_STRIP -- gestione particolare del caso di profilo di split if not EgtGetFirstNameInGroup( nPrevProfileId, sStripName) then -- recupero la curva di base outline da cui deriva il precedente local nPrevSouId = EgtGetInfo( nPrevOutlineId, WIN_COPY, 'i') local sPrevSouName repeat nPrevSouId = EgtGetInfo( nPrevSouId, WIN_SOU, 'i') sPrevSouName = EgtGetName( nPrevSouId or GDB_ID.NULL) until not nPrevSouId or sPrevSouName == WIN_SPLIT -- verifico da quale lato si trova la curva per decidere quale controprofilo considerare local _, _, nSide = EgtPointCurveDistSide( EgtMP( nOutlineId), nPrevSouId, Z_AX()) if nSide == 1 then sStripName = WIN_STRIP .. '1' -- dx else sStripName = WIN_STRIP .. '2' -- sx end end if s_bSimplSolid then sStripName = WIN_SIMPLIFIED .. sStripName end local nStripId = EgtGetFirstNameInGroup( nPrevProfileId, sStripName) return nStripId end --------------------------------------------------------------------- -- funzione che crea le linee di contorno massima e minima degli strip local function CreateStripGuideLines( nOutlineId, nStripId, nProfileId, nSolidLayerId) -- recupero il frame del profilo local nProfileFrameId = EgtGetFirstNameInGroup( nProfileId, WIN_SECTIONFRAME) local frProfile = EgtFR( nProfileFrameId, GDB_ID.ROOT) -- se profilo e direzione prev uguali ( Prev e' Split), cambio segno all'offset di modo che rimanga sempre dalla stessa parte local vtE = EgtEV( nOutlineId) local bMainInvertOffset = AreSameVectorApprox( frProfile:getVersZ(), vtE) -- calcolo BBox 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 dMainStripMinDelta = EgtIf( bMainInvertOffset, - b3MainStrip:getMax():getX() + dDelta, b3MainStrip:getMin():getX() - dDelta) local dMainStripMaxDelta = EgtIf( bMainInvertOffset, - b3MainStrip:getMin():getX() + dDelta, b3MainStrip:getMax():getX() - dDelta) local nStripMinOffsetId = EgtCopy( nOutlineId, nSolidLayerId) EgtOffsetCurve( nStripMinOffsetId, dMainStripMinDelta) local nStripMaxOffsetId = EgtCopy( nOutlineId, nSolidLayerId) EgtOffsetCurve( nStripMaxOffsetId, dMainStripMaxDelta) return nStripMinOffsetId, nStripMaxOffsetId end --------------------------------------------------------------------- -- funzione che crea gli Strip local function CreateStripFromOutline( nAreaId, nOutlineId) -- recupero il pezzo associato ( prendendo quello di bottomrail se esiste) local nPartId = FindAssociatedPart( nOutlineId, true) -- recupero layer per solido e per profili di estrusione local nSolidLayerId = EgtGetFirstNameInGroup( nPartId, WIN_SOLID) -- recupero gli outline precedente e successivo ( non serve utilizzare un WIN_PRF accurato perchè conta solo sia diverso da split) local nOutlineLayerId = EgtGetParent( nOutlineId) local vPrevOutlineId, vNextOutlineId = GetPrevNextOutline( WIN_PRF.NULL, nOutlineId, nOutlineLayerId) -- recupero i pezzi precedente e successivo, prendendo eventualmente quelli di bottomrail local nPrevPartId = FindAssociatedPart( vPrevOutlineId[1], true) local nNextPartId = FindAssociatedPart( vNextOutlineId[1], true) -- recupero profilo e controprofili local nMainProfileLayerId = EgtGetFirstNameInGroup( nPartId, WIN_PROFILE) local nMainProfileId = EgtGetFirstNameInGroup( nMainProfileLayerId, WIN_PRF_MAIN) local nPrevProfileLayerId = EgtGetFirstNameInGroup( nPrevPartId, WIN_PROFILE) local nStartProfileId = EgtGetFirstNameInGroup( nPrevProfileLayerId, WIN_PRF_MAIN) local nNextProfileLayerId = EgtGetFirstNameInGroup( nNextPartId, WIN_PROFILE) local nEndProfileId = EgtGetFirstNameInGroup( nNextProfileLayerId, WIN_PRF_MAIN) -- a) estrudo il fermavetro -- recupero guida Main local nGuideId = EgtGetFirstNameInGroup( nSolidLayerId, WIN_MAINGUIDE) -- recupero strip piu' vicino a prev outline e lo posiziono sulla guida local nMainStripId = GetStripNearestToOutline( nMainProfileId, nOutlineId, vPrevOutlineId[1]) local nSectionId = EgtCopyGlob( nMainStripId, nSolidLayerId) local nFrameProfileId = EgtGetFirstNameInGroup( nMainProfileId, WIN_SECTIONFRAME) local frOrig = EgtFR( nFrameProfileId, GDB_ID.ROOT) frOrig:invert() local frDest = Frame3d( EgtSP( nGuideId), - EgtSV( nGuideId)) EgtTransform( nSectionId, frOrig) EgtTransform( nSectionId, frDest) -- creo estrusione local nMainStripExtrusionId = EgtSurfTmSwept( nSolidLayerId, nSectionId, nGuideId, false, WIN_SURF_APPROX) EgtSetName( nMainStripExtrusionId, WIN_SRF_STRIP) -- b) taglio con start -- recupero strip dello start piu' vicino ad outline local nStartStripId = GetStripNearestToOutline( nStartProfileId, vPrevOutlineId[1], nOutlineId) -- disegno guida start per lo strip trovando le intersezioni degli outline minimi e massimi tra MainStrip e StartStrip local nMainStripMinOffsetId, nMainStripMaxOffsetId = CreateStripGuideLines( nOutlineId, nMainStripId, nMainProfileId, nSolidLayerId) local nStartStripMinOffsetId, nStartStripMaxOffsetId = CreateStripGuideLines( vPrevOutlineId[1], nStartStripId, nStartProfileId, nSolidLayerId) local ptStripMinStart = FindIntersectionPoint( nMainStripMinOffsetId, nStartStripMinOffsetId, EgtSP( nMainStripMinOffsetId)) local ptStripMaxStart = FindIntersectionPoint( nMainStripMaxOffsetId, nStartStripMaxOffsetId, EgtSP( nMainStripMinOffsetId)) local nStartStripGuideId = EgtLine( nSolidLayerId, ptStripMinStart, ptStripMaxStart) EgtExtendCurveStartByLen( nStartStripGuideId, 10) EgtExtendCurveEndByLen( nStartStripGuideId, 10) EgtMove( nStartStripGuideId, Z_AX()) -- estrudo Strip start local b3RefStartProfile = GetProfileLocalBox( nStartProfileId) local nStartStripExtrusionId = EgtSurfTmByExtrusion( nSolidLayerId, nStartStripGuideId, - Z_AX() * ( b3RefStartProfile:getDimY() + 2), WIN_SURF_APPROX) EgtInvertSurf( nStartStripExtrusionId) -- intersezione con main EgtSurfTmIntersect( nMainStripExtrusionId, nStartStripExtrusionId) -- c) taglio con end -- recupero strip piu' vicino ad outline local nEndStripId = GetStripNearestToOutline( nEndProfileId, vNextOutlineId[1], nOutlineId) -- disegno guida end per lo strip trovando le intersezioni degli outline minimi e massimi tra MainStrip ed EndStrip local nEndStripMinOffsetId, nEndStripMaxOffsetId = CreateStripGuideLines( vNextOutlineId[1], nEndStripId, nEndProfileId, nSolidLayerId) local ptStripMinEnd = FindIntersectionPoint( nMainStripMinOffsetId, nEndStripMinOffsetId, EgtEP( nMainStripMinOffsetId)) local ptStripMaxEnd = FindIntersectionPoint( nMainStripMaxOffsetId, nEndStripMaxOffsetId, EgtEP( nMainStripMaxOffsetId)) local nEndStripGuideId = EgtLine( nSolidLayerId, ptStripMinEnd, ptStripMaxEnd) EgtExtendCurveStartByLen( nEndStripGuideId, 10) EgtExtendCurveEndByLen( nEndStripGuideId, 10) EgtMove( nEndStripGuideId, Z_AX()) -- estrudo Strip end local b3RefEndProfile = GetProfileLocalBox( nEndProfileId) local nEndStripExtrusionId = EgtSurfTmByExtrusion( nSolidLayerId, nEndStripGuideId, - Z_AX() * ( b3RefEndProfile:getDimY() + 2), WIN_SURF_APPROX) -- intersezione con main EgtSurfTmIntersect( nMainStripExtrusionId, nEndStripExtrusionId) -- cancello curve e superfici di costruzione EgtErase( nSectionId) EgtErase( { nMainStripMinOffsetId, nMainStripMaxOffsetId}) EgtErase( { nStartStripMinOffsetId, nStartStripMaxOffsetId, nStartStripGuideId, nStartStripExtrusionId}) EgtErase( { nEndStripMinOffsetId, nEndStripMaxOffsetId, nEndStripGuideId, nEndStripExtrusionId}) 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], false) local b3FrameProfile = GetProfileLocalBox( nProfileId) local dOffs = b3FrameProfile:getMin():getX() EgtOffsetCurve( nCrv, dOffs) end TrimAndOrientOrderedCurves( vCrvs, false) 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) 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) -- 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, nOutlineLayerId, nGeoLayerId) end 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 elseif nAreaType == WIN_AREATYPES.FILL then -- creo riempimento CreatePartFromOutline( nAreaId, sName) end -- verifico se c'e' uno split da realizzare local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) if nSplitLayerId then 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 local nSplitId = EgtGetFirstInGroup( nSplitLayerId) if nSplitId then -- creo pezzo split local nSplitPartId = CreatePartFromOutline( nAreaId, sName, nSplitId) -- disegno area di selezione per programma local nSelectionLayerId = EgtGroup( nAreaId) EgtSetName( nSelectionLayerId, WIN_SPLITSELECTION) EgtSetStatus( nSelectionLayerId, GDB_ST.OFF) local nSplitPartGeoId = EgtGetFirstNameInGroup( nSplitPartId, WIN_GEO) local nSelectionArea = CreateGeoArea( nSplitPartGeoId, nSelectionLayerId) EgtSetColor( nSelectionArea, 'YELLOW') EgtSetAlpha( nSelectionArea, 10) EgtMove( nSelectionArea, 10 * Z_AX()) end end elseif nAreaType ~= WIN_AREATYPES.FILL then if s_bCalcSolid then --- verifico se area successiva e' un fill local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*') local nChildAreaType = EgtGetInfo( nChildAreaId or GDB_ID.NULL, WIN_AREATYPE, "i") if nChildAreaType == WIN_AREATYPES.FILL then -- se lo e', vuol dire che e' un vetro fisso, quindi calcolo strip dell'outline local nOutlineLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_OUTLINE) local nOutlineId = EgtGetFirstInGroup( nOutlineLayerId) while nOutlineId do CreateStripFromOutline( nAreaId, nOutlineId) nOutlineId = EgtGetNext( nOutlineId) end end end end -- se anta disegno apertura if nAreaType == WIN_AREATYPES.SASH then DrawOpening( nAreaId) 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 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 ptMin = b3Ref:getMin() local ptMax = b3Ref:getMax() -- 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} TrimAndOrientOrderedCurves( vCrvs, false) -- TO DO : controllo lunghezza minima -- local dLenTop = 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 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 UpdateSolidWithDowel( nDowelId, nSolidId, vtDir, dLen, 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) EgtRelocateGlob( 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) TrimAndOrientOrderedCurves( vCrvs, false) -- 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 ---------------------------------------------------------------------------------- ------------------------------ 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) end ---------------------------------------------------------------------------------- ---------------------------------- FERRAMENTA ---------------------------------- ---------------------------------------------------------------------------------- -- funzione che disegna le cerniere local function DrawHinges( 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 la maniglia local function DrawHandle( 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 --------------------------------------------------------------------- -- funzione che disegna la ferramenta local function DrawSashHardware( nAreaId, nRefAreaId, nSolidLayerId) 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, nSolidLayerId) -- 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, nSolidLayerId) -- 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 = 400 local vOptions = EgtGetInfo( nRefAreaId, 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 dHandleH = tonumber( vString[2]) break end end DrawHandle( nOutlineId, sHandleSide, dHandleH, nSolidLayerId, true) -- 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 dati della maniglia local sHandleSide = EgtGetInfo( nRefAreaId, WIN_HDW_HANDLE) local dHandleH = 500 local vOptions = EgtGetInfo( nRefAreaId, 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 dHandleH = tonumber( vString[2]) break end end -- 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), nSolidLayerId) elseif nSashType == WIN_SASHTYPES.NULL then -- è il lato senza maniglia if sHandleSide == 'Sx' then DrawHinges( nLeftId, nSolidLayerId) else DrawHinges( nRightId, nSolidLayerId) end end -- maniglia if nSashType == WIN_SASHTYPES.ACTIVE or nSashType == WIN_SASHTYPES.ACTIVE_IN or nSashType == WIN_SASHTYPES.NULL then if sHandleSide == 'Sx' then DrawHandle( nRightId, sHandleSide, dHandleH, nSolidLayerId) else DrawHandle( nLeftId, sHandleSide, dHandleH, nSolidLayerId) 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 TrimAndOrientOrderedCurves( vOutlineCopy, false) -- 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 aggiunge l'hardware function WinCalculate.AddHardwareForSash( nFrameId, bOnlyRequest) -- 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 bOnlyRequest then nFavourite = WDG.HDWFAVOURITE end if not nFavourite or nFavourite == '000000' then EgtOutLog('Warning! No hardware favourite set!') return end local sHandle = EgtGetInfo( nFrameId, WIN_HDW_HANDLE) if bOnlyRequest then sHandle = WDG.HDWHANDLE end if not sHandle then EgtOutLog('Warning! No hardware handle set!') return end -- creo file di richiesta ferramenta local sNow = os.date( '_%Y_%m_%d_%H_%M_%S', os.time()) local sInputFile = 'a:\\InputBatch\\Input' .. sNow .. '.txt' local sAGBOutputFile = 'C:\\AGB3000NG\\OutputBatch\\Output' .. sNow .. '.txt' local sAGBOutputLavFile = 'C:\\AGB3000NG\\OutputBatch\\OutputLav' .. sNow .. '.txt' local sOutputFile = 'a:\\OutputBatch\\Output' .. sNow .. '.txt' local sOutputLavFile = 'a:\\OutputBatch\\OutputLav' .. sNow .. '.txt' -- Apro file Input in scrittura local fhInput = io.open( sInputFile, 'w') if not fhInput then EgtOutLog( 'Error opening file ' .. sInputFile) return false end local sText = 'OUTPUTKIT=' .. sAGBOutputFile .. '\n' .. '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 sText = sText .. 'CNCOUTPUT=' .. sAGBOutputLavFile .. '\n' .. 'RUN' -- Scrittura nuova linea fhInput:write( sText .. '\n') -- Chiudo file fhInput:close() if bOnlyRequest then return sInputFile end -- attendo scrittura output local nWait = 0 while not EgtExistsFile( sOutputFile) and nWait < 20 do nWait = nWait + 1 EgtPause( 500) end EgtPause( 500) -- Apro file Output in lettura local fhOutput = io.open( sOutputLavFile, 'r') if not fhOutput then EgtOutLog( 'Error opening file ' .. sOutputLavFile) return false end local nFrameAreaId = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*') local nHdwFrameLayerId = EgtGetFirstNameInGroup( nFrameAreaId, WIN_HDW_FRAME) local sOutputLine = fhOutput:lines('l') for sMach in fhOutput:lines('l') do local MachParams = EgtSplitString( sMach, ';') local sPart = MachParams[3] local nSashIndex = tonumber( MachParams[4]) local sSashPart = MachParams[5] local dPosX = tonumber( MachParams[6]) local dPosY = tonumber( MachParams[7]) local dPosZ = tonumber( MachParams[8]) local sMacro = MachParams[9] local sSide = MachParams[21] -- FT1, FT2, FT3, FA1, FA2, FA3 local sOrigin = MachParams[24] -- 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) -- aggiornamento del solido if s_bCalcSolid then -- costruisco asola come volume chiuso per eseguire operazioni booleane con il solido local nOutlineId = EgtCopyGlob( nPocketOutlineId, nSolidLayerId) EgtMove( nOutlineId, Z_AX()) local nSolidId = EgtSurfTmByRegionExtrusion( nProcLayerId, nOutlineId, - ( dHeight + 1) * Z_AX()) EgtTransform( nSolidId, frHdw) EgtSurfTmSubtract( nMainExtrusionId, nSolidId) EgtErase( {nSolidId, nOutlineId}) end -- porto la lavorazione in globale EgtTransform( nPocketOutlineId, frHdw) 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) 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) -- aggiornamento del solido if s_bCalcSolid then local nSolidHoleId = EgtSurfTmByRegionExtrusion( nProcLayerId, nHoleId, - ( dDepth + 1) * Z_AX()) EgtMove( nSolidHoleId, Z_AX()) EgtTransform( nSolidHoleId, frHdw) EgtSurfTmSubtract( nMainExtrusionId, nSolidHoleId) EgtErase( nSolidHoleId) end -- porto la lavorazione in globale EgtTransform( nHoleId, frHdw) end end -- Chiudo file Output in lettura fhOutput:close() -- 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 --------------------------------------------------------------------- -- funzione che aggiunge l'hardware function WinCalculate.AddHardware( nAreaId) -- verifico il tipo local nAreaType = EgtGetInfo( nAreaId, WIN_AREATYPE, 'i') local nSplitLayerId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) local nSplitType = WIN_SPLITTYPES.NULL if nSplitLayerId then nSplitType = EgtGetInfo( nSplitLayerId, WIN_SPLITTYPE, 'i') end if nAreaType == WIN_AREATYPES.SASH or ( nSplitLayerId and nSplitType == WIN_SPLITTYPES.FRENCH) then -- lancio calcolo sash return WinCalculate.AddHardwareForSash( nAreaId) else -- verifico se ci sono sotto-aree local nChildAreaId = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*') while nChildAreaId do -- lancio verifica di quell'area WinCalculate.AddHardware( nChildAreaId) nChildAreaId = EgtGetNextName( nChildAreaId, WIN_AREA .. '*') end end end ---------------------------------------------------------------------------------- ----------------------------------- ACCESSORI ---------------------------------- ---------------------------------------------------------------------------------- -- funzione che indidivua i parametri di trim della curva nCrvId in base al geo delle curve prev e next ( ricavate dalle info di nAuxCrv) local function GetTrimParamsByPrevAndNext( nCrvId, nAuxCrvId, sGeoRef) local nAuxGrp = EgtGetParent( nCrvId) -- recupero curve prev e next di riferimento local nPrevCrv = EgtGetInfo( nAuxCrvId, WIN_PREV_OUTLINES, 'i') local nNextCrv = EgtGetInfo( nAuxCrvId, WIN_NEXT_OUTLINES, 'i') if not nPrevCrv or not nNextCrv then -- gestione speciale per soglia dove prev e next non sono settati local nRefGrp = EgtGetParent( nAuxCrvId) nPrevCrv = EgtGetLastInGroup( nRefGrp) nNextCrv = EgtGetNext( nAuxCrvId) end -- recupero le curve del geo di interesse local nPrevPart = EgtGetInfo( nPrevCrv, WIN_REF_PART, 'i') local nPrevGeo = EgtGetFirstNameInGroup( nPrevPart, WIN_GEO) local nPrevRef = EgtGetFirstNameInGroup( nPrevGeo, sGeoRef) local nPrevCopy = EgtCopyGlob( nPrevRef, nAuxGrp) EgtExtendCurveStartByLen( nPrevCopy, 1000) EgtExtendCurveEndByLen( nPrevCopy, 1000) local nNextPart = EgtGetInfo( nNextCrv, WIN_REF_PART, 'i') local nNextGeo = EgtGetFirstNameInGroup( nNextPart, WIN_GEO) local nNextRef = EgtGetFirstNameInGroup( nNextGeo, sGeoRef) local nNextCopy = EgtCopyGlob( nNextRef, nAuxGrp) EgtExtendCurveStartByLen( nNextCopy, 1000) EgtExtendCurveEndByLen( nNextCopy, 1000) -- recupero punti di intersezione local ptS = EgtIP( nCrvId, nPrevCopy, ORIG()) local dParS = EgtCurveParamAtPoint( nCrvId, ptS) local ptE = EgtIP( nCrvId, nNextCopy, ORIG()) local dParE = EgtCurveParamAtPoint( nCrvId, ptE) EgtErase( { nPrevCopy, nNextCopy}) return dParS, dParE 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) local dParS, dParE = GetTrimParamsByPrevAndNext( nGuideId, nOutlineId, WIN_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 dParS, dParE = GetTrimParamsByPrevAndNext( nGuideId, nOutlineId, WIN_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 local nAreaGrp = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*') EgtSetInfo( nAreaGrp, 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 -- gruppi per i conti local nGrp = EgtGroup( nPartId) -- recupero parametri di intersezione con i pezzi vicini local dParPrev, dParNext = GetTrimParamsByPrevAndNext( nOutlineId, nOutlineId, WIN_IN) local vParams = { dParPrev, dParNext} -- verifico se outline va spezzato ulteriormente a causa di montanti 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.FRAME or nAreaType == WIN_AREATYPES.SPLIT then local nSplitId = EgtGetFirstNameInGroup( vStack[i], WIN_SPLIT) if nSplitId then local nSplitType = EgtGetInfo( nSplitId, WIN_SPLITTYPE, 'i') if nSplitType ~= WIN_SPLITTYPES.FRENCH then -- recupero il pezzo associato allo split local nSplitOutline = EgtGetFirstInGroup( nSplitId) local nSplitPart = EgtGetInfo( nSplitOutline, WIN_REF_PART, 'i') -- recupero le intersezioni con la curva di outline local nSplitGeo = EgtGetFirstNameInGroup( nSplitPart, WIN_GEO) local nCrv1 = EgtGetFirstNameInGroup( nSplitGeo, WIN_IN) local nCopy1 = EgtCopyGlob( nCrv1, nGrp) EgtExtendCurveStartByLen( nCopy1, 200) EgtExtendCurveEndByLen( nCopy1, 200) local nCrv2 = EgtGetFirstNameInGroup( nSplitGeo, WIN_OUT) local nCopy2 = EgtCopyGlob( nCrv2, nGrp) EgtExtendCurveStartByLen( nCopy2, 200) EgtExtendCurveEndByLen( nCopy2, 200) local pt1 = EgtIP( nOutlineId, nCopy1, ORIG()) local pt2 = EgtIP( nOutlineId, nCopy2, ORIG()) if pt1 and pt2 then -- salvo i parametri di intersezione local dPar1 = EgtCurveParamAtPoint( nOutlineId, pt1, 100 * GEO.EPS_SMALL) local dPar2 = EgtCurveParamAtPoint( nOutlineId, pt2, 100 * GEO.EPS_SMALL) table.insert( vParams, dPar1) table.insert( vParams, dPar2) end -- salvo le sue sottoaree per analizzarle local vChildren = EgtGetNameInGroup( vStack[i], WIN_AREA .. '*') or {} vStack = EgtJoinTables( vStack, vChildren) end end end i = i + 1 end end -- riordino i parametri ( non dovrebbero mai capitare parametri coincidenti) table.sort( vParams) -- recupero il gruppo per il disegno dei solidi local nSolidLayId if bDraw and s_bCalcSolid then nSolidLayId = GetAuxLayer() end local dLenTot = 0 for i = 1, #vParams, 2 do -- creo la guida di estrusione per il gocciolatoio local nGuideId = EgtCopyGlob( nOutlineId, nGrp) -- trim della curva EgtTrimCurveStartEndAtParam( nGuideId, vParams[i], vParams[i+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 end -- salvo la lunghezza del gocciolatoio local nAreaGrp = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*') EgtSetInfo( nAreaGrp, WIN_WATERDRIP_LEN, dLenTot) EgtErase( nGrp) 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 TrimAndOrientOrderedCurves( vCrvs, true) -- aggiorno lunghezza for i = 1, #vCrvs do if tParts[i].sGasket then -- devo ignorare le curve di trim dLenTot = dLenTot + EgtCurveLength( vCrvs[i]) end end -- disegno if bDraw and s_bCalcSolid then -- recupero il gruppo per il disegno dei solidi local nSolidLayerId = GetAuxLayer() for i = 1, #vCrvs do if tParts[i].sGasket then -- estrusione principale della giunzione local nGasketStm = CreateProfileSurf( vOutlines[i], tParts[i].nProfileId, tParts[i].sGasket, 100, nSolidLayerId) EgtSetColor( nGasketStm, Color3d( 128, 128, 128)) EgtSetName( nGasketStm, sGasket) -- trim start local nPrev = EgtIf( i == 1, #vCrvs, i - 1) local nGuideId if not tParts[nPrev].sGasket then -- se precedente è curva di trim la uso direttamente nGuideId = EgtCopyGlob( vCrvs[nPrev], nSolidLayerId) EgtInvertCurve( nGuideId) else -- taglio lungo la bisettrice local vtDir = 0.5 * ( EgtSV( vCrvs[i]) - EgtEV( vCrvs[nPrev])) if vtDir:isSmall() then vtDir = EgtSV( vCrvs[i]) vtDir:rotate( Z_AX(), 90) end nGuideId = EgtLinePVL( nSolidLayerId, EgtSP( vCrvs[i]), vtDir, 200) EgtExtendCurveStartByLen( nGuideId, 100) end local nTrimStart = EgtSurfTmByExtrusion( nSolidLayerId, nGuideId, - 200 * Z_AX()) EgtSurfTmIntersect( nGasketStm, nTrimStart) EgtErase( { nGuideId, nTrimStart}) -- trim end local nNext = EgtIf( i == #vCrvs, 1, i + 1) if not tParts[nNext].sGasket then nGuideId = EgtCopyGlob( vCrvs[nNext], nSolidLayerId) else local vtDir = 0.5 * ( EgtSV( vCrvs[nNext]) - EgtEV( vCrvs[i])) if vtDir:isSmall() then vtDir = EgtSV( vCrvs[nNext]) vtDir:rotate( Z_AX(), 90) end nGuideId = EgtLinePVL( nSolidLayerId, EgtEP( vCrvs[i]), vtDir, 200) EgtExtendCurveStartByLen( nGuideId, 100) end local nTrimEnd = EgtSurfTmByExtrusion( nSolidLayerId, nGuideId, - 200 * Z_AX()) EgtInvertSurf( nTrimEnd) EgtSurfTmIntersect( nGasketStm, nTrimEnd) EgtErase( { nGuideId, nTrimEnd}) end end end end end -- aggiorno valore lunghezza local nAreaGrp = EgtGetFirstNameInGroup( GDB_ID.ROOT, WIN_AREA .. '*') local dLenOld = EgtGetInfo( nAreaGrp, WIN_GASKET_LEN, 'd') or 0 EgtSetInfo( nAreaGrp, WIN_GASKET_LEN, dLenOld + 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 gocciolatioio 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 un french split o se definisce direttamente anta local nSplitId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) or GDB_ID.NULL local nSplitType = EgtGetInfo( nSplitId, WIN_SPLITTYPE, 'i') if nSplitId == GDB_ID.NULL or nSplitType == WIN_SPLITTYPES.FRENCH then CalcGaskets( nAreaId, bDraw) end -- TODO guarnizioni per gocciolatoio elseif nAreaType == WIN_AREATYPES.SASH then -- guarnizioni anta CalcGaskets( nAreaId, bDraw) elseif nAreaType == WIN_AREATYPES.SPLIT then -- guarnizioni se è french split che non deriva da un french split local nSplitId = EgtGetFirstNameInGroup( nAreaId, WIN_SPLIT) local nSplitType = EgtGetInfo( nSplitId, WIN_SPLITTYPE, 'i') if nSplitType == WIN_SPLITTYPES.FRENCH then local nParentArea = EgtGetParent( nAreaId) local nParentSplit = EgtGetFirstNameInGroup( nParentArea, WIN_SPLIT) or GDB_ID.NULL local nSplitType = EgtGetInfo( nParentSplit, WIN_SPLITTYPE, 'i') if nSplitType ~= WIN_SPLITTYPES.FRENCH then CalcGaskets( nAreaId, bDraw) end end elseif nAreaType == WIN_AREATYPES.NULL then -- guarnizioni se non deriva da french split e ha come sottoarea un'anta local nParentArea = EgtGetParent( nAreaId) local nParentSplit = EgtGetFirstNameInGroup( nParentArea, WIN_SPLIT) or GDB_ID.NULL local nSplitType = EgtGetInfo( nParentSplit, WIN_SPLITTYPE, 'i') if nSplitType == WIN_SPLITTYPES.MULLION then local nChildArea = EgtGetFirstNameInGroup( nAreaId, WIN_AREA .. '*') or GDB_ID.NULL local nChildType = EgtGetInfo( nChildArea, WIN_AREATYPE, 'i') if nChildType == WIN_AREATYPES.SASH then CalcGaskets( nAreaId, bDraw) end 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 --------------------------------------------------------------------- return WinCalculate