extend/modify a list interactively

lohabithi shared this question 5 years ago
Answered

Hello,

I am trying to create a custom tool that can extend a given list.

The list would start like L_1={}, and then each time I actionate the tool, one more point (or line, or vector) would be added, like:


Setvalue(L_1, Length(L_1)+1, A)

(assuming A is a point given as an input to the custom tool)


It would be probably easy to do if there was a scripting option like "scripting on creation", but there is only "on click" and "on update". Further, "on click" seem to work only for buttons.

Is there a way to turn around this limitation?

For example, we could create a polyline interactively by adding points to it (but not only that, we could create and modify any list interactively).

Thanks,

Laurent

Best Answer
photo

The more you write, the less clear is what you really want.

I refer to your first text:

------------Quote--------------------

I am trying to create a custom tool that can extend a given list.

The list would start like L_1={}, and then each time I actionate the tool, one more point (or line, or vector) would be added, like: Setvalue(L_1, Length(L_1)+1, A)

(assuming A is a point given as an input to the custom tool)

---------------------------------------

The output of an user-tool can be a text-object.

this text-object can be hidden and can include a key-word (for example "$UsrTool$") and after that the object-name from an input-parameter of the user-tool. Then the command in the user-Tool is: outUsrTool="$UsrTool$"+Name(A) (in which A is for example a point). Note: only for input-parameter of the user-tool exist a Name(). And not for generated objects.

The text-objects become the names text1..textnn. This is depending from actual-language.


Its possible to create a (dynamic) list with all the objects (for example points) from all textnn there are created with the user-tool (and has the value "$UsrTool$" at beginn).

