Forum Sketchup Artlantis Archicad
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
Annonces
Bonjour Invité Bienvenue sur le forum biblio3d - le forum a été créé le Sam 19 Jan 2008 - 14:26- Nous avons enregistrés 14855 topics pour un total de : 176114 posts - le record de membres connectés simultanément :853
vidéo sur youtube
Ton bloc notes
Derniers sujets
» [ SKETCHUP généralité ] Problème d'ouverture de SO
par lionel Claude Aujourd'hui à 13:47

» [ SKETCHUP plugins ] une barre d’outils perso
par bianhai Aujourd'hui à 13:12

» [ ARCHICAD-BIM CLOUD/TEAMWORK ] BimOBject.Com
par odrik Aujourd'hui à 9:56

» [ ARCHICAD-OBJETS GDL ] Boîte à eau
par Jean-Marc Aujourd'hui à 7:57

» [ SKETCHUP composants dynamiques ] Grue parametrique
par davidheritier Hier à 11:28

» [ INTELLIGENCE ARTIFICIELLE ] Nvidia Project Digits: Un Supercalculateur d'Intelligence Artificielle sur Votre Bureau
par tenrev Mar 14 Jan 2025 - 23:13

» [ SKETCHUP composants dynamiques ] petite piqure de rappel - cours de 6h30 sur les composants dynamiques
par tenrev Mar 14 Jan 2025 - 9:47

» [ INTELLIGENCE ARTIFICIELLE ] Heygen IA et de nouvelles fonctionnalités
par tenrev Lun 13 Jan 2025 - 16:21

» [ AUTRES LOGICIELS ] Sites utile concernant Revit, AutoCad, sketchup
par tenrev Mer 8 Jan 2025 - 16:32

» [ SKETCHUP plugins ] SJ SectionBox
par furax49 Mar 7 Jan 2025 - 15:29

» [ INTELLIGENCE ARTIFICIELLE ] j'ai généré une appli no code avec Bolt et Chatgpt
par tenrev Mar 7 Jan 2025 - 14:06

» [ INTELLIGENCE ARTIFICIELLE ] un tout petit peu de sketchup et beaucoup d'IA
par tenrev Lun 6 Jan 2025 - 17:15

» [ SKETCHUP généralité ] Comment éviter l'overlapping des géométries des composants en miroir ?
par simjoubert Dim 5 Jan 2025 - 13:43

» [ SKETCHUP généralité ]
par tenrev Sam 4 Jan 2025 - 15:52

» [ SKETCHUP plugins ] Moulures cadres
par Lionscov Lun 16 Déc 2024 - 23:28

» [ PHOTOSHOP ] tuto (encore)
par tenrev Ven 13 Déc 2024 - 9:37

» [ SKETCHUP généralité ] 3D Basecamp 2024 Keynote Highlights
par tenrev Jeu 28 Nov 2024 - 21:54

» [ TWINMOTION ] sortie de twinmotion 2025 review
par tenrev Jeu 28 Nov 2024 - 21:50

» [ SKETCHUP tutos ] Vasque Cannelée et Évasée sur les côtés
par jerryvento Jeu 28 Nov 2024 - 15:42

» [ SKETCHUP généralité ] Tête de pilastre
par jerryvento Jeu 28 Nov 2024 - 15:31

» [résolu] [ ARCHICAD ] Paramétrage des coupes sur Archicad
par Patrick Superpat Jeu 28 Nov 2024 - 11:25

» [ SKETCHUP généralité ] probleme insertion image
par gthib09 Jeu 28 Nov 2024 - 11:04

» [ AUTRES LOGICIELS ] Appli générée par l'IA
par tenrev Mer 27 Nov 2024 - 15:05

» [ TWINMOTION ] Unreal Engine déménage sur Fab - Assets de Megascan
par JDD Lun 25 Nov 2024 - 15:55

» [ SKETCHUP plugins ] Les bon plans Black Friday 2024
par tenrev Lun 25 Nov 2024 - 12:41

» [ CHALLENGE 2024 ] résultats du challenge
par Allansens Ven 22 Nov 2024 - 8:42

» [ FORUM ] astuce pour insérer facilement un tableau sur le forum
par tenrev Mer 20 Nov 2024 - 9:12

» [ SKETCHUP généralité ] Orienter 1 Face, 1 Profil Normal (Perpendiculaire) à 1 Arête, 1 Trajectoire
par jerryvento Lun 18 Nov 2024 - 14:47

» [ SKETCHUP généralité ] Modéliser facilement 1 spirale en moins de 40 secondes
par jerryvento Lun 18 Nov 2024 - 14:47

» [ SKETCHUP généralité ] Modélise 1 Forme Hélicoïdale, en forme de spirale : main courante, rampe d'accès voitures...
par jerryvento Lun 18 Nov 2024 - 14:46

» [ SKETCHUP tutos ] Orienter 1 Face, 1 Profil Normal (Perpendiculaire) à 1 Arête, 1 Trajectoire
par jerryvento Lun 18 Nov 2024 - 14:45

» [ SKETCHUP tutos ] Modéliser facilement 1 spirale en moins de 40 secondes
par jerryvento Lun 18 Nov 2024 - 14:44

» [ SKETCHUP tutos ] Modélise 1 Forme Hélicoïdale, en forme de spirale : main courante, rampe d'accès voitures...
par jerryvento Lun 18 Nov 2024 - 14:43

» ColorMaker par Didier Bur[ SKETCHUP plugins ]
par JDD Dim 17 Nov 2024 - 20:56

» [ ARCHICAD ] Plus de format *atl dans Archicad
par Coulou Jeu 14 Nov 2024 - 8:26

Sondage

