Ajout de graphiques linéaires à ma bibliothèque de graphiques
Pour ajouter de nouvelles fonctionnalités, je voulais aujourd’hui faire les choses un peu différemment. Habituellement, j’ajoute des fonctionnalités de manière quelque peu aléatoire à n’importe quelle partie du module qui, selon moi, en a le plus besoin, mais aujourd’hui, je vais ajouter une fonctionnalité à la fois à HDraw et à HPlot individuellement.
Ligne
À partir de HPlot; les nuages de points sont cool et tout, mais Hone va évidemment devoir faire beaucoup mieux que cela pour être une bibliothèque graphique vraiment géniale. L’un des autres types les plus importants de tracés continus sont les tracés linéaires, qui devraient être relativement simples à créer. Pour la première étape, nous allons commencer par créer notre fonction _arrayline (). Voici mon brouillon original:
function _arrayline(x,y,axiscolor=:lightblue,
grid=Grid(3), custom="", frame=Frame(1280,720,0mm,0mm,0mm,0mm))
pairs = []
for (i,w) in zip(x,y)
append!(pairs,[i,w])
end
println(pairs)
lin = Line(pairs)
expression = string(",(context(),",lin.update(),",")
expression = string(expression, "(context(),", axisx_tag,grid_tag,custom, axisy_tag,"),")
tt = transfertype(expression)
frame.add(tt)
show() = frame.show()
tree() = introspect(composition)
save(name) = draw(SVG(name), composition);
get_frame() = frame
(var)->(show;composition;tree;save;get_frame)
end
Donc, la première erreur que j’ai rencontrée avec cette fonction est que l’ajout des paires ajoute simplement les deux nombres, pas réellement le NTuple des deux paires. Si je suis honnête, je ne sais pas vraiment comment changer cela, mais ma première inclination est que je pourrais peut-être utiliser la poussée! fonction, plutôt que l’ajout! une fonction. Donc, avec cette idée, j’ai mis en place un petit test où je pousserais deux paires distinctes dans un tableau de paires, comme ceci:
Et le test a réussi!
Cependant, chaque fois que j’essayais cela sur la fonction, j’obtenais toujours l’erreur de limites.
Ce problème semble familier et je crois que j’ai rencontré ce même problème à l’origine chaque fois que j’ai créé la fonction de ligne. Fait intéressant, cela est probablement la cause de la fonction de mise à jour qui ne fonctionne pas également pour la ligne. Heureusement, tout en récurant le Documentation de la structure de données Julia, Je suis tombé sur un gros indice!
Ici, nous pouvons voir que c’est en fait le type de données du dictionnaire qui est utilisé pour créer le type de données de la paire. C’est un peu déroutant car je ne pense pas que je serais en mesure d’affirmer la paire Pair, en fait, je pensais que le type s’appelait autre chose, mais intéressant, chaque fois que la syntaxe du dictionnaire est utilisée avec une clé et une valeur correspondante il deviendra automatiquement une paire. Nous pouvons également le visualiser en l’imprimant.
Maintenant, après avoir décommenté et rendu le type de transfert itérable dans la méthode frame.add (), nous avons rencontré cette erreur:
Heureusement, j’ai frappé cette dernière fois que j’ai fait une méta-expression, qui était pour cet objet de grille. Cela signifie que nous avons une virgule supplémentaire. Après avoir supprimé cela, ainsi que le « fluff » que je n’ai pas encore ajouté, comme les lignes d’axe et la grille, voici le résultat:
Maintenant, cette fonction fonctionne complètement, mais si nous l’exécutions, nous n’obtiendrions bien sûr rien:
Vous vous demandez peut-être:
Pourquoi donc?
Il peut y avoir quelques choses en jeu ici. Premièrement, la ligne que nous utilisons n’est peut-être pas nécessairement d’accord avec la courbe, et c’est bien parce que nous pouvons ajouter une nouvelle ligne courbe à HDraw.jl assez facilement. Deuxièmement, la mise à l’échelle est également importante et continuera d’être un problème pour tout tracé que nous tracerons…
Ce que j’ai décidé de faire ensuite était de faire en sorte que chaque ligne ne contienne que deux paires au maximum. Pour ce faire, j’ai inversé l’expression pour ajouter des balises uniquement lorsqu’une condition est remplie. Cette condition déterminera le nombre de paires parcourues depuis la dernière fois qu’une ligne a été ajoutée à l’expression.
Mais ça n’a pas marché non plus…
Donc, à ce stade, ma seule théorie est que le type de paire n’est peut-être pas le type correct pour la fonction Ligne. Pour tester cela, j’ai créé une nouvelle ligne et passé le type de paires à travers elle:
Et pour confirmer que ce soupçon est correct, j’ai fait de même avec la syntaxe d’origine:
D’accord, j’avais donc raison.
Alors maintenant, je dois comprendre comment ce type est appelé:
Et maintenant, essayons d’affirmer ce type à une paire de coordonnées.
Ça a marché!
Il ne nous reste plus qu’à l’appliquer à nos paires!
Mais quand nous essayons de lancer ceci:
Il semble que ce problème provienne de la méthode push! (). Pour tester cette théorie, j’ai décidé d’essayer de pousser un tuple normalement.
Il semble que je sois en fait incorrect. Donc, cette erreur de limites est probablement levée chaque fois que le tableau est analysé. Pour tester cela, je viens d’ajouter un println () après la boucle qui remplit les paires. Cela nous permettra de savoir si la fonction va si loin avant de lancer l’erreur de limites. Cela nous permettra également d’avoir un aperçu des paires qui sont passées.
Effectivement, les paires ont été imprimées avec succès. Cela soulève cependant une question: d’où vient exactement l’erreur? Peut-être que la fonction Line () est à blâmer?
Eureka!
Pour déboguer cela, j’ai décidé d’essayer d’analyser une expression contenant la même syntaxe pour voir pourquoi cela ne fonctionne pas:
tupearr = []
tupe = Tuple([5,10])
push!(tupearr,tupe)
lin = Line(tupearr)
Mais cela:
lin = line([5,10])
Ce que je vois comme le problème potentiel est que notre tableau est un tableau de type
Array{Any}
Quand devrait-il être
Array{Tuple}
Cependant, chaque fois que nous essayons de pousser! () Ou d’ajouter! () À un type Array {Tuple}, nous obtenons:
À mon avis, il existe deux solutions à ce problème.
- Je crée une nouvelle fonction de répartition pour la méthode append! () Qui peut gérer un tableau de tuples.
- Je trouve un type différent qui peut contenir des Tuples et a déjà son envoi en base.
- Je pourrais convertir le type du tableau en tableau de tuple après avoir ajouté mes données.
Le troisième semblait être l’option la plus simple, c’est donc ce que j’ai choisi. Pour ce faire, j’ai d’abord poussé mes données vers le type Array {Any}:
tupearr = []
tupe = Tuple([5,10])
push!(tupearr,tupe)
Et puis a tenté d’affirmer notre type Array {Tuple} à ce type.
Ça a marché!
Essayons maintenant de brancher cela dans notre fonction Ligne:
Fabuleux!
Il ne nous reste plus qu’à réintégrer ce concept dans notre fonction.
Ça marche enfin!
Wow, celui-là était un doozee.
La mise à l’échelle est foirée, mais c’est juste parce que je semble accidentellement avoir changé de math. Plutôt que:
x = (i * topx /frame.width)
y = (w * topy / frame.height)
Ça devrait être:
x = (i / topx * frame.width)
y = (w / topy * frame.height)
Ça a l’air beaucoup mieux! Pour ajouter la touche finale, nous ajoutons simplement la balise de notre objet de grille et notre axe au mélange.
Texte
Une caractéristique qui manque définitivement à hone est la possibilité de dessiner du texte, et plus précisément:
Étiquettes.
Cela devrait être relativement simple et facile à faire, voici ce que j’ai trouvé:
function Text(label,x,y,stroke,size)
color = string(""",string(stroke),""")
label = string(""",string(label),""")
tag = string("text(",x, ",", y, ",", label, ",hcenter, vcenter),",
"stroke(", color,
"), fontsize(", size, "),")
expression = string("compose(context(), ",tag,")")
exp = Meta.parse(expression)
show() = eval(exp)
update() = tag
(var)->(show;expression;tag;exp)
end
Bien que je ne m’attendais certainement pas à ce que cet article montre un excellent exemple de la façon de déboguer lors de la programmation, j’ai l’impression que c’est exactement le cas. Bien que ce problème de ligne ait été certainement difficile, une fois terminé, il a certainement été gratifiant. L’objet texte est également une étape importante et fera certainement son chemin dans la mise en œuvre dans d’autres fonctions de Hone.