usrtoolPointList = RemoveUndefined(Zip(If(First(P, 9) ≟ "$UsrTool$", Object(Take(P, 10))), P, RemoveUndefined(Sequence(If(IsDefined(Object("text" + (n) + "")), Object("text" + (n) + "")), n, 1, 500))))


  • Note1: Object("text" + (n) must be change (2 time) for the actual language for example: "testo" for italian.
  • Note2: its also possible you create in the user-tool something like outUsrTool="$UsrTool${"+Name(A)+","+Name(B)+"}" (not tested myself)
  • Note3: its possible to rename or delete the points (user-tool input objects)
  • Note4: the points (user-tool input objects) can be created by a command outside of the user-tool
  • Note5: No JS-scripts and No GGB-scripts are necessary (! ! !)

Comments (16)

photo
1

Looking into similar questions, I found some javascript code here, posted by RAMI, that looks like working well and that I will try to use:https://help.geogebra.org/t...

There is also something similar here:

https://help.geogebra.org/t...

But given the question asked, and the complication of the coding, the person seem to have copied a piece of code without understanding it very well...

Anyway, if someone has some suggestion that use the minimum amount of javascript (of which I know nothing), it would be helpful!

photo
1

I have tried to do it within geogebra script, but it seems like it is impossible. GGB script doesn't give access to selected objects, or to the last created (or the last selected) object, it can't launch a custom tool without specifying all the parameters (no access to clicking), and there seem to be no way an object created by a tool or by a custom tool can have a calculated name... So, there seem to be no way outside of javascript.

The problem with the files above, is that they don't work smoothly as soon as they are used in alternance with geogebra commands using the points generated. Even a simple polyline disturbs the process.

photo
2

The more you write, the less clear is what you really want.

I refer to your first text:

------------Quote--------------------

I am trying to create a custom tool that can extend a given list.

The list would start like L_1={}, and then each time I actionate the tool, one more point (or line, or vector) would be added, like: Setvalue(L_1, Length(L_1)+1, A)

(assuming A is a point given as an input to the custom tool)

---------------------------------------

The output of an user-tool can be a text-object.

this text-object can be hidden and can include a key-word (for example "$UsrTool$") and after that the object-name from an input-parameter of the user-tool. Then the command in the user-Tool is: outUsrTool="$UsrTool$"+Name(A) (in which A is for example a point). Note: only for input-parameter of the user-tool exist a Name(). And not for generated objects.

The text-objects become the names text1..textnn. This is depending from actual-language.


Its possible to create a (dynamic) list with all the objects (for example points) from all textnn there are created with the user-tool (and has the value "$UsrTool$" at beginn).

usrtoolPointList = RemoveUndefined(Zip(If(First(P, 9) ≟ "$UsrTool$", Object(Take(P, 10))), P, RemoveUndefined(Sequence(If(IsDefined(Object("text" + (n) + "")), Object("text" + (n) + "")), n, 1, 500))))


  • Note1: Object("text" + (n) must be change (2 time) for the actual language for example: "testo" for italian.
  • Note2: its also possible you create in the user-tool something like outUsrTool="$UsrTool${"+Name(A)+","+Name(B)+"}" (not tested myself)
  • Note3: its possible to rename or delete the points (user-tool input objects)
  • Note4: the points (user-tool input objects) can be created by a command outside of the user-tool
  • Note5: No JS-scripts and No GGB-scripts are necessary (! ! !)

photo
1

Hello Rami,

I think I understood what you have done.

For my worksheet I indeed needed 2 inputs (it's a set of forces) so I made the file attached, following the idea you suggested in your note(2).

I tested it by adding free texts, then adding elements, then removing the texts, adding and removing elements in any order, and it seems to be working.

(An easy way to verify if the link between inputs is preserved is to draw vectors and polygons between them. If these vectors or polygons are disturbed it means it doesn't work).

Please see if you can suggest any problem or improvement!

I will post my funicular drawing here after it is completed.

Thanks,

Laurent

photo
1

Sorry, the previously attached file does not work. There are some issues when many points are erased at a time, or when the last point is erased: The list definitions are also erased.

To retrieve these definitions I have made a button, that initialises all these lists in case they are lost...

photo
1

I see, my idea in Note 2 can't work.

But your solution for 2 points is correct.

It's imperative to separate the 2 points to create Object(<1>) and Object(<2>) in 2 separate (synchrone) list.

photo
1

I think your idea works if you accept to have to click on one button to run a script, with the "execute" command, that would execute the brackets, taking it as a code to run. But I wanted to avoid one more click.

photo
1

It's depending in what object you write the OnUpdate-script (instead of an button.). But this i have not tested,

And sometime its also depending of the sequence in the constructions-protokoll (with drag and drop the sequence can be change in the constuctions protokoll)

But without scripts (Execute()) you have generally less problems with the timing and the dependencies.

photo
1

Quote rami: But this i have not tested

Now is tested, see attachment (some time (?) performance bad)

conclusion: Note2 (in my first post) is possible but need a script (script must not be in a button)

photo
1

Hello Rami, congratulations, your solution is very elegant, it is conceptually simple and concise in code!

But it is also a little slow, probably because of the script. At each definition, the script makes GGB copy again the entire list of names, and as a result it becomes slower as the number of points increases (when it reaches 100 or so, otherwise it is hardly noticeable). But in my definition I can take advantage of GGB's internal optimisation, which probably doesn't recompute an entire list if only some of its elements are changed, and no slowing down is noticeable with increase in number. or at least I didn't notice. So despite its complication, I will keep my method.

Also I will keep the "initialisation" button for when I want to erase all points, so that the lists are not lost. Like that I can also start with a blank sheet, which is nice, otherwise I have to remember to always keep at least 2 arbitrary twin points, just to preserve the lists.

Also a minor bug in your code: When a name is modified, an error message appears. But the error doesn't disturb anything, you just click and continue working.

photo
1

About the bug:

Add in the script OnUpdate "allPntEXE" as first line/command: UpdateConstructio()

--------------------------

About reset / back to the initial-values:

Add a button with the (very small) JavaScript (choose at bottom JS)

ggbApplet.reset()

--------------------------

About performance:

Maybe it's possible to write a universal JS-addListener the create a list with the names of all text-objects (include synchronization with Algebra-View and Constructions-Protokoll). If this is possible, then also the language-option is no problem.

photo
photo
1

Dear Rami: You are a genius. I have no other words!

Thanks a lot for your highly specific, pointed and successful effort at solving my problem!

I will need time to understand what you have done, but it just works, and no script at all!!!

Laurent

photo
1

You have in effect solved the problem of making an editable polyline, an editable polygon, and generally, an editable construction based on a changing number of objects!

Congratulations!

Laurent

photo
photo
1

Dear Rami,

Please have a look at the file attached. I have finally completed my goal: A fully interactive funicular. This was possible only thanks to the "input name / object" mechanism you have created and given me in your post above. A big thank to you!

It draws a funicular polygon through a given point, with a given slope at the point.

The funicular portion works, more or less (the mechanism works, but it needs some refinement to make it more convenient).

But there is one problem: Whenever I erase the first vector, which was created using the tool "tagged 2 inputs a", and if I save the file, it doesn't work again after opening.

Clicking the init button has no effect.

Even, if I execute manually the code in the "init" button, it still doesn't work.

I seems the very first line:

alltexts=RemoveUndefined(Sequence(If(IsDefined(Object("text" + (n))), Object("text" + (n))), n, 1, 500))

just doesn't work anymore!

This looks like a bug in geogebra. Because if it works before closing the file, it should work again after re-opening it!

++++++++++

Apart from that, the funicular part works more or less, you can add and remove as many forces as you want, in any sequence, and the funicular navigates it way through the forces as they physically hit the path. So the principle works.

I just have to find out how to eliminate force duplicates when I trace the funicular in two opposite directions (because I want to be able to position the reference point from anywhere in the structure, so I have to trace the funicular in two directions, from a given point). But this should be easy.

photo
2

sorry, I'm completely overburdened with this application and as a result also how the bug could arise.

In my opinion, a GGB bug is not very likely. As long as no cause/effect is analyzed (only one example: Object() and sequence in Construction-Protocol, before and after save/reopen), this assumption is even counterproductive because it psychologically prevents. to be creative about the possibilities and to find the error.

Note: Object() is an very critically command. See the docu in the manual.

photo
photo
1

unos pocos comentarios al trabajo realizado (gran trabajo realizado por Rami).

dejando claro desde el principio que yo no soy diseñador de GG y ni siquiera soy un programador de nada; de simple profe de matemáticas no paso; es posible que toda mi suposición en este comentario sea falsa y probable que algo lo sea.

después de unas 200 hojas de trabajo creadas, modificadas, guardadas y abiertas de nuevo no me extraña que Rami esté hiperquemado, pues cosas que funcionan de pronto dejan de funcionar.

Rami lo resume en que Object() is an very critically command. See the docu in the manual. En dicho manual avisan sobre todo de que el objeto llamado debe estar antes de la llamada en el protocolo de construcción, o sea, que si queremos Object("A") el objeto llamado A debe estar en el protocolo antes que el comando Object(). Rami ha intentado, puesto que era la finalidad del trabajo, llamar a todos los posibles objetos de texto, existan o no, de la hoja. Esto parecía hacer que al guardar un archivo y luego abrirlo, sobre todo si se borraban los textos, entonces diera error. Después de muchas pruebas me pareció que el problema no era que los objetos a leer todavía no estuvieran creados, pues sin estar creados a veces funcionaba. Pero de pronto vi que cuando un objeto estaba creado y se borraba el hueco que dejaba en la lista era rellenado de forma distinta que cuando era un desconocido. O sea, de alguna forma GG recordaba el tipo de objeto que había leído y/o en el caso de listas intentaba mantener la coherencia del tipo con el primero de la lista. Así pues, la solución podría estar en empezar todas las listas con el comando object() con un objeto del tipo que deseábamos leer a lo largo de la lista. De hecho si el elemento 1 era un texto los no existentes se rellenan con "" y si el primero está borrado se rellena con ?

creo haber solucionado este problema con la creación de un texto y un punto falsos (que no se usan para nada) para ponerlos como primer elemento de las listas de Object() y que así GG sepa de qué tipo deben ser los elementos que todavía no han sido definidos. por supuesto he probado un centenar de veces el resultado final y funciona bien. si alguien lo prueba y falla me gustaría que me lo comentase para ver de remediarlo.


también he subido una versión que usa javascript. tiene la ventaja de que funciona aunque se cambie el idioma o se renombren los textos. esto me lleva a comentar que últimamente se ven muchos posts que dicen " cómo puedo hacer esto pero sin scripts". esto es como preguntar cómo se hace un buen documento en word sin usar estilos y saltos de sección. la respuesta casi siempre es simple: si no usas script no se puede. de hecho creo que el 'overburdening' se ha producido por olvidar la máxima "dime qué quieres hacer, no cómo lo quieres hacer". otra mala costumbre es no subir el ggb para su análisis. no lo hagáis, da mucho trabajo.

por ultimo comentar que he decidido usar la hoja de calculo y no usar iterationlist(). parece que usar la hoja de calculo en lugar de iterationlist() da menos categoría al trabajo porque no permite aumentar el numero de objetos que se iteran. sobre esto pienso que como todo tiene un limite pues yo le he puesto 38 (edad de Pau Gasol) y tiene la ventaja de poner colorines.


supongo que el autor del hilo querrá más opciones en la hoja. creo que tiene todas las herramientas necesarias y lo bastante simples como para completar cualquier deseo sobre este trabajo

muchas gracias a Rami por darnos la capacidad de añadir o quitar puntos a una lista con libertad.

https://www.geogebra.org/m/dsjwhz6r


© 2023 International GeoGebra Institute