êtes vous intéressé et prêt à participer à un challenge ?

 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c1015% [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c10 15% [ 2 ]
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c1031% [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c10 31% [ 4 ]
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c1046% [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c10 46% [ 6 ]
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c108% [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c10 8% [ 1 ]
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c100% [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c10 0% [ 0 ]
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c100% [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Poll_c10 0% [ 0 ]

Total des votes : 13

chaine sketchup.tv
Serveur Discord
Galerie


 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Empty
Le Deal du moment : -15%
Champagne Canard-Duchêne Brut – 75 cl
Voir le deal
22.01 €

[ SKETCHUP généralité ] Comment éviter l'overlapping des géométries des composants en miroir ?

Voir le sujet précédent Voir le sujet suivant Aller en bas

JDD
JDD
V.I.P.
V.I.P.
Masculin Humeur : Cool, œil de lynx à pattes de velours
Date d'inscription : 21/05/2021
Nombre de messages : 1165
Points : 2542
Age : 76
Localisation : Nord (59)
Emploi : Director of Myself

MessageJDD Ven 3 Jan 2025 - 17:18

Bonjour,

Je recherche un moyen , plugin, code ou autres permettant de gérer l'overlapping (chevauchement) des géométries modifiées sur des composants en miroir.

Cette disposition existe dans d'autres logiciels de modélisation 3D ( Blender par exemple) . Elle permet d'éviter l'overlapping des géométries en miroir lors de modifications.

Certain logiciel permette en plus de fusionner automatiquement les géométries exactement à la jonction du plan de symétrie ( ou même à partir d'une certaine distance d'approche de ce plan de symétrie).

Pour clarifier ma demande, un exemple simple ci-après comprenant deux composants, le second ayant été créé à partir d'une copie miroir du premier.

Si on modifie le composant 1, le composant 2 subit la même modification mais en miroir.

Comment empêcher l'overlapping dans l'exemple et le bloquer juste au plan de symétrie ?

L'exemple est donné unique pour clarifier l'overlapping.

 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Mirroi13
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Mirroi12
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Mirroi14
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Mirroi15

Et éviter ceci :

 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? Mirroi16

JDD


Dernière édition par JDD le Sam 4 Jan 2025 - 16:36, édité 1 fois
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Ven 3 Jan 2025 - 17:45

Hello JDD
Tu peux utiliser simplement un plan de section intégré à ton composant à l'endroit du plan de symétrie ou englober comme dans cet exemple ton composant et un plan de section dans un composant et en faire la symétrie
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? VslZDuaxVG
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? IPB_917
JDD
JDD
V.I.P.
V.I.P.
Masculin Humeur : Cool, œil de lynx à pattes de velours
Date d'inscription : 21/05/2021
Nombre de messages : 1165
Points : 2542
Age : 76
Localisation : Nord (59)
Emploi : Director of Myself

MessageJDD Ven 3 Jan 2025 - 17:51

Hello  @simjoubert

Je n'arrive pas à visionner ton gif animé.

Si je clique sur l'image elle apparait bien en grand mais elle est tronquée dans le coin bas droit de l'écran ??

Impossible de la visionner au centre de l'écran ? Une explication ?

JDD
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Ven 3 Jan 2025 - 17:53

tu es sur ton téléphone ou le pc chez moi elle est bien visible ! :colère:
JDD
JDD
V.I.P.
V.I.P.
Masculin Humeur : Cool, œil de lynx à pattes de velours
Date d'inscription : 21/05/2021
Nombre de messages : 1165
Points : 2542
Age : 76
Localisation : Nord (59)
Emploi : Director of Myself

MessageJDD Ven 3 Jan 2025 - 17:53

Sur mon PC.

J'ai testé un autre de tes gifs publiés dans un autre sujet, RAS, tout est correct sur ces derniers.

JDD

simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Ven 3 Jan 2025 - 17:59

Bon ma proposition est simple
Tu places un plan de section sur le futur plan de symétrie le plan peux être dans le composant ou à extérieur du composant. Si tu choisi à extérieur tu englobe ton plan de section et le composant dans un nouveau composant. Et tu fais le symétrique.
Les plans de section s'opposent et masque ce que tu nommes l'overlapping.
Avec le plan de section à extérieur cela te permet de modifier le composant via une 3eme copie sans plan de section.
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Ven 3 Jan 2025 - 18:00

je t'en refait un, un peu plus zoomé
JDD
JDD
V.I.P.
V.I.P.
Masculin Humeur : Cool, œil de lynx à pattes de velours
Date d'inscription : 21/05/2021
Nombre de messages : 1165
Points : 2542
Age : 76
Localisation : Nord (59)
Emploi : Director of Myself

MessageJDD Ven 3 Jan 2025 - 18:01

Ton gif fonctionne maintenant
Je vais l'analyser
Merci
JDD

simjoubert aime ce message

JDD
JDD
V.I.P.
V.I.P.
Masculin Humeur : Cool, œil de lynx à pattes de velours
Date d'inscription : 21/05/2021
Nombre de messages : 1165
Points : 2542
Age : 76
Localisation : Nord (59)
Emploi : Director of Myself

MessageJDD Ven 3 Jan 2025 - 18:54

OK pour cette façon de procéder  @simjoubert .

Mais je ne souhaite pas particulièrement créer et avoir ces géométries masquées. Surtout sur un modèle complexe comportant de très nombreux éléments disposés symétriquement à un plan donné et surtout dans ce cas la gestion des plans de sections va devenir un calvaire.
Pas certain que cela ne pose pas de problèmes pour les rendus .

J'aimerais par exemple que lorsque l'on extrude une face jusqu'au plan de symétrie il ne soit plus possible de l'extruder au delà, même si l'extrusion , n'est pas perpendiculaire au plan de symétrie, le plan de symétrie jouant alors comme une sorte de plan de coupe de la géométrie en cours d'extrusion.
JDD
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Ven 3 Jan 2025 - 21:53

Le tout doit être dynamique ou le composant ne subit plus de transformation?
JDD
JDD
V.I.P.
V.I.P.
Masculin Humeur : Cool, œil de lynx à pattes de velours
Date d'inscription : 21/05/2021
Nombre de messages : 1165
Points : 2542
Age : 76
Localisation : Nord (59)
Emploi : Director of Myself

MessageJDD Ven 3 Jan 2025 - 21:57

Il doit pouvoir rester modifiable.
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Ven 3 Jan 2025 - 22:34

je peux te proposer de reutiliser une partie de mon script que j'utilise dans mon plugin Sj FrameBuilder

le concept :
  • on fixe que le point de symétrie est sur le plan YZ passant par l'origine du composant !
  • on créer un observateur attaché au composant. A chaque modification du composant il execute la commande suivante :


    • On place une face sur le plan YZ passant par l'origine du composant, cette facce fera le double de la hauteur et de la profondeur de ton composant  pour etre sure qu'elle rentrera bien en intersection avec des éléments "Sortants".
    • On réalise l'intersection de la face avec les entités du composant
    • On liste toutes les vertices du composant et on filtre ceux qui sont à l'extérieur de la zone autorisée, puis on supprime toutes les arrêtes qui partent de ces vertices.



Le principe t'ira ?
Cela reste dynamique mais tu perds ce qui dépasse !
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Sam 4 Jan 2025 - 11:46

Hello JDD
Je n'ai pas attendu ta réponse et voici une proposition de code
Code à ne lire qu'une seule fois par session SketchUp pour éviter la duplication des menus



Code:
# TRUNCAT V1.0 2025/01/04
# Author Simon Joubert

# Ce script permet de tronquer tout les élements d'un composant qui sont placés à une position x négative par rapport à son origine.

# Ce script ajoute dans le menu dessiner un sous menu Truncat avec 2 commandes:
##Ajouter un observateur sur chaque instance du composant et sur ses futures nouvelles instance
##Supprimer les observateurs sur chaque instances du composant

#Fonctionnement :
# selectionner un composant
# Attacher lui un Truncat observer depuis la commande Menu > Dessiner > Truncat > Add Observer

# Lors du déclenchement de la commande Add Observer un attribut truncat de valeur 1 est ajouté à la définition et au instance du composant sélectionné.
# cet attribut sert d'intérupteur 1 => truncat activé, aute valeur => inactivé

# L'observateur se déclenche à la fermeture du composant quand vous avez modifié son contenu.
# Il réalise 2 tests :
## la définition possède un attribut truncat de valeur 1 (1 => Truncat activé , Sinon inactivé)
## si Truncat activé il test si des arrêtes ont un début ou une fin avec des coordonées x <0
# Si les 2 conditions sont vraie l'opération de truncat commenvce (opération annulable)
#Une face est ajoutée au entités du comosant sur le plan YZ placé à l'origine. l'intersection de la face avec le reste des éléments est réalisée. Puis suppression des éléments "a l'exterieur".

#Executer ce script une fois par session Sketchup pour eviter la duplication des menu

#On défini la variable globale qui contiendra tout les observateurs
 TRUNCAT_SPYS ||= {}

# Observateur d'instance
class TruncatInstanceObserver < Sketchup::InstanceObserver  
  def onClose(instance)
    truncat_atrribute = instance.definition.get_attribute("dynamic_attributes","truncat", 0).to_i
    truncat(instance) if truncat_atrribute == 1
  end  
end #Fin class

# Observateur de déinition
class TruncatDefinitionObserver < Sketchup::DefinitionObserver
  def onComponentInstanceAdded(definition, instance)
    pid = instance.persistent_id
    TRUNCAT_SPYS[pid.to_s] = TruncatInstanceObserver.new
    instance.add_observer(TRUNCAT_SPYS[pid.to_s])
  end
  
  def onComponentInstanceRemoved(definition, instance)
    pid = instance.persistent_id    
    instance.remove_observer(TRUNCAT_SPYS[pid.to_s]) if instance.valid?
    TRUNCAT_SPYS.delete(pid.to_s)
  end
end


#Pour ajouter un un Truncat observer sur toutes les instances soeur de l'instance sélectionnée
def addTruncatObserver()
  model = Sketchup.active_model # Open model
  model.start_operation("Add Truncat Observer",true,false,false)
  ents = model.entities # All entities in model
  sel = model.selection # Current selection
 
  inst = sel.grep(Sketchup::ComponentInstance).first
  inst_def = inst.definition
  
  #On Verifie l'existance de l'attribut truncat on l'ajoute s'il n'éxiste pas
  dcdict = "dynamic_attributes"
  unless inst.get_attribute(dcdict, "truncat", false)
    inst_def.set_attribute(dcdict, "truncat", 1)
    inst_def.set_attribute(dcdict, "_truncat_label", "truncat")
    inst_def.set_attribute(dcdict, "_truncat_formulaunits", "STRING")
    inst.set_attribute(dcdict, "truncat", 1)
  end
  
  # on ajoute un TruncatDefinitionObserver sur la définition
  ## pour attacher un TruncatInstanceObserver sur les nouvelles instance
  ## et le supprimer lorsque l'instance est effacée  
  inst_def_pid = inst_def.persistent_id
  TRUNCAT_SPYS[inst_def_pid.to_s] = TruncatDefinitionObserver.new
  inst_def.add_observer(TRUNCAT_SPYS[inst_def_pid.to_s])
  
  # On ajoute un TruncatInstanceObserver sur chaque instance de la définition
  insts = inst_def.instances
  insts.each do |instance|
    pid = instance.persistent_id
    if TRUNCAT_SPYS[pid.to_s] == nil
      TRUNCAT_SPYS[pid.to_s] = TruncatInstanceObserver.new
      instance.add_observer(TRUNCAT_SPYS[pid.to_s])
    end
  end
  model.commit_operation
end

#Pour retirer les observateur de toutes les instances soeurs de l'instance sélectionnée
def removeTruncatObserver()
  model = Sketchup.active_model # Open model
  model.start_operation("Remove Truncat Observer",true,false,true)
  ents = model.entities # All entities in model
  sel = model.selection # Current selection
  inst = sel.grep(Sketchup::ComponentInstance).first
  inst_def = inst.definition
  #On supprime l'observer sur la definition
  inst_def_pid = inst_def.persistent_id
  inst_def.remove_observer(TRUNCAT_SPYS[inst_def_pid.to_s]) if TRUNCAT_SPYS[inst_def_pid.to_s]
  TRUNCAT_SPYS.delete(inst_def_pid.to_s)
  
  insts = inst_def.instances
  insts.each do |instance|
    pid = instance.persistent_id    
    instance.remove_observer(TRUNCAT_SPYS[pid.to_s])
    TRUNCAT_SPYS.delete(pid.to_s)
  end
  model.commit_operation
end #Fin removeTruncatObserver()

# Méthode appelé par l'observateur d'instance lorsque l'on sort du composant
# Tronque les entités du composant pour ne conservér que la partie avec un x >= 0
def truncat(inst)  
  model = Sketchup.active_model # Open model
  
  inst_def = inst.definition
  inst_ents = inst_def.entities
  
  # On test s'il y a des éléments avec un x < 0
  inst_edges = inst_ents.grep(Sketchup::Edge)
  inst_edges_out = inst_edges.filter { |e| e.start.position.x < 0 || e.end.position.x < 0 }
  
  #On annule s'il n'y aaucune edge qui dépasse avec une coordonnée x <0
  raise "Aucun element n'a de coordonées x <0 " if inst_edges_out.length == 0
  
  #Sinon début de la pile d'annulation
  model.start_operation("Truncat instance",true,false,false)
  
  #Agrandissement x100
  p0 = Geom::Point3d.new(0,0,0)
  tr_scale = Geom::Transformation.scaling(p0, 100, 100, 100)
  tr_rescale = Geom::Transformation.scaling(p0, 0.01, 0.01 ,0.01)  
  inst_ents.transform_entities(tr_scale, inst_ents.to_a)
  
  #On filtre les faces et les arrêtes
  inst_collection = inst_ents.grep(Sketchup::Edge) + inst_ents.grep(Sketchup::Face)
  
  #On récupère la BoundingBox
  bb_ents = inst_collection.map { |e| e.bounds }
  bb = Geom::BoundingBox.new
  bb.add(bb_ents)
  
  #On récupère les dimensions de la boundingBox
  bb_d = bb.depth #longueur axe Z
  bb_h = bb.height #longueur Axe Y
  bb_min = bb.min #point avec le x, y et z le plus petit petit
  bb_max = bb.max  #point avec le x, y et z le plus petit grand

  # calcule des points de la face  
  bb_min_y = bb.min.y - (bb_h / 2)
  bb_min_z = bb_min.z - (bb_d / 2)  
  bb_max_y = bb_max.y + (bb_h / 2)
  bb_max_z = bb_max.z + (bb_d / 2)

  pts_face = [
  Geom::Point3d.new(0, bb_min_y, bb_min_z),
  Geom::Point3d.new(0, bb_min_y, bb_max_z),
  Geom::Point3d.new(0, bb_max_y, bb_max_z),
  Geom::Point3d.new(0, bb_max_y, bb_min_z)
  ]
  #Creation de la face d'intersection
  face = inst_ents.add_face(pts_face)
  #On sauvgarde les vertices de la face
  vertices_face = face.vertices

  #Intersection de la face avec les autres entités de la définition du composant
  recursion = true
  tr0 = Geom::Transformation.new(p0)
  inst_ents.intersect_with(recursion, tr0, inst_ents, tr0, true,[face])

  #Effacement des arrêtes indésirables
  #On récupère les arrêtes
  edges = inst_ents.grep(Sketchup::Edge)
  #On récupère un array  mis à plat de tout les vertices des arrêtes
  vertices  = edges.map { |e| e.vertices }.flatten
  #On filtre les vertices qui ont  une position x < 0
  vertices_out = vertices.filter { |v| v.position.x < 0 } + vertices_face
  
  #Boucle sur chaque vertices filtrés
  vertices_out.each do |v|
    next if !v.valid? # On passe au suivant si le vertice n'existe plus
    #On récupère les arrêtes qui utilise ce vertice
    edges_out = v.edges
    #On efface les arrêtes trouvées
    edges_out.each { |e| e.erase! if e.valid? }      
  end
  
  # On rescale les entités
  inst_ents.transform_entities(tr_rescale, inst_ents.to_a)
  
  model.commit_operation

end #Fin truncat

def menu_Truncat()
  add_separator_to_menu("Draw")
  truncat_menu = UI.menu("Draw").add_submenu("Truncat")

  cmd_add_observer = UI::Command.new("Add Truncat Observer") {  addTruncatObserver() }
  cmd_add_observer.menu_text = "Add Truncat Observer to all instances of the definition of the select instance"
  truncat_menu.add_item cmd_add_observer

  cmd_remove_observer = UI::Command.new("Remove Truncat Observer") {  removeTruncatObserver() }
  cmd_remove_observer.menu_text = "Remove Truncat Observer to all instances of the definition of the select instance"
  truncat_menu.add_item cmd_remove_observer
end

menu_Truncat()



J'attends ton retour
 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? IPB_917
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Sam 4 Jan 2025 - 20:16

Nouvelle version V1.2.0
Possibilité de choisir le plan de truncat "XZ", "YZ", ou "XY"

Pour l'installer redémarrer une nouvelle session de SU
puis copier le code dans la console

Code:
# TRUNCAT V1.2 2025/01/04
# Author Simon Joubert

# Ce script permet de tronquer tout les élements d'un composant qui sont placés à une position x négative par rapport à son origine.

# Ce script ajoute dans le menu dessiner un sous menu Truncat avec 2 commandes:
##Ajouter un observateur sur chaque instance du composant et sur ses futures nouvelles instances
##Supprimer les observateurs sur chaque instances du composant

#Fonctionnement :
# selectionner un composant
# Attacher lui un Truncat observer depuis la commande Menu > Dessiner > Truncat > Add Observer

# Lors du déclenchement de la commande Add Observer un attribut truncat de valeur 1 est ajouté à la définition et aux instances du composant sélectionné.
# cet attribut sert d'intérupteur 1 => truncat activé, aute valeur => inactivé
#Attribut Truncat_plane permet de choisir le plan selon lequel tronquer

# L'observateur se déclenche à la fermeture du composant quand vous avez modifié son contenu.
# Il réalise 2 tests :
## la définition possède un attribut truncat de valeur 1 (1 => Truncat activé , Sinon inactivé)
## si Truncat activé il test si des arrêtes ont un début ou une fin avec des coordonées négatives selon le plan choisi.
# Si les 2 conditions sont vraies, l'opération de truncat commence (opération annulable)
#Une face est ajoutée aux entités du composant sur le plan choisi placé à l'origine. l'intersection de la face avec le reste des éléments est réalisée. Puis suppression des éléments "a l'exterieur".

#Executer ce script une fois par session Sketchup pour eviter la duplication des menu

# Note de version:
# V1.2.0
# Ajout d'un attribut pour choisir le plan selon lequel tronquer les éléments de coordonnées négatives

#########################################################################################################

#On défini la variable globale qui contiendra tout les observateurs
 TRUNCAT_SPYS ||= {}

# Observateur d'instance
class TruncatInstanceObserver < Sketchup::InstanceObserver  
  def onClose(instance)
    truncat_atrribute = instance.definition.get_attribute("dynamic_attributes","truncat", 0).to_i
    truncat(instance) if truncat_atrribute == 1
  end  
end #Fin class

# Observateur de déinition
class TruncatDefinitionObserver < Sketchup::DefinitionObserver
  def onComponentInstanceAdded(definition, instance)
    pid = instance.persistent_id
    TRUNCAT_SPYS[pid.to_s] = TruncatInstanceObserver.new
    instance.add_observer(TRUNCAT_SPYS[pid.to_s])
  end
  
  def onComponentInstanceRemoved(definition, instance)
    pid = instance.persistent_id    
    instance.remove_observer(TRUNCAT_SPYS[pid.to_s]) if instance.valid?
    TRUNCAT_SPYS.delete(pid.to_s)
  end
end


#Pour ajouter un un Truncat observer sur toutes les instances soeurs de l'instance sélectionnée
def addTruncatObserver()
  model = Sketchup.active_model # Open model
  model.start_operation("Add Truncat Observer",true,false,false)
  ents = model.entities # All entities in model
  sel = model.selection # Current selection
 
  inst = sel.grep(Sketchup::ComponentInstance).first
  inst_def = inst.definition
  
  #On Verifie l'existance de l'attribut truncat on l'ajoute s'il n'éxiste pas
  dcdict = "dynamic_attributes"
  unless inst.get_attribute(dcdict, "truncat", false)
    inst_def.set_attribute(dcdict, "truncat", 1)
    inst_def.set_attribute(dcdict, "_truncat_label", "truncat")
    inst_def.set_attribute(dcdict, "_truncat_formulaunits", "STRING")
    inst_def.set_attribute(dcdict, "_truncat_units", "STRING")
    inst_def.set_attribute(dcdict, "_truncat_access", "LIST")
    inst_def.set_attribute(dcdict, "_truncat_formlabel", "Truncat status")
    inst_def.set_attribute(dcdict, "_truncat_options", "&ON=1&OFF=0&")
    inst.set_attribute(dcdict, "truncat", 1)

    inst_def.set_attribute(dcdict, "truncat_plane", "YZ")
    inst_def.set_attribute(dcdict, "_truncat_plane_label", "truncat_plane")
    inst_def.set_attribute(dcdict, "_truncat_plane_formulaunits", "STRING")
    inst_def.set_attribute(dcdict, "_truncat_plane_units", "STRING")
    inst_def.set_attribute(dcdict, "_truncat_plane_access", "LIST")
    inst_def.set_attribute(dcdict, "_truncat_plane_formlabel", "Truncat plane")
    inst_def.set_attribute(dcdict, "_truncat_plane_options", "&XZ=XZ&YZ=YZ&XY=XY&")
    inst.set_attribute(dcdict, "truncat_plane", "YZ")
    
  end
  
  # on ajoute un TruncatDefinitionObserver sur la définition
  ## pour attacher un TruncatInstanceObserver sur les nouvelles instance
  ## et le supprimer lorsque l'instance est effacée  
  inst_def_pid = inst_def.persistent_id
  TRUNCAT_SPYS[inst_def_pid.to_s] = TruncatDefinitionObserver.new
  inst_def.add_observer(TRUNCAT_SPYS[inst_def_pid.to_s])
  
  # On ajoute un TruncatInstanceObserver sur chaque instance de la définition
  insts = inst_def.instances
  insts.each do |instance|
    pid = instance.persistent_id
    if TRUNCAT_SPYS[pid.to_s] == nil
      TRUNCAT_SPYS[pid.to_s] = TruncatInstanceObserver.new
      instance.add_observer(TRUNCAT_SPYS[pid.to_s])
    end
  end
  model.commit_operation
end

#Pour retirer les observateur de toutes les instances soeurs de l'instance sélectionnée
def removeTruncatObserver()
  model = Sketchup.active_model # Open model
  model.start_operation("Remove Truncat Observer",true,false,true)
  ents = model.entities # All entities in model
  sel = model.selection # Current selection
  inst = sel.grep(Sketchup::ComponentInstance).first
  inst_def = inst.definition
  #On supprime l'observer sur la definition
  inst_def_pid = inst_def.persistent_id
  inst_def.remove_observer(TRUNCAT_SPYS[inst_def_pid.to_s]) if TRUNCAT_SPYS[inst_def_pid.to_s]
  TRUNCAT_SPYS.delete(inst_def_pid.to_s)
  
  insts = inst_def.instances
  insts.each do |instance|
    pid = instance.persistent_id    
    instance.remove_observer(TRUNCAT_SPYS[pid.to_s])
    TRUNCAT_SPYS.delete(pid.to_s)
  end
  model.commit_operation
end #Fin removeTruncatObserver()

# Méthode appelé par l'observateur d'instance lorsque l'on sort du composant
# Tronque les entités du composant pour ne conservér que la partie avec un x >= 0
def truncat(inst)  
  model = Sketchup.active_model # Open model
  rp = 4 #round_precision
  
  inst_def = inst.definition
  inst_ents = inst_def.entities

  #On récupère le plan
  plane = inst_def.get_attribute("dynamic_attributes", "truncat_plane", "YZ")

  
  # On test s'il y a des éléments avec un x < 0
  inst_edges = inst_ents.grep(Sketchup::Edge)
  inst_edges_out = inst_edges.filter do |e|
    case plane
    when "XZ"
      e.start.position.y < 0 || e.end.position.y < 0
    when "YZ"
      e.start.position.x < 0 || e.end.position.x < 0
    when "XY"
      e.start.position.z < 0 || e.end.position.z < 0
    end
  end
  #On annule s'il n'y aucune edge qui dépasse avec une coordonnée x <0
  raise "Aucun element à l'exterieur " if inst_edges_out.length == 0
  
  #Sinon début de la pile d'annulation
  model.start_operation("Truncat instance",true,false,false)
  
  #Agrandissement x100
  p0 = Geom::Point3d.new(0,0,0)
  tr_scale = Geom::Transformation.scaling(p0, 100, 100, 100)  
  inst_ents.transform_entities(tr_scale, inst_ents.to_a)
  
  #On filtre les faces et les arrêtes
  inst_collection = inst_ents.grep(Sketchup::Edge) + inst_ents.grep(Sketchup::Face)
  
  #On récupère la BoundingBox
  bb_ents = inst_collection.map { |e| e.bounds }
  bb = Geom::BoundingBox.new
  bb.add(bb_ents)
  
  #On récupère les dimensions de la boundingBox
  bb_w = bb.width #longueur axe X
  bb_d = bb.depth #longueur axe Z
  bb_h = bb.height #longueur Axe Y
  bb_min = bb.min #point avec le x, y et z le plus petit petit
  bb_max = bb.max  #point avec le x, y et z le plus petit grand

  # calcule des points de la face
  bb_min_x = bb.min.x - (bb_w / 2)
  bb_min_y = bb.min.y - (bb_h / 2)
  bb_min_z = bb_min.z - (bb_d / 2)
  bb_max_x = bb_max.x + (bb_w / 2)
  bb_max_y = bb_max.y + (bb_h / 2)
  bb_max_z = bb_max.z + (bb_d / 2)

  case plane
  when "XZ"
    pts_face = [
      Geom::Point3d.new(bb_min_x, 0, bb_min_z),
      Geom::Point3d.new(bb_max_x, 0, bb_min_z),
      Geom::Point3d.new(bb_max_x, 0, bb_max_z),
      Geom::Point3d.new(bb_min_x, 0, bb_max_z)
    ]
  when "YZ"
    pts_face = [
      Geom::Point3d.new(0, bb_min_y, bb_min_z),
      Geom::Point3d.new(0, bb_min_y, bb_max_z),
      Geom::Point3d.new(0, bb_max_y, bb_max_z),
      Geom::Point3d.new(0, bb_max_y, bb_min_z)
    ]
  when "XY"
    pts_face = [
      Geom::Point3d.new(bb_min_x, bb_min_y, 0),
      Geom::Point3d.new(bb_min_x, bb_max_y, 0),
      Geom::Point3d.new(bb_max_x, bb_max_y, 0),
      Geom::Point3d.new(bb_max_x, bb_min_y, 0)
    ]
  end  
  
  #Creation de la face d'intersection
  face = inst_ents.add_face(pts_face)

  #On sauvegarde les arrêtes externes de la face
  face_outer_edges = face.outer_loop.edges
  

  #Intersection de la face avec les autres entités de la définition du composant
  recursion = true
  tr0 = Geom::Transformation.new(p0)
  inst_ents.intersect_with(recursion, tr0, inst_ents, tr0, true, [face])

  # Effacement des arrêtes indésirables
  ## On efface les arrêtes de la face
  face_outer_edges.each { |e| e.erase! if e.valid? }    

  ## On récupère les arrêtes
  edges = inst_ents.grep(Sketchup::Edge)

  ## On supprime les arrêtes out
  edges.each do |e|
    case plane
    when "XZ"
      p_start = (e.start.position.y).round(rp)
      p_end = (e.end.position.y).round(rp)
    when "YZ"
      p_start = (e.start.position.x).round(rp)
      p_end = (e.end.position.x).round(rp)
    when "XY"
      p_start = (e.start.position.z).round(rp)
      p_end = (e.end.position.z).round(rp)
    end

    case
    when p_start == 0 && p_end < 0
      e.erase! if e.valid?
    when p_end == 0 && p_start < 0
      e.erase! if e.valid?
    when p_end < 0 && p_start < 0
      e.erase! if e.valid?
    end
  end
  
  
  # On rescale les entités
  tr_rescale = Geom::Transformation.scaling(p0, 0.01, 0.01 ,0.01)
  inst_ents.transform_entities(tr_rescale, inst_ents.to_a)
  
  model.commit_operation

end #Fin truncat

def menu_Truncat()
  add_separator_to_menu("Draw")
  truncat_menu = UI.menu("Draw").add_submenu("Truncat")

  cmd_add_observer = UI::Command.new("Add Truncat Observer") {  addTruncatObserver() }
  cmd_add_observer.menu_text = "Add Truncat Observer to all instances of the definition of the select instance"
  truncat_menu.add_item cmd_add_observer

  cmd_remove_observer = UI::Command.new("Remove Truncat Observer") {  removeTruncatObserver() }
  cmd_remove_observer.menu_text = "Remove Truncat Observer to all instances of the definition of the select instance"
  truncat_menu.add_item cmd_remove_observer
end

menu_Truncat()

 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? IPB_917
JDD
JDD
V.I.P.
V.I.P.
Masculin Humeur : Cool, œil de lynx à pattes de velours
Date d'inscription : 21/05/2021
Nombre de messages : 1165
Points : 2542
Age : 76
Localisation : Nord (59)
Emploi : Director of Myself

MessageJDD Dim 5 Jan 2025 - 9:48

Hello @simjoubert,

C'est étrange je pensais t'avoir répondu hier en fin d'après midi en te posant justement la question s'il était possible d'utiliser ton script en fixant d'autres plans de symétries que celui du plan YZ.
Il ne semble pas être passé, pourtant j'en avais profité pour corriger une coquille dans le titre qui lui a bien été modifié.
Je t'avoue n'avoir pas eu le temps d'analyser les résultats de ton script car j'ai quelques petits soucis à résoudre en priorité.

De nouveau, puisque mon message n'est pas passé je te remercie pour ton implication, je n'en demandais pas tant.

JDD

simjoubert et Rascal aiment ce message

simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Dim 5 Jan 2025 - 10:00

Avec plaisir mon cher JDD
Quand je me lance je veux le faire bien en essayant que ce soit fonctionnel, pratique, réutilisable!

On pourrait aller plus loin et rajouter 2 attributs : offset et sens
Le premier défini la distance à l’origine du plan de troncat, le second avec une valeur 1 ou -1 pour définir le côté à conserver

On peut aussi étendre les fonctions à du one shoot avec un bouton on sélectionne un élément groupe ou composant
Puis clic sur le bouton
Un dialogue apparaît avec les 4 attributs
En cliquant sur valider le troncat est opéré!

 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? IPB_917
simjoubert
simjoubert
Administrateurs
Administrateurs
Masculin Humeur : Des racines et des rêves !!!
Date d'inscription : 05/08/2012
Nombre de messages : 2995
Points : 6633
Age : 49
Localisation : Val de Marne
Emploi : Paysagiste
https://www.sketchup.simjoubert.com/

Messagesimjoubert Dim 5 Jan 2025 - 13:43

Hello, comme annoncé voici la version  1.3.0

Elle ajoute 2 attributs supplémentaires dans la définition du plan de Truncate ( rigole avec un e c'est mieux) :
  • Offset pour définir le décalage du plan par rapport à l'origine
  • Direction qui peut être supérieur ou inférieur, il définit l'opérateur de comparaison pour savoir quel côté du plan de découpe conserver.


L'utilisation peut se faire de manière automatisée en utilisant les observateurs ou à la volée sur une selection de composants avec l'ajout d'une 3eme commande dans le menu.

Cette dernière, test la présence de composants dans la sélection, puis propose un dialogue afin de renseigner les options du plan de découpe.

Relancez une nouvelle session de Sketchup pour utiliser le code, sinon il y aura des doublons dans le menu.
Code à copier une fois dans la console ruby.

Voici le code :
Code:
# TRUNCATE V1.3 2025/01/05
# Author Simon Joubert

# Ce script permet de tronquer tout les éléments d'un composant qui sont placés derrière un plan de découpe.
# Le plan de découpe est définit par une orientation de plan 'XZ', 'YZ' ou 'XY'.
# Un décalage par rapport à l'origine du composant et une direction pour définir quel côté sera conservé.

# Ce script ajoute dans le menu dessiner un sous menu Truncate avec 2 commandes:
##Ajouter un observateur sur chaque instance du composant et sur ses futures nouvelles instances
##Supprimer les observateurs sur chaque instances du composant

#Fonctionnement :
# selectionner un composant
# Attacher lui un Truncate observer depuis la commande Menu > Dessiner > Truncate > Add Observer

# Lors du déclenchement de la commande Add Observer un attribut truncate de valeur 1 est ajouté à la définition et au instance du composant sélectionné.
# cet attribut sert d’interrupteur 1 => truncate activé, aute valeur => inactivé

# L'observateur se déclenche à la fermeture du composant quand vous avez modifié son contenu.
# Il réalise 2 tests :
## la définition possède un attribut truncate de valeur 1 (1 => Truncate activé , Sinon inactivé)
## si Truncate activé il test si des arrêtes ont un début ou une fin avec des coordonées x <0

# Si les 2 conditions sont vraies l'opération de truncate commence (opération annulable) :
## Une face est ajoutée aux entités du composant sur le plan sélectionnée placé à une distance offset de l'origine.
## l'intersection de la face avec le reste des éléments est réalisée.
## Puis suppression des éléments "à l’extérieur", sens définit par l'attribut direction.

# N’exécutez ce script qu'une fois par session Sketchup, pour éviter la duplication des menus.

# Note de versions:
# V1.2.0
# Ajout d'un attribut pour choisir le plan selon lequel tronquer les éléments de coordonnées négatives

# V1.3.0
# Ajout d'un attribut Offset pour décaler le plan de troncat par rapport à l'origine du plan sélectionné
# Ajout d'un attribut direction pour choisir quelle côté du plan conservé

#########################################################################################################

#On défini la variable globale qui contiendra tout les observateurs
 TRUNCATE_SPYS ||= {}

# Observateur d'instance
class TruncateInstanceObserver < Sketchup::InstanceObserver  
  def onClose(instance)
    truncate_attribute = instance.definition.get_attribute("dynamic_attributes","truncate", 0).to_i
    truncate(instance) if truncate_attribute == 1
  end  
end #Fin class

# Observateur de déinition
class TruncateDefinitionObserver < Sketchup::DefinitionObserver
  def onComponentInstanceAdded(definition, instance)
    pid = instance.persistent_id
    TRUNCATE_SPYS[pid.to_s] = TruncateInstanceObserver.new
    instance.add_observer(TRUNCATE_SPYS[pid.to_s])
  end
  
  def onComponentInstanceRemoved(definition, instance)
    pid = instance.persistent_id    
    instance.remove_observer(TRUNCATE_SPYS[pid.to_s]) if instance.valid?
    TRUNCATE_SPYS.delete(pid.to_s)
  end
end


#Pour ajouter un un Truncate observer sur toutes les instances soeur de l'instance sélectionnée
def addTruncateObserver()
  model = Sketchup.active_model # Open model
  model.start_operation("Add Truncate Observer",true,false,false)
  ents = model.entities # All entities in model
  sel = model.selection # Current selection
 
  inst = sel.grep(Sketchup::ComponentInstance).first
  inst_def = inst.definition
  
  #On Verifie l'existance de l'attribut truncate on l'ajoute s'il n'éxiste pas
  dcdict = "dynamic_attributes"
  unless inst.get_attribute(dcdict, "truncate", false)
    inst_def.set_attribute(dcdict, "truncate", 1)
    inst_def.set_attribute(dcdict, "_truncate_label", "truncate")
    inst_def.set_attribute(dcdict, "_truncate_formulaunits", "STRING")
    inst_def.set_attribute(dcdict, "_truncate_units", "STRING")
    inst_def.set_attribute(dcdict, "_truncate_access", "LIST")
    inst_def.set_attribute(dcdict, "_truncate_formlabel", "Truncate status")
    inst_def.set_attribute(dcdict, "_truncate_options", "&ON=1&OFF=0&")
    inst.set_attribute(dcdict, "truncate", 1)

    inst_def.set_attribute(dcdict, "truncate_plane", "YZ")
    inst_def.set_attribute(dcdict, "_truncate_plane_label", "truncate_plane")
    inst_def.set_attribute(dcdict, "_truncate_plane_formulaunits", "STRING")
    inst_def.set_attribute(dcdict, "_truncate_plane_units", "STRING")
    inst_def.set_attribute(dcdict, "_truncate_plane_access", "LIST")
    inst_def.set_attribute(dcdict, "_truncate_plane_formlabel", "Truncate plane")
    inst_def.set_attribute(dcdict, "_truncate_plane_options", "&XZ=XZ&YZ=YZ&XY=XY&")
    inst.set_attribute(dcdict, "truncate_plane", "YZ")

    inst_def.set_attribute(dcdict, "truncate_offset", 0)
    inst_def.set_attribute(dcdict, "_truncate_offset_label", "truncate_offset")
    inst_def.set_attribute(dcdict, "_truncate_offset_formulaunits", "CENTIMETERS")
    inst_def.set_attribute(dcdict, "_truncate_offset_units", "CENTIMETERS")
    inst_def.set_attribute(dcdict, "_truncate_offset_access", "TEXTBOX")
    inst_def.set_attribute(dcdict, "_truncate_offset_formlabel", "Truncate offset")    
    inst.set_attribute(dcdict, "truncate_offset", 0)

    inst_def.set_attribute(dcdict, "truncate_direction", "1")
    inst_def.set_attribute(dcdict, "_truncate_direction_label", "truncate_direction")
    inst_def.set_attribute(dcdict, "_truncate_direction_formulaunits", "STRING")
    inst_def.set_attribute(dcdict, "_truncate_direction_units", "STRING")
    inst_def.set_attribute(dcdict, "_truncate_direction_access", "LIST")
    inst_def.set_attribute(dcdict, "_truncate_direction_formlabel", "Truncate direction")
    inst_def.set_attribute(dcdict, "_truncate_direction_options", "&Superior=1&Inferior=-1&")
    inst.set_attribute(dcdict, "truncate_direction", "1")
    
  end
  
  # on ajoute un TruncateDefinitionObserver sur la définition
  ## pour attacher un TruncateInstanceObserver sur les nouvelles instance
  ## et le supprimer lorsque l'instance est effacée  
  inst_def_pid = inst_def.persistent_id
  TRUNCATE_SPYS[inst_def_pid.to_s] = TruncateDefinitionObserver.new
  inst_def.add_observer(TRUNCATE_SPYS[inst_def_pid.to_s])
  
  # On ajoute un TruncateInstanceObserver sur chaque instance de la définition
  insts = inst_def.instances
  insts.each do |instance|
    pid = instance.persistent_id
    if TRUNCATE_SPYS[pid.to_s] == nil
      TRUNCATE_SPYS[pid.to_s] = TruncateInstanceObserver.new
      instance.add_observer(TRUNCATE_SPYS[pid.to_s])
    end
  end
  model.commit_operation
end

#Pour retirer les observateur de toutes les instances soeurs de l'instance sélectionnée
def removeTruncateObserver()
  model = Sketchup.active_model # Open model
  model.start_operation("Remove Truncate Observer",true,false,true)
  ents = model.entities # All entities in model
  sel = model.selection # Current selection
  inst = sel.grep(Sketchup::ComponentInstance).first
  inst_def = inst.definition
  #On supprime l'observer sur la definition
  inst_def_pid = inst_def.persistent_id
  inst_def.remove_observer(TRUNCATE_SPYS[inst_def_pid.to_s]) if TRUNCATE_SPYS[inst_def_pid.to_s]
  TRUNCATE_SPYS.delete(inst_def_pid.to_s)
  
  insts = inst_def.instances
  insts.each do |instance|
    pid = instance.persistent_id    
    instance.remove_observer(TRUNCATE_SPYS[pid.to_s])
    TRUNCATE_SPYS.delete(pid.to_s)
  end
  model.commit_operation
end #Fin removeTruncateObserver()

# Méthode appelé par l'observateur d'instance lorsque l'on sort du composant
# Tronque les entités du composant pour ne conserver que la partie dont les coordonées sont au-delà du plan
def truncate(inst, plane=nil, offset=nil, direction=nil)  
  model = Sketchup.active_model # Open model
  rp = 4 #round_precision
  
  inst_def = inst.definition
  inst_ents = inst_def.entities

  #On récupère les attributs du plans de troncat s'ils ne sont pas passés en paramètres
  plane ||= inst_def.get_attribute("dynamic_attributes", "truncate_plane", "YZ")
  puts "plane #{plane}"
  offset ||= inst_def.get_attribute("dynamic_attributes", "truncate_offset", "0").to_f
  puts "Offset #{offset}"
  direction ||= inst_def.get_attribute("dynamic_attributes", "truncate_direction", "1").to_i
  puts "direction #{direction}"
  
  # On test s'il y a des éléments avec un x < 0
  inst_edges = inst_ents.grep(Sketchup::Edge)
  inst_edges_out = inst_edges.filter do |e|
    case direction
    when 1
      case plane
      when "XZ"
        e.start.position.y < offset || e.end.position.y < offset
      when "YZ"
        e.start.position.x < offset || e.end.position.x < offset
      when "XY"
        e.start.position.z < offset || e.end.position.z < offset
      end
    when -1
      case plane
      when "XZ"
        e.start.position.y > offset || e.end.position.y > offset
      when "YZ"
        e.start.position.x > offset || e.end.position.x > offset
      when "XY"
        e.start.position.z > offset || e.end.position.z > offset
      end
    end
  end
  #On annule s'il n'y aucune edge qui dépasse avec une coordonnée x <0
  raise "Aucun element à l'exterieur " if inst_edges_out.length == 0
  
  #Sinon début de la pile d'annulation
  model.start_operation("Truncate instance",true,false,false)
  
  #Agrandissement x100
  offset = offset*100
  p0 = Geom::Point3d.new(0,0,0)
  tr_scale = Geom::Transformation.scaling(p0, 100, 100, 100)  
  inst_ents.transform_entities(tr_scale, inst_ents.to_a)
  
  #On filtre les faces et les arrêtes
  inst_collection = inst_ents.grep(Sketchup::Edge) + inst_ents.grep(Sketchup::Face)
  
  #On récupère la BoundingBox
  bb_ents = inst_collection.map { |e| e.bounds }
  bb = Geom::BoundingBox.new
  bb.add(bb_ents)
  
  #On récupère les dimensions de la boundingBox
  bb_w = bb.width #longueur axe X
  bb_d = bb.depth #longueur axe Z
  bb_h = bb.height #longueur Axe Y
  bb_min = bb.min #point avec le x, y et z le plus petit petit
  bb_max = bb.max  #point avec le x, y et z le plus petit grand

  # calcule des points de la face
  bb_min_x = bb.min.x - (bb_w / 2)
  bb_min_y = bb.min.y - (bb_h / 2)
  bb_min_z = bb_min.z - (bb_d / 2)
  bb_max_x = bb_max.x + (bb_w / 2)
  bb_max_y = bb_max.y + (bb_h / 2)
  bb_max_z = bb_max.z + (bb_d / 2)

  case plane
  when "XZ"
    pts_face = [
      Geom::Point3d.new(bb_min_x, offset, bb_min_z),
      Geom::Point3d.new(bb_max_x, offset, bb_min_z),
      Geom::Point3d.new(bb_max_x, offset, bb_max_z),
      Geom::Point3d.new(bb_min_x, offset, bb_max_z)
    ]
  when "YZ"
    pts_face = [
      Geom::Point3d.new(offset, bb_min_y, bb_min_z),
      Geom::Point3d.new(offset, bb_min_y, bb_max_z),
      Geom::Point3d.new(offset, bb_max_y, bb_max_z),
      Geom::Point3d.new(offset, bb_max_y, bb_min_z)
    ]
  when "XY"
    pts_face = [
      Geom::Point3d.new(bb_min_x, bb_min_y, offset),
      Geom::Point3d.new(bb_min_x, bb_max_y, offset),
      Geom::Point3d.new(bb_max_x, bb_max_y, offset),
      Geom::Point3d.new(bb_max_x, bb_min_y, offset)
    ]
  end  
  
  #Creation de la face d'intersection
  face = inst_ents.add_face(pts_face)
  face.reverse! if direction == -1

  #On sauvegarde les arrêtes externes de la face
  face_outer_edges = face.outer_loop.edges
  

  #Intersection de la face avec les autres entités de la définition du composant
  recursion = true
  tr0 = Geom::Transformation.new(p0)
  inst_ents.intersect_with(recursion, tr0, inst_ents, tr0, true, [face])

  # Effacement des arrêtes indésirables
  ## On efface les arrêtes de la face
  face_outer_edges.each { |e| e.erase! if e.valid? }    
  
 
  ## On récupère les arrêtes
  edges = inst_ents.grep(Sketchup::Edge)
  #edges = []

  ## On supprime les arrêtes out
  edges.each do |e|
    next if !e.valid?
    case plane
    when "XZ"
      p_start = (e.start.position.y).round(rp)
      p_end = (e.end.position.y).round(rp)
    when "YZ"
      p_start = (e.start.position.x).round(rp)
      p_end = (e.end.position.x).round(rp)
    when "XY"
      p_start = (e.start.position.z).round(rp)
      p_end = (e.end.position.z).round(rp)
    end

    case direction
    when 1
      case
      when p_start == offset && p_end < offset.round(rp)
        e.erase! if e.valid?
      when p_end == offset && p_start < offset.round(rp)
        e.erase! if e.valid?
      when p_end < offset.round(rp) && p_start < offset.round(rp)
        e.erase! if e.valid?
      end
    when -1
      case
      when p_start == offset && p_end > offset.round(rp)
        e.erase! if e.valid?
      when p_end == offset && p_start > offset.round(rp)
        e.erase! if e.valid?
      when p_end > offset.round(rp) && p_start > offset.round(rp)
        e.erase! if e.valid?
      end
    end
  end
  
  ## On récupère les vertices
  vertices = inst_ents.grep(Sketchup::Edge).map { |e| e.vertices }.flatten
  ## On supprime les arrêtes issues des vertices out
  vertices.each do |v|
    next if !v.valid?
    x = v.position.x
    y = v.position.y
    z = v.position.z
    case plane
    when "XZ"
      c = y.round(rp)
    when "YZ"
      c = x.round(rp)
    when "XY"
      c = z.round(rp)
    end

    case direction
    when 1
      v.edges.each { |e| e.erase! if e.valid? } if c < offset.round(rp)
    when -1
      v.edges.each { |e| e.erase! if e.valid? } if c > offset.round(rp)
    end
  end
  
  
  
  # On rescale les entités
  tr_rescale = Geom::Transformation.scaling(p0, 0.01, 0.01 ,0.01)
  inst_ents.transform_entities(tr_rescale, inst_ents.to_a)
  
  model.commit_operation

end #Fin truncate

def selectTruncate()
  model = Sketchup.active_model
  sel = model.selection
  insts = sel.grep(Sketchup::ComponentInstance)

  # Test si aucune instance dans la sélection
  UI.messagebox("There is no component instance in the selection! Operation canceled!", MB_OK) if insts.length == 0
  raise if insts.length == 0

  prompts = ["Plane", "Offset in centimeters", "Direction"]
  defaults = ["YZ", "0", "Superior"]
  list = ["XZ|YZ|XY", "", "Superior|Inferior"]
  input = UI.inputbox(prompts, defaults, list, "Define the truncate plane")

  raise if input == nil

  plane = input[0]
  offset = input[1].to_f.cm.to_f
  direction = ( input[2] == "Superior" ? 1 : -1)

  insts.each { |inst| truncate(inst, plane, offset, direction) }

end

def menu_Truncate()
  add_separator_to_menu("Draw")
  truncate_menu = UI.menu("Draw").add_submenu("Truncate")

  cmd_add_observer = UI::Command.new("Add Truncate Observer") {  addTruncateObserver() }
  cmd_add_observer.menu_text = "Add Truncate Observer to all instances of the definition of the select instance"
  truncate_menu.add_item cmd_add_observer

  cmd_remove_observer = UI::Command.new("Remove Truncate Observer") {  removeTruncateObserver() }
  cmd_remove_observer.menu_text = "Remove Truncate Observer to all instances of the definition of the select instance"
  truncate_menu.add_item cmd_remove_observer

  cmd_truncate_select = UI::Command.new("Truncate the selected components") {  selectTruncate() }
  cmd_truncate_select.menu_text = "Truncate the selected components, define the truncate plane with the dialog. Select components before launch!"
  truncate_menu.add_item cmd_truncate_select
end

menu_Truncate()

 [ SKETCHUP généralité ] Comment  éviter l'overlapping des géométries des composants en miroir ? IPB_917

tenrev et Rascal aiment ce message

Contenu sponsorisé

MessageContenu sponsorisé

Voir le sujet précédent Voir le sujet suivant Revenir en haut

Créer un compte ou se connecter pour répondre

Vous devez être membre pour répondre.

S'enregistrer

Rejoignez notre communauté ! C'est facile !


S'enregistrer

Connexion

Vous êtes déjà membre ? Aucun soucis, cliquez ici pour vous connecter.


Connexion

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum