Pourquoi quand je supprime un polygone, il reste toujours les points, c'est nul
une astuce ??
Wow , je crois qu'il faudrait quand même que tu fasses un tour du côté des bases de C4D et de sa documentation , un minimum.
Pour virer les points , tu cliques droit et optimiser
toujours autant emballé et optimiste avec ce soft......... c'est nul
Non mais sérieux. T'inquiète pas je la consulte la doc. Je trouve naturel que lorsqu'on supprime un poly, les arrêtes et les points qui le compose disparaissent en même temps. Je suis toujours très emballé par ce soft. Je l'adore. C'est juste que vous adorez cliquer.
C4D supprime bien les arrêtes lors de la suppression du poly, oui. Il ne peut pas faire les points.
Au contraire, je trouve ça très bien que les points restent. Des fois, on a des polygones pas chouettes alors hop on les supprime et on retricote les polys en s'appuyant sur les points des polys qu'on vient de supprimer.
Un jour, j'en suis sûr, tu te diras : "Ah oui, finalement, c'est plutôt pas mal !". Au moins avec C4D tu as le choix. Peut-être faudrait-il ajouter ça dans les préfs : Supprimer les points quand on supprime un polygone.
Tout ce que j'écris est à prendre au 15e degré. Car comme dit le proverbe chinois : Quand le dragon d'or, le ragondin ; voilà qui devrait faire taire les critiques et me mettre à l'abri d'attaques frontales.
Sinon tu maintiens Maj en passant du mode polygones au mode points, puis tu supprimes les points sélectionnés.
Et oui comme les points me gêne je les supprime par les points. À voir lenogre en effet je risque de les aimer à la longue.
Une réponse pour une autre question. Comment afficher les points d objets non sélectionnés dans le viewport
Avoir une option de suppression "complete" poly et points serait quand même le bienvenue..
Car l'astuce dutiliser majuscule ne peut ne peu être utilisé que dans le cas ou les polys forme un ilot, sinon on vire une rangée de points en trop.
Du coup il faut utiliser l'option optimise et selon les cas n'utiliser que l'option "unusued points" au risque de faire des conneries. surtout que cette option est mémorisé avec le fichier, ce qui est plutôt bien, mais aussi peu être source d'erreur quand tu as une multitude de fichier ou tu est obligé de changer cette "pref" en permanence.
Alors effectivement dans le cas de bases de données simple ce n'est pas très grave, mais sur ce quoi je bosse en ce moment c'est un peu chiant. On a plus de trois km de bâtiment à découper en morceaux (c'est pour de l'impression), donc optimise a gogo, et avec ce système on a réussi à faire des conneries, genre souder des points sans le vouloir (et sans s'en rendre compte), et la base ayant évolué on ne peu plus revenir en arrière. Du coup on se retrouve par endroit avec des non-manifold et comme c'est pour de l'impression c'est plutôt gênant.
J'ai même voulu écrire une commande pour avoir l'option effacer poly avec point,
mais c'est plus compliqué que je ne pensais.
J'ai commencé a codé un script pour supprimer les polygones et les points. J'arrive à récupérer l'ID des Faces + Vertex a supprimer mais après comment faire pour les supprimer ^^'.
J'ai pensé à recréer un nouvel objet de a-Z mais bon on dois bien pouvoir mettre à jour un objet. Car sinon c'est un peu relou ^^'
Voila mon code pour le moment (il ne marche pas, il fait crash C4D). Pour ceux qui veulent tester faite un cube avec 5subdiv et selectionner par exemple 4 face côte/côte. Je sais pour le moment j'ai fait aucun check pour voir si la sélection est nul ou autre erreur d'entrée d'utilisateur.
pointToRemove va contenir l'ID du point central de ces 4 faces et idSelectedPoly contient l'ID des faces selectionnées
Merci d'avance
Code:import c4d from c4d.utils import Neighbor def getSelectedPolyID(obj): nbPoly = obj.GetPolygonCount() selectedPoly = obj.GetPolygonS() list_polys = selectedPoly.GetAll(nbPoly) buffer = [] for i in xrange(nbPoly): if list_polys[i]: buffer.append(i) return buffer def getPointIDFromPolyID(obj,polyID): buffer = [] for i in xrange(len(polyID)): buffer_a = obj.GetPolygon(polyID[i]).a buffer_b = obj.GetPolygon(polyID[i]).b buffer_c = obj.GetPolygon(polyID[i]).c buffer_d = obj.GetPolygon(polyID[i]).d buffer.append(buffer_a) buffer.append(buffer_b) buffer.append(buffer_c) buffer.append(buffer_d) return buffer def getPointsToRemove(obj,ptn): nb = Neighbor() nb.Init(obj,None) buffer = [] for i in xrange(len(ptn)): nbFaceNear = len(nb.GetPointPolys(ptn[i])) if ptn.count(ptn[i]) >= nbFaceNear and not ptn[i] in buffer: buffer.append(ptn[i]) nb.Flush() return buffer def getFaceWithoutSelected(obj,idSelectedPoly): nbPoly = obj.GetPolygonCount() buffer = [] for i in xrange(nbPoly): if not i in idSelectedPoly: buffer.append(obj.GetPolygon(i)) return buffer def getPointWithoutSelected(obj,ptnToRemove): allPoints = obj.GetAllPoints() for i in xrange(len(ptnToRemove)): allPoints.pop(ptnToRemove[i]) return allPoints def removePoint(obj,pointFinal,polyFinal): nbPts = len(pointFinal) nbPolys = len(polyFinal) obj.ResizeObject(nbPts, nbPolys) #obj.SetAllPoints(pointFinal) #for i, p in enumerate(polyFinal): # obj.SetPolygon(i, p) #obj.Message(c4d.MSG_UPDATE) #c4d.EventAdd() def main(): obj = doc.GetActiveObject() idSelectedPoly = getSelectedPolyID(obj) pointIDSelected = getPointIDFromPolyID(obj,idSelectedPoly) pointToRemove = getPointsToRemove(obj,pointIDSelected) polyFinal = getFaceWithoutSelected(obj,idSelectedPoly) pointFinal = getPointWithoutSelected(obj,pointToRemove) removePoint(obj,pointFinal,polyFinal) if __name__=='__main__': main()
Dernière modification par gr4ph0s ; 06/03/2016 à 20h15.
SDK Specialist
MAXON Computer GmbH
Mais pourquoi s'emmerder, optimiser les points non utilisés ne suffit pas ?
Avec ces deux commandes à la suite, ça marche à merveille.
Ok César je l'entends mais c'était une question.
S'il faut faire un u-o après la suppression c'est pas grave non plus
Envoyé de mon iPhone en utilisant Tapatalk
Oui dans la plupart des cas ça suffit et oui ça marche avec ces deux commandes.
Ce qui me gene c'est que optimise suprime les poits ET fusionne les points adjacents.
Dans certains cas il faut impérativement désactiver la fusion.
Quand on nettoie un objet pas de souci, mais dans le cadre du boulot que je suis en train de terminer, dont la phase finale est le découpage en morceau d'une base complexe ou on ne peut vérifier à l'oeuil ce qui se passe, et le fichier passant d'une personne à l'autre, ça nous a généré des problèmes.
Des polys on été fusionnés alors qu'il n'aurai pas du, résultant en un paquet de non-fanifold. ce qui est genant pour l'impression 3D.
Une commande directe effaçant les poly avec leurs point sans fusionner les point adjacent aurai évité ces problèmes. Et la je parle de couts de réimpression en centaines voir plus d'euros
C'est pourquoi j'ai essayé de scripter une commande, pour éviter les embrouilles.
Mais comme le montre le script de Graphos (merci au passage ) c'est pas si simple.
Du coup il a fallu etre super vigilant voir parano avec cette commande optimise.
Mais sinon oui ca marche
Dernière modification par Floc ; 06/03/2016 à 16h42.
Oui oui j'avais compris, mais je veux dire que si tu veux faire un script, il suffit de balancer la commande de suppression, puis celle d'optimisation avec uniquement la suppression des points isolés en paramètre. ^^
Mettre ces deux commandes dans un script et luia ffecter un raccourci clavier tel que Maj + Supp fonctionne pas trop mal.
Code PHP:
import c4d
def main():
if not op or not op.CheckType(c4d.Opolygon) : return
if doc.GetMode() != c4d.Mpolygons : return
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_DELETE,
list = [op],
mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
doc = doc)
bc = c4d.BaseContainer()
bc[c4d.MDATA_OPTIMIZE_POINTS] = False
bc[c4d.MDATA_OPTIMIZE_POLYGONS] = False
bc[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True
c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_OPTIMIZE,
list = [op],
mode = c4d.MODELINGCOMMANDMODE_ALL,
bc = bc,
doc = doc)
doc.EndUndo()
c4d.EventAdd()
if __name__=='__main__':
main()
C'est sûr que c'est moins amusant que de recalculer l'objet, Graphos, certes. : p
J'ai pas regardé ton script, mais quand on modifie le nombre de points ou polys d'un objet, il faut pas oublier de modifier en conséquence toutes les propriétés de type point ou polygones associées (UVW, sélections...) pour qu'elles restent cohérentes, ce qui est assez chiant.
Dernière modification par César Vonc ; 06/03/2016 à 20h23.
Sauf que la tu supprime si il y a d'autre points isolés.
Au début je pensais faire pareil mais je n'ai pas trouvé simplement de façon de passer d'une sélection de poly à une sélection de point. Et puis je me suis dis qu'explorer un peu les objets poly pourrais être cool :p
J'avais penser aussi en faisant un truc dans le genre, vu que j'ai l'ID des points a supprimer en sélectionnant les points devant être supprimé. Mais comment avoir un BaseSelect avec seulement l'ID du vertex? Puis après lancer la commande delete MCOMMAND_DELETE avec ma selection de Vertex.
Dernière modification par gr4ph0s ; 06/03/2016 à 20h37.
SDK Specialist
MAXON Computer GmbH
En rajoutant une commande pour convertir la sélection ...Code PHP:
import c4d
def main():
#si on est pas en mode polygone -> stop
if not doc.GetMode() == c4d.Mpolygons: return
#conversion de la sélection
bc = c4d.BaseContainer()
bc[c4d.MDATA_CONVERTSELECTION_LEFT] = 2
bc[c4d.MDATA_CONVERTSELECTION_RIGHT] = 0
bc[c4d.MDATA_CONVERTSELECTION_TOLERANT] = False
c4d.utils.SendModelingCommand(command =c4d.MCOMMAND_CONVERTSELECTION,
list = [op],
mode = c4d.MODIFY_ALL,
bc = bc,
doc = doc)
c4d.CallCommand(12109) # Delete
#Optimisation uniquement pour les points inutiles
bc = c4d.BaseContainer()
bc[c4d.MDATA_OPTIMIZE_POINTS] = False
bc[c4d.MDATA_OPTIMIZE_POLYGONS] = False
bc[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True
c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_OPTIMIZE,
list = [op],
mode = c4d.MODELINGCOMMANDMODE_POINTSELECTION,
bc = bc,
doc = doc)
c4d.EventAdd()
if __name__=='__main__':
main()
Sauf qu'on perd notre sélection de points. Pour ça j'ai par contre rien trouvé de mieux que de l'enregistrer dans une propriété tampon (prise en charge automatiquement par les commandes) :
Marrant comme exercice. : pCode PHP:
import c4d
def chargeSel(obj, prop) :
prop.GetBaseSelect().CopyTo(obj.GetPointS())
prop.Remove()
def sauveSel(obj) :
bs = obj.GetPointS()
prop = obj.MakeTag(c4d.Tpointselection)
bs.CopyTo(prop.GetBaseSelect())
return prop
def main():
if not op or not op.CheckType(c4d.Opolygon) : return
if doc.GetMode() != c4d.Mpolygons : return
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
# Enregistre les points sélectionnés dans une propriété tampon
tampon = sauveSel(op)
# Sélectionne les points des polys sélectinnés
bc = c4d.BaseContainer()
bc[c4d.MDATA_CONVERTSELECTION_LEFT] = 2
bc[c4d.MDATA_CONVERTSELECTION_RIGHT] = 0
bc[c4d.MDATA_CONVERTSELECTION_TOLERANT] = False
c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_CONVERTSELECTION,
list = [op],
mode = c4d.MODELINGCOMMANDMODE_ALL,
bc = bc,
doc = doc)
# Supprime les polygones
c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_DELETE,
list = [op],
mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
doc = doc)
# Optimize les points des polys supprimés
bc = c4d.BaseContainer()
bc[c4d.MDATA_OPTIMIZE_POINTS] = False
bc[c4d.MDATA_OPTIMIZE_POLYGONS] = False
bc[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True
c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_OPTIMIZE,
list = [op],
mode = c4d.MODELINGCOMMANDMODE_POINTSELECTION,
bc = bc,
doc = doc)
# Rétablit les points sélectionnés de base et supprime la propriété tampon
chargeSel(op, tampon)
doc.EndUndo()
c4d.EventAdd()
if __name__=='__main__':
main()
Dernière modification par César Vonc ; 06/03/2016 à 21h14.
Sympa les gars
Oua super !
Merci beaucoup à tous.