J'ai pensé faire ce pentagonal au fond d'une bouteille en PET de boisson gazeuse, que tout le monde a toujours vu, par programmation.
De la conclusion, environ 70 points ont été faits par auto-évaluation. Si vous êtes intéressé par le résultat, faites d'abord défiler vers le bas pour voir l'image terminée, puis décidez si vous souhaitez lire plus loin.
C'est un pentagonal.
Cette forme est communément appelée ** Petaloid **. Cela signifie "petal-oid". Il est ainsi appelé car il ressemble à un pétale vu de dessous.
Si vous avez une bouteille en PET gazéifiée à la maison, jetez un œil au bas.
Il existe de nombreuses formes de bouteilles en PET, mais en gros, seules les boissons gazeuses ont cette forme de fond. Les boissons gazeuses ont une forte pression interne, donc si elles ont la forme d'une bouteille de thé, le fond gonflera. On dit que les pétaloïdes sont utilisés pour maintenir la force parce que des problèmes tels que le roulement et l'éclatement se produisent tels quels.
Je voudrais présenter une expérience dans laquelle du bicarbonate de soude a été mis dans une bouteille de thé en PET pour tester sa force.
Il y a un secret profond sous la forme des bouteilles pour animaux de compagnie - Diamond Online
L'objectif de cet article est de générer par programme des formes pétaloïdes. Visez la qualité telle qu'elle est (ne vous attendez pas trop car mon jugement est plus bâclé que celui du grand public).
Je me suis demandé si cela pouvait être facilement exprimé avec une seule formule, mais je n'ai obtenu aucun résultat. Bien que les données de test de pression sortiront ...
Peut-être que je conçois avec la CAO.
Si vous ne pouvez pas compter sur Internet, vous devez le faire vous-même. Heureusement, j'ai autant de vraies choses que moi. Tout d'abord, utilisez un cutter pour découper uniquement le fond de la bouteille en PET.
De plus, essayez de réduire de moitié verticalement à partir du centre. De la direction 12 heures à la direction 6 heures dans l'image ci-dessus.
-Cinq de la même forme sont alignés sur la circonférence --Il y a des vallées et des pics alternés -La partie vallée est une courbe lisse du centre
Tout d'abord, comme vous pouvez le voir en un coup d'œil, cinq de la même forme sont alignés sur la circonférence, donc si vous pouvez reproduire l'un d'eux, vous pouvez voir que vous pouvez atteindre l'objectif simplement en copiant et en en disposant cinq.
En termes de forme, il existe une alternance de pics et de vallées, et les vallées ont une largeur d'environ 6 à 7 mm et semblent avoir des lignes parallèles du centre à la circonférence externe. La forme de la montagne est assez compliquée, mais elle ressemble à un éventail vu directement au-dessus (ou directement en dessous) et à un trapèze vu de côté. Pour être précis, il y a une courbe douce entre les pics et les vallées.
En regardant la section transversale, la section transversale de la partie vallée est une courbe intelligente qui ressemble à un quart d'une courbe elliptique. En revanche, la coupe transversale de la partie montagne est un peu compliquée.
De plus, ce n'est pas très pertinent pour l'article, mais la partie inférieure était assez épaisse, environ 3 mm. Au début, je me demandais si je pouvais le couper avec des ciseaux, mais j'ai dû utiliser une scie à fil car la lame n'avait pas de dents.
À partir de ces informations, réfléchissez à la manière de reproduire la forme.
Premièrement, comme politique de base, nous considérerons les choses en fonction du centre de la bouteille. Plus précisément, comme le montre la figure ci-dessous, nous allons essayer de reproduire le solide en calculant la forme de la section transversale dans la direction de l'angle azimutal θ à chaque fois avec le centre comme référence et en l'accumulant.
Ensuite, concernant la reproduction de la forme de la section transversale, il est nécessaire de générer les trois types de courbes différents suivants.
Peut-être que cela pourrait être résumé dans une formule, mais je ne peux pas y penser dans mon esprit, alors cette fois j'ai décidé d'utiliser la courbe spline (spline en cas de problème).
Comme mentionné ci-dessus, considérons comment générer trois types de courbes différents basés sur une variable appelée angle d'azimut $ θ $.
Tout d'abord, envisagez d'exprimer la courbe de la partie vallée avec une fonction spline. Comme vous pouvez le voir, cette courbe a à peu près la forme d'un arc sur une ellipse, il n'est donc pas difficile de la représenter avec des splines.
Par souci de simplicité, nous allons l'utiliser comme un cercle parfait au lieu d'une ellipse. Si vous souhaitez le ramener à une ellipse, vous pouvez l'agrandir ou le réduire verticalement.
Dessinez un cercle comme indiqué ci-dessus. Disposez $ N $ points de contrôle à intervalles égaux sur l'arc du quatrième quadrant (en bas à droite) et tracez une courbe spline cubique les reliant. Cette courbe est faite pour passer par tous les points de contrôle. Cela ne correspond pas exactement à l'arc, mais c'est une courbe qui ne se distingue pas à l'œil humain. De plus, N $ = 9 $.
Ensuite, je vais faire une courbe pour la partie montagne. Ici, traitons la courbe de la vallée et imitons la courbe de la montagne comme grossièrement observée.
Plus précisément, le point de contrôle $ (x_i, y_i) $ sur l'arc est étendu en multipliant $ k_i $ à partir du centre $ (0,0) $ du cercle ($ 1 \ leq i \ leq N $). Faites un contour approximatif comme indiqué dans la figure ci-dessous.
x'_i = x_i * k_i \\
y'_i = y_i * k_i
Tout en jetant un œil à l'image capturée, affinez la valeur de $ k_i $ pour qu'elle ait presque la même apparence. Le dernier paramètre est
\begin{align}
K &= [k_1, k_2, k_3, ... , k_9] \\
&= [1.00, 1.05, 1.18, 1.46, 1.36, 1.18, 1.07, 1.01, 1.00]
\end{align}
C'était fabriqué. Les points de bord (k1 et k9) doivent être mis à 1.0 ou le résultat sera étrange.
Augmenter le nombre de points de contrôle $ N $ pour reproduire une courbe plus précise peut améliorer la qualité, mais il est assez difficile de l'ajuster. Considérant après la fin, il aurait peut-être été préférable d'ajouter un ou deux points supplémentaires afin d'améliorer la précision de la partie inférieure (quatrième point à partir de la gauche).
L'interpolation spline de ce contour donne ce qui suit. J'ai ajusté $ k_i $ en regardant la vraie bouteille en PET de côté, donc ça ressemble beaucoup à ça.
Enfin, tracez une courbe pour la pente entre les pics et les vallées. Ceci est fait en mélangeant les courbes de crête et de vallée avec une variable appelée le rapport de déformation $ D $ (ce que vous faites est juste interpolation linéaire. % B7% 9A% E5% BD% A2% E8% A3% 9C% E9% 96% 93)).
\begin{align}
x''_i &= x_i * D + x'_i * (1-D) \\
&= x_i * (D + k_i - Dk_i) \\
y''_i &= y_i * D + y'_i * (1-D) \\
&= y_i * (D+k_i - Dk_i)
\end{align}
\quad (0 \leq D \leq 1)
L'image ci-dessus montre la courbe de la partie inclinée de 0,0 à 1,0 par pas de 0,2. D = 0 est la ligne pourpre rougeâtre et D = 1 est la ligne vert jaunâtre. Vous pouvez créer une courbe qui comble en douceur l'espace entre les pics et les creux, tels que les lignes de contour.
Au moment de décider de la politique, j'ai décidé de faire une courbe de la section transversale pour chacun des multiples angles d'azimut $ θ $. De plus, puisque nous avons introduit une variable appelée rapport de déformation $ D $ pour créer une courbe, nous devons trouver la valeur de $ D $ en fonction de la valeur de $ θ $.
Je vais dessiner un graphique de θ (0 à 360 degrés) sur l'axe horizontal et D (0 à 1) sur l'axe vertical pour clarifier cette relation. Tout d'abord, pour le sommet de la montagne, définissez $ D = 1 $. La plage de l'angle considéré comme le haut est de 22 degrés à partir de la mesure visuelle (à peu près).
De plus, définissez $ D = 0 $ pour le fond de la vallée. C'est environ 10 degrés. Comme il était difficile à comprendre car il n'apparaissait pas dans le graphique, la limite inférieure de l'axe Y est fixée à -0,2.
La partie blanche de l'écart entre l'orange et le bleu est la pente entre le sommet et la vallée. Cette partie sera remplie entre 0 et 1 avec une courbe, mais comment la remplir? C'est cool de dire que c'est mathématiquement comme ça, mais je ne suis pas si intelligent. Je vais utiliser la fonction d'assouplissement ici pour le remplir joliment.
Référence: feuille de calcul de la fonction d'assouplissement
Après avoir essayé diverses choses, j'ai choisi ʻeaseInOutQuad` parce que ça avait l'air bien.
\begin{align}
y &= easeInOutQuad(x) \\
&=
\begin{cases}
2x^2 &(0 \leq x < \frac{1}{2}) \\
-2x^2 + 4x - 1 &(\frac{1}{2} \leq x \leq 1)
\end{cases}
\end{align}
Le graphique final ressemble à ceci: Notez que la plage sur l'axe vertical est passée de 0 à 1.
Maintenant que nous avons les courbes dans toutes les directions, nous allons les utiliser pour créer un modèle 3D.
Tout d'abord, l'angle azimutal θ est découpé à intervalles égaux (par exemple, tous les 1 °) pour générer une courbe. Pour la courbe, calculez les coordonnées discrètes en M points. Concentrez-vous sur les points des deux courbes et sélectionnez les trois points pour former un polygone triangulaire.
Vous pouvez dessiner directement avec OpenGL etc. tel quel, mais cette fois je vais exporter le fichier au format DXF et l'afficher avec un logiciel de modélisation 3D.
Depuis que j'ai écrit le code en Python cette fois, j'ai utilisé la bibliothèque ezdxf qui peut gérer le format DXF en Python. L'image suivante montre le fichier de sortie avec le logiciel appelé Modo.
Voici le résultat de l'affectation des matériaux et du rendu [^ 1].
C'est le résultat affiché dans Blender. Le plug-in d'importation AutoCAD DXF doit être activé.
On dirait que ça a l'air bien de côté, mais ça ne ressemble pas très bien du bas. C'est peut-être parce que les inégalités ne suffisent pas ou parce qu'elles ne sont pas arrondies. Hum ...
Je ne pense pas que la plupart des gens le liront, alors je vais le plier.
Nécessite les bibliothèques NumPy, SciPy, ezdxf.
petaloid.py
from typing import List, Tuple
import math
import numpy as np
from scipy.interpolate import splprep, splev
import ezdxf
#Définition de l'indice de type
Point2D = Tuple[float, float]
Point3D = Tuple[float, float, float]
def mix(a: float, b: float, x: float) -> float:
"""Division interne linéaire x=Quand 0 a, x=Quand 1 b"""
return b * x + a * (1.0 - x)
def easeInOutQuad(x: float) -> float:
"""Fonction de détente"""
if x < 0.5:
return 2.0 * x * x
else:
return -2 * x * x + 4 * x - 1
def calcDeformRate(t: float) -> float:
"""
Trouver le rapport de déformation de la courbe D correspondant à l'angle azimutal t
:param t:Angle de direction(L'unité est le degré).. Lorsque le reste divisé par 72 vaut 0, cela correspond à la vallée, et lorsqu'il est à 36 °, cela correspond à la partie convexe.
:return:Rapport de déformation D(0~1)
"""
t = math.radians(math.fmod(t, 72.0))
M = math.radians(72.0) #Plage d'angle pour une saillie
k = math.radians(5.0) #Plage d'angle de la vallée
tL = math.radians(25.0) - k #Une limite latérale de la montagne
tR = (M - k) - tL #L'autre côté de la montagne
if t < k or t > M - k:
return 0.0 #Partie vallée
elif t < k + tL:
return easeInOutQuad((t-k) / tL) #Incliné
elif t < tR:
return 1.0 #Partie montagne
else:
return easeInOutQuad(((M-k) - t) / tL) #Incliné(Inverser)
def curve(angle: float, div_num: int) -> List[Point2D]:
"""
Calculez la courbe extérieure en fonction de l'angle azimutal spécifié
:param angle:Angle de direction(0~360°)
:param div_num:Le nombre de points qui composent la courbe. Plus il est, plus il est lisse
:return:Une séquence de points représentant une courbe
"""
# degree -> radian
angle = math.fmod(angle, 360.0 / 5) #Puisqu'il s'agit d'un pentagone, 360 degrés est divisé en 5 parties égales.
#Trouvez le rapport de déformation D correspondant à l'angle azimutal(D dans la vallée=0, D dans les montagnes=1)
D = calcDeformRate(angle)
#Trouvez le taux de déformation de chaque point de contrôle
#Dans la partie vallée, tous les points de contrôle sont à gauche(1.0)Et ça devient un arc
#Dans la partie montagne, tous les points de contrôle dessinent une courbe spécifiée avec le rapport sur la droite
#Autres parties(Pente de montagne)Dessine une courbe interpolée en fonction de la valeur de D
r_rate = [
mix(1.00, 1.00, D),
mix(1.00, 1.05, D),
mix(1.00, 1.18, D),
mix(1.00, 1.46, D),
mix(1.00, 1.36, D),
mix(1.00, 1.18, D),
mix(1.00, 1.07, D),
mix(1.00, 1.01, D),
mix(1.00, 1.00, D)]
#Trouvez la position du point de contrôle
xs = []
ys = []
n = len(r_rate)
for i in range(n):
deg = i * 90.0 / (n - 1)
rad = math.radians(deg)
x = r_rate[i] * math.sin(rad)
y = r_rate[i] * math.cos(rad)
xs.append(x)
ys.append(y)
#Dessinez une courbe spline cubique pour passer à travers tous les points de contrôle
spline = splprep([xs, ys], s=0, k=3)[0]
detail = np.linspace(0, 1, num=div_num, endpoint=True)
ix, iy = splev(detail, spline)
points = list(zip(ix, iy))
return points
def main():
#Faire une petite saillie au centre en bas
num_bottom_point = 8 #Score des microprojections en bas au centre
bottom_width = 0.2 #Taille inférieure centrale
bottom_height = 0.05 #Hauteur du fond central
bottom_points = []
for i in range(num_bottom_point):
n = i / num_bottom_point
angle = n * math.pi
x = n * bottom_width
#Y avec cos=[1.0,1.0+height]Faire une courbe
y = 1.0 + (math.cos(angle) + 1) / 2 * bottom_height
bottom_points.append((x, y))
#Créer une liste tridimensionnelle de sommets représentant des figures pétaloïdes
num_curve: int = 180 #Nombre de divisions azimutales(360 à chaque fois,180 est toutes les 2 fois)
num_point: int = 50 #Nombre approximatif de courbes dans une direction(Y compris le point central)
num_point_curve = num_point - num_bottom_point # (Excluant le point central)
aspect_adjust: float = 0.75 #Valeur d'ajustement du rapport d'aspect
vertices: List[Point3D] = []
for i in range(num_curve):
#Trouvez la courbe pour chaque direction
theta_deg = 360.0 / num_curve * i
theta_rad = math.radians(theta_deg)
points1 = curve(theta_deg, num_point_curve)
#Connectez-vous avec la petite saillie au centre
points2: List[Point2D] = [*bottom_points]
for p in points1:
#À travers la courbe(X)Écraser un peu dans le sens et faire de la partie vacante une surface plane(Quel processus délicat ...)
x = bottom_width + p[0] * (1.0 - bottom_width)
y = p[1]
points2.append((x, y))
#Convertir en coordonnées 3D
c = math.cos(theta_rad)
s = math.sin(theta_rad)
for p in points2:
x2 = p[0]
y2 = p[1]
x3 = x2 * c
y3 = y2 * aspect_adjust #Ajuster le rapport hauteur / largeur
z3 = x2 * s
vertices.append((x3, y3, z3))
#Divisez en triangles
indices: List[Tuple[int, int, int]] = []
for angle in range(num_curve):
a0 = angle
a1 = (angle + 1) % num_curve
for i in range(num_point - 1):
i00 = a0 * num_point + i
i01 = a0 * num_point + i + 1
i10 = a1 * num_point + i
i11 = a1 * num_point + i + 1
if i != 0: #Seul le centre est un triangle, alors excluez-le pour qu'il ne se chevauche pas
indices.append((i00, i10, i11))
indices.append((i11, i01, i00))
#Sortie avec dxf
#Je l'ai divisé en sommet et index, mais comme la face 3D de dxf n'a que des sommets,
#Synthétiser une liste de sommets
triangles: List[Tuple[Point3D, Point3D, Point3D]] = []
for i in indices:
v1 = vertices[i[0]]
v2 = vertices[i[1]]
v3 = vertices[i[2]]
triangles.append((v3, v2, v1))
doc = ezdxf.new('R2010') # MESH requires DXF R2000 or later
msp = doc.modelspace()
for t in triangles:
msp.add_3dface(t)
doc.saveas("petaloid.dxf")
if __name__ == '__main__':
main()
Je ne suis plus motivé. Si vous avez une personne étrange qui veut défier un pétaloïde plus complet, veuillez vous y référer.
--Reproduction d'une constriction plus réaliste Lorsque vous regardez la réalité, les deux extrémités de la partie de la vallée semblent plus resserrées. En particulier, la vallée du côté central a un rétrécissement en forme de U, mais cette fois j'ai renoncé à penser que le calcul serait trop compliqué à terminer. Je ne sais pas quoi faire spécifiquement, mais ce serait bien d'avoir un élément qui change non seulement avec l'angle azimutal mais aussi avec la distance du centre ou l'angle zénithal.
Q. Pourquoi seulement le bas? Et le corps? A. Je suis épuisé \ _ (: 3 "∠) \ _
[^ 1]: Après avoir importé DXF, Mesh CleanUp est exécuté pour combiner des polygones. De plus, une surface de subdivision est utilisée pour lisser la forme.