Meine erste Figur habe ich mit Asymptote in 3D codiert. Dabei handelt es sich um einen Spielwürfel mit Seiten, die von eins bis sechs Punkten nummeriert sind und auf klassische Weise die Zahlen 1 bis 6 darstellen. Dieser Würfel kann mit der Maus manipuliert werden.
Das Problem besteht darin, dass die Scheiben, die die Punkte darstellen, beim Manipulieren der Würfel funkeln.
Wenn ich die Draw-Anweisung (Zeile 25) kommentiere, draw(scale3(84a)*unitcube, surfacepen=white);
flackern die Scheiben gar nicht, sondern die Würfel werden plötzlich transparent. Ich schließe daraus, dass das Problem daher rührt, dass die blaue Farbe der Scheiben die weiße Farbe der Flächen überdruckt. Eine Lösung wäre daher, die Flächen in zwei Schritten einzufärben, wie es mit Tikz möglich ist:
- Flächen ohne Scheiben im Rohling
- Einzelscheiben in blau
Aber die Befehle clip
, fill
, unfill
, filldraw
funktionieren nicht mit der 3D- surface()
Funktion.
Wie können wir die Seiten des Würfels einfärben, ohne dass es flackert?
Die Asymptote-Datei .asy
sieht wie folgt aus (der Code ist nicht für die Lesbarkeit optimiert):
import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path carre = box ((0,0),(84a,84a)),
disque = scale(9a)*unitcircle,
patron1[] = shift(42a,42a)*disque,
patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
patron6[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift(84a*X), tY=shift(84a*Y), tZ=shift(84a*Z);
path3 facegauche[] =path3(patron6,ZXplane),
facedroite[] =path3(patron1,ZXplane),
faceavant[] =path3(patron2,YZplane),
facearriere[] =path3(patron5,YZplane),
facehaut[] =path3(patron4,XYplane),
facebas[] =path3(patron3,XYplane);
draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);
Antwort1
Nach einer französischen Antwort in einem französischen Forum finden Sie hier eine ungefähre englische Antwort. Tatsächlich befinden sich die Scheiben auf/in den Flächen des Würfels, aber es ist nicht möglich, die relative Position der Scheiben in Bezug auf die Flächen zu ermitteln. Abhängig von der numerischen Näherung befinden sich die Scheiben über/unter den Flächen und numerische Artefakte erzeugen ein Flackern.
Lösung 1): jede Scheibe in die richtige Richtung verschieben, wie hier vorgeschlagen
import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path carre = box ((0,0),(84a,84a)),
disque = scale(9a)*unitcircle,
patron1[] = shift(42a,42a)*disque,
patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
patron6[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift((84a+00.1)*X), tY=shift((84a+.001)*Y), tZ=shift((84a+0.01)*Z);
path3 facegauche[] =shift(0,-0.001,0)*path3(patron6,ZXplane),
facedroite[] =path3(patron1,ZXplane),
faceavant[] =path3(patron2,YZplane),
facearriere[] =shift(-0.001,0,0)*path3(patron5,YZplane),
facehaut[] =path3(patron4,XYplane),
facebas[] =shift(0,0,-0.001)*path3(patron3,XYplane);
draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);
Lösung 2): Erstellen Sie die reale Oberfläche der Würfelflächen. Update: Bitte finden Sie die 2. Lösung. Tatsächlich bezulate
kann ein 2D-Pfad in einen 3D-Pfad umgewandelt werden. Laut Dokumentation
Patches planarer Bézier-Oberflächen werden mithilfe der Bezulate-Routine von Orest Shardt erstellt. Diese zerlegt (möglicherweise nicht einfach verbundene) Bereiche, die (gemäß der Zerowinding-Füllregel) durch einfache zyklische Pfade (die sich nur an den Endpunkten schneiden) begrenzt sind, in Unterbereiche, die durch zyklische Pfade mit einer Länge von 4 oder weniger begrenzt sind.
Um ein Loch zu erzeugen, muss man Folgendes verwenden reverse
(entlang des Pfades rückwärts laufen): z. B. bezulate(unitsquate^^reverse(scale(.3)*unitcircle))
. Dann surface(bezulate(unitsquate^^reverse(scale(.3)*unitcircle)))
wird die Oberfläche eines Einheitsquadrats mit kleinem Loch erzeugt. Der Code für den vollständigen Würfel.
import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
//settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path carre = box ((0,0),(84a,84a)),
// reverse est capital pour créer les trous avec bezulate
// c'est la règle : unitsquare et disque ne seront pas dans le
// même sens, donc bezulate comprend que c'est un trou
disque = scale(9a)*reverse(unitcircle),
patron1[] = shift(42a,42a)*disque,
patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
patron6[]= shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift((84a)*X), tY=shift((84a)*Y), tZ=shift((84a)*Z);
path3 facegauche[] =path3(patron6,ZXplane),
facedroite[] =path3(patron1,ZXplane),
faceavant[] =path3(patron2,YZplane),
facearriere[] =path3(patron5,YZplane),
facehaut[] =path3(patron4,XYplane),
facebas[] =path3(patron3,XYplane);
// draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);
// les faces trouées
path[] gp6=bezulate(scale(84a)*unitsquare^^patron6);
path[] gp5=bezulate(scale(84a)*unitsquare^^patron5);
path[] gp4=bezulate(scale(84a)*unitsquare^^patron4);
path[] gp3=bezulate(scale(84a)*unitsquare^^patron3);
path[] gp2=bezulate(scale(84a)*unitsquare^^patron2);
path[] gp1=bezulate(scale(84a)*unitsquare^^patron1);
surface s1=shift((0,84a,84a))*rotate(90,Y)*rotate(90,X)*surface(gp1);
surface s2=shift(84a,0,0)*rotate(-90,Y)*surface(gp2);
surface s3=surface(gp3);
surface s4=shift((0,0,84a))*surface(gp4);
surface s5=shift((0,0,84a))*rotate(90,Y)*surface(gp5);
surface s6=shift((0,0,84a))*rotate(90,Y)*rotate(90,X)*surface(gp6);
draw(s6,red);
draw(s5,red);
draw(s4,red);
draw(s3,red);
draw(s2,red);
draw(s1,red);
und das Ergebnis
OG