Hey,
I wanted to ask if no one yet is assigned the task python-brlcad task and wanted to add a proposal for the same. I am a former Code in finalist and have some experience with working with brlcad and for other open source organizations as well. Hope I am not too late and the task hasn't been assigned yet.
Hello, @Jaipal Singh . congrats on being a part of the community ! For the start, can we have your database updated on http://brlcad.org/wiki/Google_Summer_of_Code/2018 . Plus it is a good practice to maintain regular dev logs, and we've been following this for long. I suggest doing this first and then coming up with a prototype for immediate next task you are planning to do.
Oops, posted in the wrong stream! :(
Hey @Shubham Rathore Thanks a ton!
Yea sure thing, it'll be up and updated soon.
Would you recommend hosting the devlogs on BRL-CAD's website or would you recommend using an external page (maybe a blog or a github.io page)
I'm on the verge of completion of my sessionals at university in a couple of days. I'll start work on formalizing the project, latest by the 1st of May. :)
all we need are dev logs ! Up to you :)
Sure thing! @Shubham Rathore
Hey @Shubham Rathore , I've pushed introduce a new primitive (ell) and also given an example for the same. https://github.com/Killthebug/python-brlcad-tcl/commit/a0973c5b42615e0ef53ba9c876ee14992e1df937
If this looks good, I can start working on integrating the other primitives as well :)
Hey @Shubham Rathore , I've pushed introduce a new primitive (ell) and also given an example for the same. https://github.com/Killthebug/python-brlcad-tcl/commit/a0973c5b42615e0ef53ba9c876ee14992e1df937
If this looks good, I can start working on integrating the other primitives as well :)
@Jaipal Singh you mentioned it earlier but can you explain again the difference with the different approaches being taken? also, do you have a write-up of your project plan posted up somewhere?
Hey @Sean , you can find a write-up of the project plan at : https://brlcad.org/wiki/User:Schindler97/GSoC18/Project
So, the original version of python brlcad (as developed by Kanzure in 2014) involved using ctypesgen. What ctypesgen does is that it allows you to load a DLL, dynamic-link library on Windows, shared libraries .so on Linux (or a dylib on macOS) and call functions from these libraries, directly from Python.
Now there are a couple of issues with using ctypesgen :
1. It sometimes has platform specific code
2. These bindings are brlcad version dependent, we figured this out when we saw errors in working with the original bindings on the latest SVN builds.
The other approach as developed by nmz787 (the one I propose we use) is fairly straight forward. You can have individual files that creates a tcl file (of either a simple primitive or a complicated shape involving multiple primitives), then sends the tcl file to mged. This then creates and populates a .g file database, then the .g file is converted with g-stl to produce an STL file.
Introducing newer primitives and also creating newer shapes in this approach is less complicated than the original approach. One advantage of this approach is that it does not need to interact with the brlcad binary, hence also making it (in a way) version independent.
Also, we use TCL just to write intermediate conversions
@Shubham Rathore , procedural geometry objects sounds like a good idea. Could you please elaborate more on that? I have a feeling that the tcl based approach does solve the problem of creating database objects that are described at run-time.
@Jaipal Singh thanks for the background, very helpful
Sure thing :)
so it sounds like there are several considerations to make then, especially with procedural objects being a primary desirable feature
Yea, though I'm still a little in the dark about how procedural objects work.
a couple observations first though -- you said the ctypesgen bindings are version dependent but that is also true of calling mged -- it's just as likely that a ged command syntax will change
Oh! I wasn't aware of that
the main difference being that with one you'll get a compile-time error about the change and the other, you just get bad runtime behavior
How often would the ged command syntax change (is there a way to predict this?)?
Yea, though I'm still a little in the dark about how procedural objects work.
so they currently don't -- this is a feature that doesn't yet exist but has been on our todo for years, incredibly powerful
there's no way to predict ged command changes -- they change all the time just like API changes all the time
Uh okay!
so for understanding procedural objects, have you gone through the tutorials?
created some geometry
Yea, I have
Though not for "understanding procedural objects", I was just trying to get a feel of how mged works and what all it can do
suggest taking a few hours to get through all of the Introduction to MGED tutorials -- they take less than a day but introduce you to basic terminology and concepts used throughout BRL-CAD
it's at http://brlcad.org/wiki/Documentation
Sure thing!
I've gone through Chapters 1-3 at http://brlcad.org/VolumeII-Introduction_to_MGED.pdf
excellent, if you can make it through all 16 that will help a fair bit
they're not the most exciting, but part of learning the terminology is through use, exposure, and repetition
I could definitely do that. Probably make some fun stuff along the way as well :P
modeling your own thing after going through the tutorials is something I've found very effective as a next step
so back to procedural objects -- check out the section in the TODO file for starters
it might not all make sense if you've only gotten through lessons 1-3, but it's a short section
I get the part until "similar to shader, material, and other object constructs", after that it's difficult to grasp
So, I imagine something like an interactive shape creator?
nods
sort of
the general idea is to have an object that is fully defined by a script
Where in the user could request a cube and then the system prompts the user asking him for the dimensions of the cube.
Similarly, he can then add more and more primitives to create a complicated shape.
So this script is also a template of sorts in which you can fill up different values at runtime right?
I mean, the script would generate placeholders and get the user to fill them in
it could take inputs
so yes, sort of
it could also take no inputs and just generate something via a script
do you know any shell scripting?
Oh okay
And the script could be a tcl script?
Yea, I can work my way around a linux system fairly decently
have you seen this -- http://brlcad.org/wiki/SGI_Cube ?
ignore everything after RENDER THE CUBE
basically that script is just some simple shell scripting that invokes mged commands (not unlike what nmz was doing in python) to create geometry
now you can hopefully easily imagine that script in python form (in fact it might be an interesting exercise to replicate the script in python)
as all it is doing is creating a bunch of rcc's and sph's using the ged 'in' command, and then grouping it all together
Yea, the script makes sense!
what does the -c "classic console mode" do?
that just tells mged to not even worry about starting up a GUI
classic mode aka command mode
Ah! Alright
now here's the trick
INSTEAD of a file outside of mged run through an interpreter that invokes mged ...
imagine the script inside a .g file as an object, and that is run by an interpreter mged (or librt) invokes
I'm trying hard to wrap my head around this
:)
maybe let's try a simple example .. I'm going to create a procedure that makes a unit sphere, that's all it does
Alright
This is a bash script, let's assume that for now?
doesn't really matter -- it can be a python script
Alright
if it's a #!/bin/bash script, it would be a one-liner that said something like mged -c temp.g in sph sph 0 0 0 0 0 1 1000
not very clever, it just makes a sphere at the origin (0,0,0) of size 1000mm (1m)
in python, what would that look like currently?
Uhm, we could access mged using subprocess
that's under the hood -- what would the python look like?
the script
there's currently no wrapper or encapsulation for shell script, so we call mged directly
import subprocess
bashCommand = "mged -c temp.g in sph sph 0 0 0 0 0 1 1000"
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
Oh! Oh alright!
we had to directly invoke mged for shell script -- but I could totally create a wrapper like nmz did for python, so it's something simpler, so my shell script might look like: sphere create 0 0 0 1000
Yea! That could be easily done
Coupled with some primitive specific checks so that we don't run into errors
sure
so now that is run on a unix command line e.g., ./make_my_sphere.sh
So I could do something like python3 script.py temp.g
create sphere 0 0 0 1 1 1 1000
create ellipsoid 0 0 0 10 0 0 0 10 0 0 0 10
exit
perfect, so we literally could do the same thing in python or shell
Uh-huh! yup
put it into a text file and the shell environment invokes the appropriate interpreter and the script is run
now instead of putting it into a file, we want to store that procedure in a .g file
Ok. How do we do that?
not only store it there, we want to be able to run it as needed too
a .g file is simple key=value database where the key is an object name and the value is the object's data
But the script is working to save the text file into a .g file right
Not literally the text file as is, but what the textfile wants to create as a .g file
This .g can then be loaded whenever it needs to be used?
consider when you make a sphere, it creates an object with that name and stores it's parameters into the .g file
Ah ok! But the .g file is not human readable
you did that with the "in" command to "input" the object
in my_sphere sph 0 0 0 0 0 1 1000
something close to that
sph is the object type
everything that follows are parameters
alright
imagine being able to do something that puts a script into the .g, like
in my_script script my_file.py
Our python script could then create tcl file after taking in the user input. Send it to mged which creates a .g file
and then being able to "draw my_script" to see its wireframe, or "comb something u my_script - foo"
forget about Tcl, there is no Tcl ... in fact, there isn't even necessarily an mged
So "in" and "draw" are bash commands that we define? What does my_file.py do then?
no, sorry -- in and draw are GED commands
that's where getting through the rest of the tutorials would be helpful ;)
Ah okay!
my_file.py didn't do anything in that example, it just contained a script (e.g., our one-liner) that was read into the my_script object
so anytime I do something with the my_script object, it runs the script and uses the geometry that results
and the "script" keyword is defined or it needs to be defined?
would need to be defined
that's the "procedural object" bits mentioned in the TODO
that keyword to the "in" command is the object type
Ah! Alright! So the script command would tell the in command what's coming in
Cool cool
*script keyword
*object type ;)
Ugh! My bad :P
it is a keyword obviously, but it directly refers to a registered object type
Again, this would not be python right? I'd have to work in C to manipulate the ged commands?
what is "this"?
Introducing "script"
we're talking about a lot of things...
ah, right so that bit would be core infrastructure code that someone else would probably write -- I could probably implement the basic necessary bits in a couple days
if you want to see what it looks like, look in the src/librt/primitives directory in a brlcad source checkout
Sure thing, I'll have a look at that
the table.c file is where all object types are registered and each implementation lives in the corresponding src/librt/primitives/OBJ subdir
so the idea is that there would be a new "script" object type that would hold the actual script (instead of it being in a text file)
and there'd be an embedded interpreter to run the script
So this script would parse a text object at run time and use the appropriate interpreter to create valid shapes?
almost got it
LIBRT would parse a script object at run time and use the appropriate interpreter to create geometry
But the script object can only exist if it is fed in valued from an external textfile?
LIBRT is the main library in BRL-CAD that is used by essentially everything
not necessarily
imagine creating a script in mged or archer, and when you run "edit myscript", it simply pops open a text editor
not reading from an external text file, but from the object
Ohhhhhhh!
It's almost like reverse engineering objects and converting them into plain-text descriptions
_or I got this completely wrong_
A script in mged would be?
what do you mean?
the mged script could be either a bash one or something for the python interpreter
Also, is edit a ged command?
yes, edit is a ged command
I feel like we're still missing something... :)
I think going through the tutorial is going to fairly help
yes, probably
and then maybe going through an example without shell or python mixed in
How about this? I'll go through the tutorial and then go through our conversation again and maybe come up with a possible interaction-diagram of the different components and we can modify that to get a clearer picture?
sure, sounds like a good start
I don't intend you to get too caught up on the C/C++ side of things in LIBRT since that's outside of scope for your project
As far as I understand, there are multiple parts involved in being able to execute
in my_sphere sph 0 0 0 0 0 1 1000
it just influences what will work best architecturally
Sounds fair, but I don't mind playing around there as well (though I might take a while to figure things out)
Uh-huh
what it implies is that you have C/C++ code running an embedded python interpreter
that logic is running from inside of "mged" and/or other command-line tools (e.g., "rt", "archer", "gqa", ...)
what we're wanting to end up with with procedural objects is not just the ability to source scripts, but create complex geometry like the SGI cube shell script
notice in that shell script how the cube dimensions are hard-coded
Yea
radius=100 for example
We'd want that to be interactive?
say I change the script, remove 100 and specify $1 instead (argv[1] or sys.argv[1] in python terms)
Yea
so instead of ./sgi.sh ... I'd run ./sgi.sh 100 and get a 100 radius shape
or ./sgi.sh 10000 and it's bigger
True true
as a procedural object, we'd want similar flexibility
maybe something like: in mysgi script sgi.py 1000
or, in mysgi script sgi.py
In the second case sgi.py could have some hardcoded values inside of it (or maybe fall back to some pre-defined value)
followed by some command that specifies parameters like "in mysql1000 exec mysgi 1000"
that way, you could stash the script and evaluate different parameters without making copies of the script each time
So, if you don't specify the "1000" here, would that raise an error?
would probably depend on the script
maybe it has a default, maybe it requires 3 parameters
Sure
So, exec here, that would need to be defined too or is it already defined?
Also, my initial tasks would be wrapping the primitives and then getting the python interpreter to work?
would need to be defined -- that's why this concept is in the TODO file
it's a somewhat advanced CAD feature, very powerful
but not terribly hard to implement
have you ever played with openscad?
Nope, never have :/
I'll brb! _AFK_
ah, well might still be helpful example -- openscad is a geometry system that essentially uses procedures everywhere
if you check out https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/User-Defined_Functions_and_Modules and jump down to "Example 2", you'll see something very similar to what we were talking about
Example two is just like python's range function
Wait, sorry example 2 in modules?
yes, sorry -- example two under the Object modules section -- little houses
module house
another consideration to test is performance .. how long it takes with the two python methods to create XXXX objects
Ah, I get the picture
alright, times up for me -- good talk
Thanks a ton for everything! I've definitely got a lot to think about and discover :)
I'll come back to you with a design for the procedural geometry in a couple of days?
give the tutorials a go, revisit the discussion, check out TODO, talk some more with the other mentors too, test performance
sounds good
Awesome! Thanks
Hey @Sean, @Shubham Rathore! I'm travelling home and will be AFK for the next two days (until 12/10/18), I'll resume work on the 13th and will make up for lost time then! :)
Hey @Jaipal Singh with the coding period about to start, I hope you are ready with a plan for the deliverables. I think Sean cleared most of your doubts, still if you are stuck with anything, feel free to ask. Wish you a happy coding period. Cheers !
Hey @Shubham Rathore! Yea the conversation did clear out a ton of things (also introduced a ton of doubts). I'm working on completing the mged tutorial series, should be done by tonight.
The first immediate goal is start wrapping up relevant primitives while designing the procedural geometry architecture parallely. I'll be furthering nmz's implementations and will keep you posted with my daily updates on the dev log. Cheers! :D
When working with arb4-arb8, are there any restrictions on the how the points are placed in a 3d space? From https://brlcad.org/wiki/BRL-CAD_Primitives, I gather that it's fine for points to overlap when working with arb8 (not be unique), are there any other such restrictions or constraints?
arb4-arb7 should have 4-7 unique vertices respectively
Not actually, its just the overlap of the points that make the difference.
Ah. Figured that :)
Went through your dev logs. The primitives look good. they run fine on my system. It'll be good if you document the export instructions for the mged as well. Will save users from some compile time errors ;)
Hey @Sean, @Shubham Rathore! I'm travelling home and will be AFK for the next two days (until 12/10/18), I'll resume work on the 13th and will make up for lost time then! :)
@Jaipal Singh thanks for letting people know
When working with arb4-arb8, are there any restrictions on the how the points are placed in a 3d space? From https://brlcad.org/wiki/BRL-CAD_Primitives, I gather that it's fine for points to overlap when working with arb8 (not be unique), are there any other such restrictions or constraints?
yes there are restrictions but I don't recall exactly what they are -- probably best to refer to the source code
Thanks @Shubham Rathore :) I'll get the documentation in place
@Sean , yea that's what I've been doing and it seems good so far!
@Jaipal Singh we need to talk some more about how this will all get leveraged, especially to @Shubham Rathore's earlier point about what is needed to get script objects to work in librt
I'm concerned that continuing down the "in" command route will be problematic because it relies on mged
mged will not necessarily be available within a librt context (because mged depends on librt, so it would create a cyclic dependency) -- even libged has that problem in a way, so there are considerations to be made...
@Sean sure. Is there some documentation where I can read about librt / libged and how they work with mged? That'll help me get a clearer idea of the problems we might have.
Also, I'm posting daily updates to the dev logs here : https://brlcad.org/wiki/User:Schindler97/GSoC18/Log :)
not much in the way of architecture docs other than the source code that you have in front of you, the doxygen API docs, and README files scattered throughout (read those....) , that's why I said we should talk more
a brl-cad .g file is a "geometry database" filled with named objects. those objects are of a particular registered type. we want to get to a point where we have a "script" type that can be Python.
all the logic for reading/writing objects will eventually be in a low-level "libg" library, but right now they live in librt (see src/librt/primitives/table.c to see where they are registered and each subdir for their implementation)
you can see librt's current dependencies in its build file (src/librt/CMakeLists.txt), but essentially it just depends on libbu/libbn/libbg and the libraries the primitives themselves require (e.g., libnmg, libbrep, opennurbs)
mged is an application that sits on top of libged for all its commands, and libged sits on top of all the other libraries (e.g., librt)
so the question / problem is how to make a script primitive that will eventually belong in libg/librt that doesn't depend on mged/libged, but has access to everything in libged...
at least not a strict linkage dependency -- the solution probably lies in dynamic runtime loading, or a different runtime object implementation that is somehow loaded by a calling context
@Sean , can I have time till Sunday to go through all this, think the architecture through and then have a conversation with you about how we would proceed?
so the question / problem is how to make a script primitive that will eventually belong in libg/librt that doesn't depend on mged/libged, but has access to everything in libged...
But, we want to use the in command and that is a ged command. How would we do away with that?
Also, I went through our conversation from earlier this week and it makes more sense (I think I understand the problem better now)
a brl-cad .g file is a "geometry database" filled with named objects. those objects are of a particular registered type. we want to get to a point where we have a "script" type that can be Python.
This python script would then be parsed by an embedded interpreter? Which would be called from within the C/C++ code?
all the logic for reading/writing objects will eventually be in a low-level "libg" library, but right now they live in librt (see src/librt/primitives/table.c to see where they are registered and each subdir for their implementation)
Yes, I'm going through the individual primitives, I did that before/during the community bonding period as well. I'm not able to figure out though how to see "where primitives are registered"
i think he's talking about struct rt_functab OBJ
in table.c, regarding where primitives are registered
Ah ok!
at least not a strict linkage dependency -- the solution probably lies in dynamic runtime loading, or a different runtime object implementation that is somehow loaded by a calling context
So the "script" would be a primitive defined in librt.
It would parse a python script (myscript.py) which would consist on instructions on how to make complicated objects at runtime.
The "script" code in librt would invoke a python interpreter to understand the input script.
Current Approach : nmz uses his code to create a .tcl -> .g (using mged)
Our Goal? : use the instructions from myscript.py to create a .g file by working with the primitive definitions internally.
libged seems to have the source code for the commands used by mged, but I can't find anything for the 'in' command. I'm looking for an 'in.c', because for commands like 'ls', there exists an 'ls.c' and I was assuming it would be the same for 'in' as well. (sorry if these doubts come across as extremely trivial)
it's in libged/typein.c
Thanks a ton @Cezar :D
@Cezar , how do you look this up? Did you explore through the file listing or is there somewhere you would look this up?
mm... i figured the command strings must be somewhere, so i ran grep -R "\"ls\"" .
in the mged
folder, and there was an array of objects which contain command strings and their associated functions. so then i ran the search for "in"
, and it looked like its function was ged_in
. so next i went into libged
and ran grep -R "^ged_in(" .
, and it was found in typein.c
with the last grep there, if you're wondering, i searched for ged_in(
at the beginning of a line because that's the coding style brl-cad uses for function definitions
Aye, great
This python script would then be parsed by an embedded interpreter? Which would be called from within the C/C++ code?
Yes, you got it!
libged seems to have the source code for the commands used by mged, but I can't find anything for the 'in' command. I'm looking for an 'in.c', because for commands like 'ls', there exists an 'ls.c' and I was assuming it would be the same for 'in' as well. (sorry if these doubts come across as extremely trivial)
The 'in' command is in the src/libged/typein.c file
with the last grep there, if you're wondering, i searched for
ged_in(
at the beginning of a line because that's the coding style brl-cad uses for function definitions
And that is an outstanding explanation for how to find mged command guts in general!
src/mged/setup.c contains the dictionary which translates the Tcl command strings to C functions for mged.
libged/typein.c is the place ! There holds a structure for a primitive that contains the list of input strings to asked from the user during the runtime. Later you may find functions to load the input to the database.
@Daniel Rossberg , to create a .g file, is it necessary to have mged to be a part of the pipeline?
not sure, but i don't think so. there are librt functions (see include/rt/db_io.h
, for example) which read/write .g files
It depends on where you are. If you can link with the BRL-CAD core libraries e.g. db_open(fileName, "rw")
opens a .g file for writing.
And if this doesn't work db_create(fileName, 5)
creates a .g database.
Ah okay!
I just want to understand better how to complete this work flow :
tcl -> .g . src/mged/setup.c (converts tcl to c commands) -> ??? -> include/rt/db_io.h -> .g
I have a feeling that I've abstracted a lot of what might go on in the middle.
src/conv seems to have the relevant scripts to carry out conversions from *format-> .g
asc2g.c makes a GED database from an ASCII GED data file.
On page 34 : https://brlcad.org/w/images/5/5f/Geometry_Conversions.pdf
From what I understand, tt says that asc2g.c can be used to convert a TCL script to a .g file
The mged command to create a new database is opendb
, which calls the f_opendb()
function defined in src/mged/mged.c.
asc2g.c makes a GED database from an ASCII GED data file.
On page 34 : https://brlcad.org/w/images/5/5f/Geometry_Conversions.pdf
From what I understand, tt says that asc2g.c can be used to convert a TCL script to a .g file
Page 34 says something about Pro/Engineer.
In addition, the TCL dialect of asc2g isn't the one used in mged. You can however use mged as a TCL script converter as well. See the mged manual page for instructions .
Sure! Thanks
@Daniel Rossberg , we want to convert tcl to .g without getting mged into the pipeline.
so the question / problem is how to make a script primitive that will eventually belong in libg/librt that doesn't depend on mged/libged, but has access to everything in libged...
@Sean had recommended this and hence we were thinking of alternate possible ways
@Jaipal Singh asc2g embeds a tcl interpreter that has just an essential set of commands registered
Think I see 3 options...1 call librt/libwdb api , 2 dynamically load libged , 3 create new libg library and call that
Dynamically load libged?
Working with libged gives us abstraction over librt and libwdb right?
Also, @Sean , @Shubham Rathore , I'm done wrapping most of the primitives and have pushed them with some example for you to try out each of them, let me know what you think and where I should head to next.
I'm going through librt and libged to get a coarse understanding of how things are dealt with by them.
@Shubham Rathore , I'm starting off on documenting the python brlcad on how parts of the code work and how complicated shapes can be drawn. Do you have any particular suggestions that I should keep in mind? :D
Also, I could only work for a couple of hours yesterday, I have a research paper deadline coming up on the first of June and ended up spending a lot of time with it. I'll make up by working extra hours today and tomorrow :)
Documentation is indeed required but that is something you should do after the primary tasks are over. Currently the main focus is to convert tcl to geometry files bypassing mged. I was traveling in the past days so couldn't be much active. But we need to figure this out soon.
In the Hacking-BRL-CAD.pdf, there's a section on procedural geometry, which states that : "BRL-CAD provides a comprehensive procedural geometry interface as a means for creating models algorithmically instead of manually". What exactly is this referring to?
@Shubham Rathore , I'd agree that's the major priority for the project as of now. I'm a little in the dark here about what could be done to bypass mged and hence thought I could use this time for documenting the project and continue working on the code once I have a clearer picture :)
Hey @Shubham Rathore , @Sean Should I start working on the script primitive? So far, I've not been able to figure out a way to get procedural geometry to work without using libged. Would you have any leads in that direction?
@Jaipal Singh the hacking book is referring to the LIBWDB api.
That’s one of the binding options I mentioned last week. We could see what all if anything is missing for what you need.
Start there and check out some of the C examples in src/proc-db and src/shapes .. I suspect binding wdb.h is super easy
@Sean On it!
Hey @Jaipal Singh Can I get some leads on the current work. Did you go through the libwdb ?
@Sean On it!
how did that go? be sure to update your log please
Hey @Shubham Rathore , @Sean , I was caught up with the conference deadline up until yesterday. :/
I've resumed work on the project from today. Will share updates regularly and make up for lost time ASAP.
@Jaipal Singh what conference? I don’t see mention of that in your plans. Totally supportive but you need to tell us things like that in advance if they are going to have any impact on your work..I have to imagine more time if you’re accepted?
Hey @Sean , yea, it was careless on my part to not inform you of this a little earlier. This is the conference : http://www.conll.org/
Nope, nothing until the GSoC period ends as any further work related to the conference will not only happen in late August
The submission here was a part of my masters thesis at university and now I'm officially done with all work for the summer so I can focus purely on GSoC
Also, I didn't know I was going to submit a paper to this conference while I was applying for GSoC, hence hadn't included it in the schedule.
But you can be rest assured that I'll finish up everything in time!
Well that’s good you can focus now, because looking at your plan schedule, we’re way off track...things still being figured out. There needs to be more coding going on by this point.
I've been through libwdb and it seems to be the right thing to handle our problem. It has functions for writing all the primitives. Also went through some of the examples in proc-db and src/shapes and getting a hang of how the shapes are being drawn. I plan to go through all of them to have a clearer idea about how libwdb functions
Yea, I'm sorry for that @Sean :/
You didn’t know when applying, but you certainly knew after and should have mentioned it once you knew, could have mentioned it in your plan.
Yea, my bad absolutely!
So what is the next steps coding?
So, first off would be introducing the script primitive in librt to read and parse the scripts
Before that I'd have to define the syntax for the scripts
But what I'm confused about is with libwdb in place now, what's the need for a python interpreter?
Also, how does one interact with the libwdb api? How/where to run src/shapes/bolt
How/where to run src/shapes/bolt
Got this.
But what I'm confused about is with libwdb in place now, what's the need for a python interpreter?
The current python interpreter creates .tcl scripts and then interacts with mged to create .g scripts.
But now that we're using the libwdb API, there's no need for an interim .tcl file.
Though we could have a templating engine written in python to create files similar to some in proc-db
@Sean , @Shubham Rathore , is there a guide/tutorial of sorts for introducing new primitives?
The existing primitives should serve as a reference.
Check out files in librt primarily. An extensive search using the defined primitives would tell you the relevant files to be modified.
Alright @Shubham Rathore
Also, I've updated the dev log.
I'll go through it. Let me know if you get stuck while defining the primitive.
Sure thing! I'm exploring librt to figure out the right things needed to start.
@Sean Do you think introducing a new primitive is going to be a redundant task? We could work with the 'in' command. Personally I think primitives would be great if we were creating something new, but that's not the case here.
@Jaipal Singh redundant how? There is currently no way to have geometry define itself — this would provide that capability.
You could even use this to have completely user-defined geometry.
Instead of the predefined set we support.
@Jaipal Singh redundant how? There is currently no way to have geometry define itself — this would provide that capability.
What do you mean by "the geometry define itself"?
Why I think it's redundant is because the in command already has the ability to create primitives with parameters given to it real time. Hence a parametric approach to buildings things. We could convert this into a procedural approach by modifying it to understand scripts (procedures) and use the currently present architecture to draw the shapes.
Instead of the predefined set we support.
What exactly are you referring to here?
I too didn't understand what redundancy here means . Are you trying to direct towards using some inheritance for the functionalities? If so, then it won't be possible and is again a big project to handle. I think there's a bit of confusion erupting here. Will you please clarify a bit?
So, the redundancy I'm talking about is with regarding the to what the 'in command' already offers.
If a new script primitive is introduced it's job will be to parse the scripts (SC from now) and draw shapes as defined in them. A script usually would define how to create a certain shape using the primitives defined in librt. To create this shape (combination of primitives) we will use the libwdb api. Hence when creating the script primitive we would have to write code to interact with libwdb for each primitive.
Now consider the 'in command'. It currently takes single primitives and arguments to draw them. It already has to code to construct all primitives. What I was recommending is we use these functions. A new script primitive could be introduced to work with the 'in command'. It would parse the SC and construct the primitives one by one and create the bigger shape. This was we can reduce our problem to adding a functionality to the 'in command' to create multiple primitives given a SC. We wouldn't have to write interactions with the libwdb API as there already exists in typein.c code to create these primitives.
Think I see 3 options...1 call librt/libwdb api , 2 dynamically load libged , 3 create new libg library and call that
Last week @Sean had mentioned that we could use the librt or libwdb api for constructing the primitives. Typein.c uses the librt approach to construct primitives already. I'm suggesting we leverage this existing functionality and add to it.
Also, I'm completely down for creating a new primitive but just want your insights on what you think about this idea!
@Sean @Shubham Rathore What do you think?
What do you mean by "the geometry define itself"?
A main purpose for script objects is having user-defined parametric geometry (e.g., "make a person, male, 6' tall"). They define a shape but are an object, thus they define themselves. All primitives technically do this, so the distinction is really that they define an arbitrary/unknown shape.
A script usually would define how to create a certain shape using the primitives defined in librt. To create this shape (combination of primitives) we will use the libwdb api. Hence when creating the script primitive we would have to write code to interact with libwdb for each primitive.
This is all good observations. Also realize that several of the primitives are quite flexible/arbitrary (e.g., bot and brep) and will even permit hooking into 3rd party applications. Like imagine a script that reads a Blender file on the fly.
Now consider the 'in command'. It currently takes single primitives and arguments to draw them. It already has to code to construct all primitives. What I was recommending is we use these functions. A new script primitive could be introduced to work with the 'in command'. It would parse the SC and construct the primitives one by one and create the bigger shape. This was we can reduce our problem to adding a functionality to the 'in command' to create multiple primitives given a SC. We wouldn't have to write interactions with the libwdb API as there already exists in typein.c code to create these primitives.
I'm not following. You recommend we use those functions ... but there aren't functions -- there's just one, ged_typein() and binding to ged is a problem. If I'm understanding you correctly, the issue I think is that you see object creation code in typein.c that you want to use -- and you are absolutely right that it should be reusable (and currently is not). I'm not seeing how you could possibly have a script get parsed within libged's 'in' command, so were you thinking to move that logic to librt/libwdb as functions?
My bad, I meant "use this functionality" and not "these functions".
binding to ged is a problem
What does that mean? Is it a problem in general or will it be a problem for me to write code to bind with ged?
how you could possibly have a script get parsed within libged's 'in' command
Yes, I had two ideas. One of them as you mentioned was to move the logic to librt/libwdb as functions. The second was to embed the logic in typein.c (of course this approach is extremely non-modular but serves as a hack). I think including the logic in libwdb is going to be a good choice.
@Sean, is it fair to assume all work from now on will be in C and not python? The script parse can just be written in C
What does that mean? Is it a problem in general or will it be a problem for me to write code to bind with ged?
It's an architectural problem. libged depends on librt, so you can't introduce code into librt that depends on libged or you create a cyclic dependency. that was the whole discussion a week or so ago when we talked about what the options were (architecturally). however, you note a solution ...
Yes, I had two ideas. One of them as you mentioned was to move the logic to librt/libwdb as functions. The second was to embed the logic in typein.c (of course this approach is extremely non-modular but serves as a hack). I think including the logic in libwdb is going to be a good choice.
Moving the logic to librt/libwdb would work and avoids the cycle. The typein hack won't be adequate for a variety of reasons.
So if you move the typein logic to librt/libwdb, what are your thoughts on having multiple functions for creating objects (essentially different constructors)?
Yes, have multiple constructors (functions) and an array of constructors would be called to create the primitives sequentially as mentioned in the script.
There's still some doubts that I have. Libwdb has functionality to draw the primitives (the mk_primitive() functions). An example where I've seen these being to draw objects are in files like proc-db/wdb_example.c .
The doubt is, at run time, our script logic (present in libwdb) would then invoke these mk_primitive() functions. Will these be rendered in mged in real-time?
Also, where and how does python do you think can help us in this project now? The python-BRLCAD that I had worked on in the first two weeks is completely independent of what we're planning to do now. I personally feel that we can just continue with C.
I also want to re-frame my plan for the next two months given the new tasks at hand and include hence asking all these questions before I get started coding.
I've also been looking for the code responsible for uploading files using mged, but I can't find any. Though the problem could be tackled in two ways, we can maybe not upload the file but read it at run time. That raises the problem of passing the absolute or relative path that we would have to then tackle.
Yes, have multiple constructors (functions) and an array of constructors would be called to create the primitives sequentially as mentioned in the script.
I'm not understanding this... you'd only need to call one constructor per statement
what's sequential?
Yea, it would be a constructor per statement. Sequentially, as in, calling the constructors in the same order as mentioned in the script.
I'm thinking the immediate task for me right now is to figure out the file upload or file-read part. I'll try and find the code mged uses for uploading files and revert back to you.
So I was referring to different constructors for the same entity, like specifying a sphere with a "point and a radius" or a "point and a direction vector" or "point and three orthogonal vectors" ... all three make a sphere but the orientation is technically different for each
s/technically/potentially/
I'm thinking the immediate task for me right now is to figure out the file upload or file-read part. I'll try and find the code mged uses for uploading files and revert back to you.
to be honest, this feels like a distraction as it's not coding and you've gone several weeks without coding now, no?
you really need to be submitting code daily by this point, something even if it's not perfect and you're learning as you go
you'll learn more and we'll have more to talk about.
you mentioned a while back that there were two python wrappers you'd looked at -- one that used mged directly and another. can you explain what exactly the other one was?
The doubt is, at run time, our script logic (present in libwdb) would then invoke these mk_primitive() functions. Will these be rendered in mged in real-time?
as an object, absolutely yes -- one of the functions that every primitive defines is how to draw itself. for a script object like this, it will just tell it to draw the geometry it created.
Also, where and how does python do you think can help us in this project now? The python-BRLCAD that I had worked on in the first two weeks is completely independent of what we're planning to do now. I personally feel that we can just continue with C.
my thinking is that the basic object structure would get stubbed in a day or two (I could probably do it today) and you'd spend most of your time defining the C-to-Python binding and then all your remaining time on the Python side creating a more seamless full API
in essence, do whatever you need to do on the python side so that you can do what wdb_example is doing from python -- which may be already done if the non-mged approach (ctypesgen?) was complete enough
you really need to be submitting code daily by this point, something even if it's not perfect and you're learning as you go
Starting today, I shall do this.
in essence, do whatever you need to do on the python side so that you can do what wdb_example is doing from python -- which may be already done if the non-mged approach (ctypesgen?) was complete enough
I think the ctypesgen approach followed the mged-approach and was complete enough. It though was designed to work with brlcad-7.24.0 and raises a lot of errors due to some changed header files when working with the latest version. I'll fix these and push changes right away.
try the latest version from github first. i had submitted a pull request that fixed those errors and was merged. if it works, you don't have to fix those problems yourself
Yea, just saw the patch you had submitted. It should fix the issues. :)
@Cezar , seems to be working, though there's still error logs about stdio.h, plo3.h and nmg.h. I tried a fix similar to yours and tried to include the header files in include/bn but that doesn't seem to fix it.
what/where are those error logs? :-?
if it's during building, i think it's fine
i think i do remember some problems there, but i think i wrote them off for some reason
Yea, it's during building. Guess it shouldn't be an issue.
https://pastebin.com/YPpP2LkJ
i think it's because during preprocessing, some headers are not included in other headers. so for example, nmg.h uses FILE but does not include stdio.h, so when looking at the header, ctypesgen (?) thinks it's an error. but nmg.c might #include <stdio.h> #include "nmg.h"
, and when nmg.c is compiled, no problem arises
Uh-huh makes sense. I guess this should never be an issue at run-time then.
my thinking is that the basic object structure would get stubbed in a day or two
@Sean , I didn't get this
i think it's because during preprocessing, some headers are not included in other headers. so for example, nmg.h uses FILE but does not include stdio.h, so when looking at the header, ctypesgen (?) thinks it's an error. but nmg.c might
#include <stdio.h> #include "nmg.h"
, and when nmg.c is compiled, no problem arises
That might actually be a good testing framework for making sure headers are appropriate encapsulated... or it's missing some critical defines (quite likely) as I believe stdio.h is included by everything via common.h
That might actually be a good testing framework for making sure headers are appropriate encapsulated... or it's missing some critical defines (quite likely) as I believe stdio.h is included by everything via common.h
hmm... i was thinking of rob pike's notes on programming in c (here), where he says that including header files in header files slows down compilation
looking at a few of them, it's not clear if this is a false positive or not -- some of them clearly don't include stdio.h directly, but at least one does indirectly and it still reported
it can slow down compilation, especially for big complicated headers where you only need a type or something simple
that said, performance-wise, it's pretty much an insignificant blip on development unless people pathologically include too many headers needlessly
headers should be self contained, including and declaring what they need so that header stands on it's own. otherwise, you're just trading a tiny fraction of development cpu time with human time (which is FAR FAR FAR more expensive), especially when they fail to include a required header and spend an hour or three debugging
Yea, it's during building. Guess it shouldn't be an issue.
https://pastebin.com/YPpP2LkJ
@Jaipal Singh I just committed a bunch of header additions that should take care of them (r71053). would you try again and report back?
@Sean , the build fails due to some missing header files : https://pastebin.com/YyhhdYMG
The weird part is when I run make -j 3, I get the error that I shared above,
When I just run make on one core, it gives a different error https://pastebin.com/Q9uX0h26
I'll pull the stable version from the trunk and introduce the changes (r71053) and see if that works
huh, that's interesting -- @Jaipal Singh you apparently have a system-installed poly2tri that is different than the one BRL-CAD is using. since it's installed in /usr/local, that takes precedence over ours in src/other/poly2tri ... and your system one looks misconfigured or has a bug.
couple workarounds possible -- easiest being: sudo mv /usr/local/include/poly2tri /usr/local/include/poly2tri.backup
alternatively, commenting out the block in the top-level CMakelLists.txt that adds /usr/local (around "# We want to check /usr/local by default, so add it if it exists")
the difference with one core is just in how the dependencies are resolved and what order they are compiled. doesn't mean anything other than possibly another issue that we'll see later with the -j3 build when it gets to that point.
pulling the stable from trunk won't likely fix the poly2tri issue because it's an issue on your system
pulling the stable from trunk won't likely fix the poly2tri issue because it's an issue on your system
Yes, moving it out to poly2tri,backup seems to have solved the issue for now
my thinking is that the basic object structure would get stubbed in a day or two
@Sean Some clarity on this?
the whole script object portion is not dependent upon what you need to sort out with ctypesgen and/or librt and/or libwdb and/or moving code from libged/typein.c
but if we want scripting objects, they obviously need to exist
well that work is really dead simple .. I can probably do it in a day if/when needed, at least the most important bits. you could probably do it in just a few days at most (but don't have to, would rather you focus closer to the python-specific needs)
Alright!
So, the build fails again : https://pastebin.com/8rb6q2iX
would you switch to https://pastebin.ca or the debian pastebin or literally anything other than pastebin.com ... they're a really obnoxious site often with maliciousness going on
and inaccessible to some devs (blocked for those same reasons)
Sure, didn't know that
so that lempar issue is really odd
what version of cmake and make are you using?
3.10.3
3.11.3 is the latest
hrm, so then I think full logs are in order on a clean build
yes, that version is fine
anything 3.3+ should be fine
Ok..
oh you know what, I bet it's a similar issue
you probably have an old system lemon installed somewhere
A prior messed up installation?
no, not likely
what's your cmake line?
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
ok
so run: rm -rf CMake*
Done and now cmake again?
then: cmake .. -DCMAKE_INSTALL_PREFIX=/opt/brlcad -DBRLCAD_BUNDLED_LIBS=ON
recommend against installing into /usr/local or other common system dir until you get more experienced
there are a variety of issues that can come up, naming conflicts
the important part is bundled libs
Yea, what does it do?
BRL-CAD uses about 2 dozen external libraries and tools like libpng, libz, tcl/tk, etc
Also, should I go ahead and make it now?
we bundle them so everything will build out of the box whether you have them installed or not, whether you have rpm/dpkg/homebrew/apt/whatever package manager
and this makes things much simpler on platforms like Windows that have nothing
Alright, so they're pre-compiled binaries?
but it is just for convenience ... you can download all 20+ dependencies yourself, compile/install them, use rpms/apt/whatever
not pre-compiled, we still compile them as needed
but it is just for convenience ... you can download all 20+ dependencies yourself, compile/install them, use rpms/apt/whatever
True, but there's a fair chance for something messing up here.
so by default, we test and see if you have a given external dep, like 'tcl/tk' and ... 'lemon' and if it finds it, we don't build ours -- we assume the system one we found is good to use
Uh-huh
But then what about version compatibility? How often do you have to update the bundled libs?
that varies from dependency to dependency, but where it matters we typically test and only use a system one if it's a version we require (or newer)
Cool
the bundled libs are updated as we need / want / care to .. those are the ones that typically always work because we made sure they work
so when you compile, the default is "Auto" where it'll detect what you have and use it if it seems to be version-compatible
the other modes are Bundled == Off and Bundled == On which tell cmake to either ONLY use system dependency libs or NEVER use system dependency libs
Does it fall back to using bundled libs if system dependencies are missing?
for Auto, sure, it has to -- that's the whole point
for Bundled, it doesn't care what you have on the system, it's not going to use it
Alright
Sean, could you help me chalk out how I should progress with the project now. The current python BRLCAD uses ctypesgen that allows us to interact with the libwdb api from python.
to be pedantically accurate, the cmake variable is BRLCAD_BUNDLED_LIBS=AUTO or =SYSTEM or =BUNDLED (which is same as =ON)
Ok yea.
so it does use libwdb?
that much wasn't clear/known
who were the main authors of the two different versions ... there was nmz, pedro, and .... ?
I've been going through the code figured most of it out yesterday (there's still some parts that throw me off)
kanzure
and who did which?
nmz was in favour of the mged approach, the one I worked on in the first two weeks of the project. That's currently loaded with functionality to create all the primitives.
kanzure worked on the ctypesgen project. I was in touch with him before the coding period began to get some help in choosing which project to continue with, the ctypesgen one or the mged one.
okay, so where does that code seem to stand?
Which one are you referring to?
you said the mged-based one was loaded with functionality to create (nearly) all the primitives ... so where's the ctypesgen one at?
The ctypesgen one is missing on a few primitives. Once those are in place it should be at part with the mged one
how does the python API compare between the two, how many primitives are hooked up?
The mged approach technically does not use any API, it makes a system call using to mged and generates the.g file
The ctypesgen approach usues ctypes to interact with the libwdb api and create the .g files
do you think you could easily show what the equivalent to wdb_example looks like in each (mged and ctypesgen versions)? how long might that take you?
I could give it to you in a couple of hours from now?
I think for the ctypesgen version, there's already an wdb_example equivalent, 1 second
that would be great to see
https://github.com/kanzure/python-brlcad/blob/master/examples/wdb_example.py
so yeah, then see what that looks like with the other one would be great for comparison
lots of little choices being made there -- method on a class, sets of global classes, using intrinsic types or not, etc
I still have to figure out how to execute operations like "union" or "intersection" via the mged approach. I'll get those sorted and revert back to you with an equivalent script for the mged version?
Yea!
sure .. it's succinct enough that I can't imagine it'll take too long
Yes! I have to quickly run some errands outside (sunday chores) and I'll be back and update you with the script? Won't be very long for sure!
then to answer your question, I think the next step will be to simply add a primitive to the wdb one that seems missing, just to get familiar with the process and code, then create a spreadsheet to itemize what's there and what's missing, and then work on a second slightly more complex primitive (again for experience) while I get the script object set up, and then you test running an embedded python in C to run one of the scripts successfully, and then we pull it all together!
sounds good
@Jaipal Singh are you done with the installation errors? I suggest you to go through the "INSTALL" file. lines from 190 onwards, will clear the picture for the installation flags. As far as the ctypesgen approach is considered, that code is totally broke, with some dependency issues, import issues, version issues, platform issues etc. Basically the stuff is incomplete, and the progress sounds hazy , that was the reason to shift to the tcl approach. We should keep these things in mind before we think forward. Looking forward to a code snippet from you. Cheers !
@Sean , the errors still show up when setting python brlcad (ctypesgen) due to the header files even after including your patch
https://gist.github.com/Killthebug/99d5aa4d6254e1dce083c784fedd7c25
@Sean , here's the script for wdb_example using the tcl approach.
https://github.com/Killthebug/python-brlcad-tcl/blob/master/examples/wdb_example.py
@Sean , here's the list of primitives already incorporated into the ctypesgen code. https://docs.google.com/spreadsheets/d/1XeeI1mpLlPFZtc7i5GeOmjLFE-s8JMsYpwVszIPsrmQ/edit?usp=sharing
There's individual files for most of the primitives and the others are inherited from their parent class.
I've gone through all the primitives and am fairly familiar with the code. As for the complicated primitive, which one would you recommend?
Also, what would be a good time to get started on setting up the script object? I'd like to give it a shot myself but am a little in the dark about how I should go about doing it.
Hey, anything on this front?
I think you can include hrt primitive as well. Might be useful in procedural geometry.
And start working on the script primitive structure. That is something you can do in very less time. Just read the code containers for the other primitives, and move along the template. The basic primitive definition lies in librt. I suggest, start from here and ping for further clarifications. You need to start doing stuff, that will make things more clear. You need to work smartly here, as many fields may remain empty for this primitive. Please ensure the updation of your daily logs.
Later our task remains to incorporate the primitive container and the ctypes bindings, but before that the primitive needs to be well defined. librt is the place where you should focus initially. Pick up a primitive as a reference and follow accordingly. Cheers !
@Jaipal Singh any updates? Are you stuck on anything?
Hey! I've been working on the script parser! I'll finish that up by tomorrow, I have to add some more primitive functions. Will move onto the script primitive then.
You can have a look at the script parser here : https://github.com/Killthebug/python-brlcad/blob/master/examples/script.py
Some questions for you. Weren't we going the ctypes way? All I can figure out is tcl-> .g in this script. and how is mged being bypassed here?
Hey Shubham! This is is the ctypesgen approach.
First off, I've chosen tcl as the scripting language here because tcl is already used in the brlcad ecosystem and hence I don't have to introduce a new script BNF.
Secondly, this is the ctypegen approach. mged is being bypassed here.
We use ctyepgen to generate bindings for libwdb. We then use the libwdb API in python to create primitives.
Until now, you would have to write separate code if you wanted to make a shape comprising of multiple primitives, something like : https://github.com/Killthebug/python-brlcad/blob/master/examples/wdb_example.py
With the scripting option that I've not introduced, you can give it tcl scripts like : https://github.com/Killthebug/python-brlcad/blob/master/examples/temp.tcl to create the same objects.
The scripting option is not completely ready. It can make all the primitives for now but still lacks functionality to deal with variables, primitive rotation, etc. I'm working on these additions right now.
As a part of procedural geometry, we can also have loops in the script to create multiple instances of the same objects with different variations. Let me know what you think about that and I'll get started on it once this part is completed.
Great !
Looks good ! I'll be waiting for it to run this way.
And what about the script primitive? Have you started working on that ?
So, the script primitive will essentially be responsible for invoking the python script parser that I've shared above. It will be python embedded in C. Once I am done perfecting the parser, I'll start work on the script primitive. Sound good?
okay, make sure you update your logs ! I find a lag there. Cheers !
Yes, I'll keep them updated @Shubham Rathore :)
@Sean , here's a sample script which the script parser will work with to create the procedural geometry. https://paste.debian.net/1030745/
This is inspired from the sgicube.sh (https://brlcad.org/wiki/SGI_Cube)
As of now the script parser can work with variables and creating primitives. Right now, I'm working on introducing procedure parsing (function parsing) in to the script. Do you think the procedure structure in the sample script I've shared looks fine?
Also, could you have a look at the workflow of the script parser and certain assumptions regarding the scripts that would be parsed?
https://github.com/Killthebug/python-brlcad/commit/b2bb4eb9ba4c830e17c80743310af31fa544205a
@Sean , @Shubham Rathore Any inputs on this? ^
@Jaipal Singh Looks ok on the first view. have you tested it ?
Yup! I test each part before I commit it! :)
How do you exactly plan to introduce function parsing into the script ?
Though the procedure structure looks fine in the script
Regarding the workflow, we'll have to see its feasibility at the run time . Fine for now ! Please try to complete this before your second evals. The only part left after the second eval should be the script primitive. I have a basic frame ready for it, so that shouldn't take much time. Plus linking different parts of the pipeline will comprise of many errors, we need time for that too. I hope you'll follow
I am creating a parser that will work with the tcl scripts based on the procedure structure that i've shared with you. It's somewhat like designing a compiler (not as complicated) where I'll be calculating values of local variables based on arguments passed and global variables available, every time a procedure is called.
I've gone through all the primitives and am fairly familiar with the code. As for the complicated primitive, which one would you recommend?
bot would probably be best to start with since it's somewhat more complicated than the other primitives, but a concern -- can we make changes on the C/C++ side so that there doesn't need to be primitive-specific bindings on the Python side?
Also, what would be a good time to get started on setting up the script object? I'd like to give it a shot myself but am a little in the dark about how I should go about doing it.
If you'd like to give it a shot, start with src/librt/primitives/table.cpp -- notice how it's a bunch of ID's and functions. look at one of the newest IDs at the bottom, like ID_DATUM, and then find all references to it throughout the source tree (grep -r ID_DATUM include src). I can certainly help you with this and/or implement it for you, but glad to give you a shot if you want to try.
bot would probably be best to start with since it's somewhat more complicated than the other primitives, but a concern -- can we make changes on the C/C++ side so that there doesn't need to be primitive-specific bindings on the Python side?
Yea, we can make changes on the C/C++ side without impacting the bindings on the python side.
If you'd like to give it a shot, start with src/librt/primitives/table.cpp -- notice how it's a bunch of ID's and functions. look at one of the newest IDs at the bottom, like ID_DATUM, and then find all references to it throughout the source tree (grep -r ID_DATUM include src). I can certainly help you with this and/or implement it for you, but glad to give you a shot if you want to try.
I'll be moving on to do this once I've completed the script parser that I'm writing. It'll be done by the second eval. Just yesterday I completed an syntax parser which can parse mathematical expressions in procedural scripts :D (Got to be one of the most exciting things I've learnt and built so far)
Procedural scripts have expressions like : [exp{2+4{$i+$j/$old}*22}]. I created a syntax parser to parse such expressions.
As of now the script parser can work with variables and creating primitives. Right now, I'm working on introducing procedure parsing (function parsing) in to the script. Do you think the procedure structure in the sample script I've shared looks fine?
@Jaipal Singh I may have missed a major detail here ... it should just read Python code -- what's the custom parsing??
I am creating a parser that will work with the tcl scripts based on the procedure structure that i've shared with you. It's somewhat like designing a compiler (not as complicated) where I'll be calculating values of local variables based on arguments passed and global variables available, every time a procedure is called.
I really don't think we want that -- if we did, we should just use Tcl... there's super complicated syntax and constructs possible even with Tcl that would not be productive to implement. keeping the scope limited to Python is perfectly fine for now. we don't need multiple points of failure and a special purpose language pretending to be a standard lanaguage. :)
Yea, we can make changes on the C/C++ side without impacting the bindings on the python side.
That's not exactly answering what was asked... :) Can I make changes on the C/C++ side, like add a new parameter to an ELL primitive that is made available on the Python side without changing a ell.py file or something similar? Basically, some sort of automatically reflective binding or discovered bindings or some other mechanism.
I'll be moving on to do this once I've completed the script parser that I'm writing. It'll be done by the second eval. Just yesterday I completed an syntax parser which can parse mathematical expressions in procedural scripts :D (Got to be one of the most exciting things I've learnt and built so far)
It's awesome that you've been having fun. Implementing parsers can be SUPER exciting when they start working. One area where that may come in handy down the road is in ascertaining the security of a given script before it's passed to a parser. For now, though, I do think we need to keep it focused on Python and how object creation is exposed as an API -- what changes are needed to make that better.
I really don't think we want that -- if we did, we should just use Tcl... there's super complicated syntax and constructs possible even with Tcl that would not be productive to implement. keeping the scope limited to Python is perfectly fine for now. we don't need multiple points of failure and a special purpose language pretending to be a standard lanaguage.
I've followed the tcl syntax for writing expressions as [exp....], similar to what is defined here : http://wiki.tcl.tk/583.
That's not exactly answering what was asked... :) Can I make changes on the C/C++ side, like add a new parameter to an ELL primitive that is made available on the Python side without changing a ell.py file or something similar? Basically, some sort of automatically reflective binding or discovered bindings or some other mechanism.
No that'll be an issue, but only at the argument level. So, the ellipsoid primitive is called using this file : https://github.com/Killthebug/python-brlcad/blob/master/brlcad/primitives/ellipsoid.py.
If you change something within the working of the primitive in the C code, it shouldn't be an issue, but if you change the number of parameters being passed to it, then that has to be manually updated here.
^ Does this make sense?
Let's say you change how an ell is drawn in the c code. In that case the code on the python side can still continue to work as the internal working of the primitive are abstracted
Bindings are automatically generated according to the version of brlcad you're using when you setup python brlcad. Though the functions that work with these bindings are already coded like the ellipsoid.py file that I had shared with you above. As long as how you interact with the primitives (arguments passed) doesn't change, there isn't going to be an issue.
@Sean , here's a sample script which the script parser will work with to create the procedural geometry. https://paste.debian.net/1030745/
This is inspired from the sgicube.sh (https://brlcad.org/wiki/SGI_Cube).
This (https://imgur.com/a/Kzi8CkF) is what the "script parser" does. It's made to handle procedural scripts like the one I shared above.
Let's have something for the reflectance here. Manual updation sounds like a pain. Once you finish your primary work, I think we can have a script that continuously updates the changes made on one side to the other.
and one more thing-- DEVLOGS ;)
@Shubham Rathore YES! I think we can brew something up! Primary work is almost done. Just doing some finishing touches and making sure that the parser is robust enough. I'll also document the code soon, so far I've not done any major documentation other than code comments.
Yes, Devlogs, DONE! :D
No that'll be an issue, but only at the argument level.
Can you think of any ways to eliminate that issue? even at the argument level? For example, most of the primitive bindings including the ellipsoid.py you linked are straight pass-through parameters (a = data.a, b = data.b, etc). What would be some strategies/options for doing that automatically?
@Sean , here's a sample script which the script parser will work with to create the procedural geometry. https://paste.debian.net/1030745/
This (https://imgur.com/a/Kzi8CkF) is what the "script parser" does. It's made to handle procedural scripts like the one I shared above.
@Jaipal Singh I read this all earlier as that is what prompted the "what is the custom parsing" question...
my comments stand that we really should be focusing exclusively on python, not tcl
The reason being is that while what you wrote looks a lot like Tcl, it's technically not Tcl. It's fun to implement, but there are severe usability implications... I'm sure I could very easily add a few lines of valid Tcl that would break it ... but more importantly, I would wonder why wouldn't we just use a Tcl interpreter.
Anyone can implement the SGI cube script in a #/opt/brlcad/bin/btclsh script today, call any ged command, and use any Tcl construct. What's the value of having a different script interpreter? More importantly ... what aren't we getting done on the python side because of the detour? :)
@Sean , I'll get back to you regarding the arguments soon.
So how would a script on the python side look like?
So how would a script on the python side look like?
that is what this project is principally concerned with figuring out, no? :)
you have one example at https://github.com/Killthebug/python-brlcad/blob/master/examples/wdb_example.py and that's a start but I think quite inadequate
Yea :P
So, this is what the wdb_example.py looks like : https://github.com/Killthebug/python-brlcad/blob/master/examples/wdb_example.py
But there's no procedural elements in this
do you think you could take a stab at implementing SGI cube in "ideal python"
Yup. I think I can do that!
if you figure out what that looks like, then the next step would be to figure out how to make that happen
and there are several decision points along the way
Uh-huh
it could be straight up procedural like Tcl
or object-oriented
what's currently bound through ctypesgen looks like a hybrid
could maybe build a OO version on the ctypesgen hybrid or change the interface it's being generated off of on the C header side
i.e., have some low-level version that is essentially a straight up binding to libwdb/librt, but then a nicer OO python layer on top
change the interface it's being generated off of on the C header side
That would almost be like scraping off ctypesgen and starting from scratch, because ctypesgen creates the bindings for libwdb (I'm still thinking of a way of how we can go lower than this)
But, um, can you give me some time to research and experiment a little bit? I don't want to drop ideas without testing out a few things :P
so yeah, looks like kanzure's exisiting code was an attempt at exactly what I'm suggesting, so the next step is probably to write a "pure" version without focusing on the backend
That would almost be like scraping off ctypesgen and starting from scratch, because ctypesgen creates the bindings for libwdb (I'm still thinking of a way of how we can go lower than this)
we don't need to go lower -- what's there is probably perfectly adequate binding-wise. we can even change or add to the C side if it helped clean something up, but that gives the lowest level access without creating a cyclic dependency.
But, um, can you give me some time to research and experiment a little bit? I don't want to drop ideas without testing out a few things :P
can you try implementing the "clean python" version of that script first?
But the advantage of using ctypesgen is that it generates bindings automatically, you don't have to manually write a lot of code (unlike something like "swig")
I really don't think there's any time left to research and experiment. there's a month remaining and we're not really any closer than when you started to a feature a user could put into use yet...
Yea sure, just for clarity, what would a "clean python" version be?
I would think it's the least complicated, most straightforward easy-to-understand python that lets you create geometry
no "wdb" (wtf is wdb)
I've spent a major time of last month working on the script parser, so you can now use tcl procedural scripts to draw complicated objects. (genuinely hope it comes into use sometime) :P
probably no files, but tbd... they really just want to create geometry
Wait, no wdb, then create geometry? How?
I know you've spent at least a solid two weeks...
that's why I interjected last week to try and get you to take a step back
Yea, also sorry I deviated from it! :/
I was moving ahead with the goal of having some way to properly implement procedural geometry
I can already use tcl scripts to draw complicated objects .... I'm really having a hard time understanding the motivation
most of mged and archer are implemented in tcl...
an "mged script" is a Tcl script
that's not to say what you've done isn't potentially useful -- it could be
for example, if we implement script objects, I can't just drop in an mged script for the same reason you couldn't just call mged -- it'd create a cyclic dependency
so it's conceivable that something like your parser could be used to parse script objects in a variety of languages
tcl, python, etc
but that's why I said we really need to just focus on python -- we do not need added complexity or broad options. we need 1 that works, is exposed to users cleanly, lets us store procedural geometry scripts in .g files, works with all the expected functions like plotting and ray tracing, etc.
I suppose from your devlog that you didn't make any progress trying to stub in a new 'script' primitive like we talked about?
but that's why I said we really need to just focus on python -- we do not need added complexity or broad options. we need 1 that works, is exposed to users cleanly, lets us store procedural geometry scripts in .g files, works with all the expected functions like plotting and ray tracing, etc.
Alright!
I suppose from your devlog that you didn't make any progress trying to stub in a new 'script' primitive like we talked about?
Yea, I've not worked on that yet.
@Sean : https://github.com/Killthebug/python-brlcad/blob/master/examples/sgi.py
I'm facing a little issue with the shader, everything else seems to be fine. Figuring it out now.
Yea, I've not worked on that yet.
Okay, then it may make more sense to @Shubham Rathore to try or I can if it takes him more than a day. ;)
@Sean : https://github.com/Killthebug/python-brlcad/blob/master/examples/sgi.py
well done @Jaipal Singh !
so that's obviously a nearly direct translation of the shell script code .. but is pretty ugly python, don't you think?
so ignoring how it was done in shell, fundamentally what is going on is we're making 18 spheres and 18 cylinders, grouping them all together, and creating a region ... what's the best way to do that?
I'll get back from the office and put a night into the primitive. It'll be done.
thanks @Shubham Rathore ! if you just grep on one of the more recent primitives, it's usually pretty easy to find all the bits needed to add a new one (e.g., grep -i -r superell .) and let me know if you get stuck.
feel free to commit incrementally, might be able to help things along
so ignoring how it was done in shell, fundamentally what is going on is we're making 18 spheres and 18 cylinders, grouping them all together, and creating a region ... what's the best way to do that?
Yea, not the cleanest of python scripts. What's a better way to do it ... hmmm..
you could maybe map out the commands actually needed, and then see how you'd reduce it and eliminate the duplication
I'll try and make a condensed version. I think this script looks very "long" because there are multiple procedures involved in it (6 to be precise). Each procedure is almost the same (but that's only in this scenario, procedures will usually be fairly different I think). Also, the name of the primitives (rcc.100) created are "calculate/composed" when the procedure is called. This takes up a few lines in each procedure too.
I'm going to try and see how much I can reduce it to soon! :)
Would it be fine if I created a script with the goal of creating the same object as sgi.sh but didn't map it exactly to python (this script is a literally a translation into python)?
don't feel limited to how the original one was implemented, what names were used, the order and manner it was constructed
Alright! Yea, the previous one was completely constraint by how the original was implemented.
all that matters is making the same resulting shape (probably still with 18 spheres and cylinders)
@Sean Yess... did something similar last summer. Thanks for the help !
@Sean , tried to get it under 100 lines and also not look very complicated. https://github.com/Killthebug/python-brlcad/blob/master/examples/sgi.py
@Jaipal Singh good reduction but not sure it helped. lets step it back more. I think we need something a lot simpler to start with. How would you make a simple cylinder with rounded edges?
Maybe draw a cylinder and two semi-spheres at it's ends. Or maybe define an object that is a cylinder with rounded edges and draw that multiple times?
Not the whole end, just the edges.
A sphere would round the entire end cap.
Say I have a cylinder from 0,0,0 to 100,0,0 ... radius is, say, 25
I want the top and bottom edges to be rounded to a radius of, say, 10
How?
@Jaipal Singh here’s an example: http://www.f-lohmueller.de/pov_tut/all_shapes/shapes340f.htm
Sorry was AFK.
So a cylinder with two Tori on the ends?
try it
I'm trying to figure out the examples you've shared.
in the examples, that's using a Round_Cylinder macro someone wrote for povray, which looks like it takes a point, a direction, a radius of the cylinder, a radius on the edge, and one more parameter we can ignore
In the rounded cylinder example, the cylinder in the middle is a merge(cylinder + 2 spheres) but the first one seems to be a merge (cylinder + 2 Tori)
One second, I'll check it out
ignore the middle one and the merge parameter
it's a total distraction
I suggest trying to create one by hand using brl-cad primitives and boolean operations (in mged/archer)
once you figure it out, then write a python function that makes one for you (taking just a point, a direction, a cylinder radius, and an edge radius)
I suggest trying to create one by hand using brl-cad primitives and boolean operations (in mged/archer)
The first cylinder in the example you'd shared?
sure
you can use the values I mentioned, or duplicate the povray example, or whatever -- the point is figuring out how to construct it correctly (there are choices)
How did you deduce that it's a point and a direction? They're both 3 dimensional vectors
because that's all that makes sense in this context ;)
http://www.f-lohmueller.de/pov_tut/all_shapes/shapes3_80e.htm : Here it says A and B are two points :P
it's modeled at the origin, so the second parameter is equivalent
Makes sense! :thumbs_up:
the first can only be a point because 0,0,0 is degenerate
either way, make it a point+vector or point+point, that part doesn't matter -- pick either but after you figure out a construction method by hand :)
Yup! On it.
I think this will lay better ground work for what we're trying to get at
Aye! I think I'm starting to understand the importance of procedural geometry now. (Hopefully the right thing)
@Sean Yess... did something similar last summer. Thanks for the help !
@Shubham Rathore any progress yet?
@Sean just back from the office . About to start working.
Just wanted to know, is it possible to round the edges of an arb8? (This old email is the only clue I had https://sourceforge.net/p/brlcad/discussion/362510/thread/2cdbd563/)
@Jaipal Singh I'm unaware of any such thing. Never ever tried rounding those edges. @Sean might give you a better insight.
P.S. - if not a feature, try implementing it through procedural geometry ;)
@Jaipal Singh of course it’s possible. There are very few shapes that are not possible without resorting to explicit surfaces. Rounded edges on a box is a basic intro shape, only slightly more complicated than rounded rcc. Speaking of which, did you figure it out?
If you need a hint, rounded rcc requires at least 4 shapes.
@Sean What should the " rt_script_internal "look like. What params should it comprise other that the uint32_t magic ?
@Shubham Rathore we don’t know that yet so can just stub it empty.
I’d expect it’ll probably need a text buffer, something describing what kind of script it is, and maybe instantiation info
Was thinking the same... Probably a bu_vls and a magic should be a part currently
Sounds like a start
@Jaipal Singh What are you working on currently ?
@Shubham Rathore , I just started work on modeling a round edged cylinder. Will then implement it in python once I know how to construct it.
The primitive will be ready soon, the part to link your code to the primitive stands next. You should start thinking of ways to encounter all the issues that we might have in the coming days.
Sure
Screen-Shot-2018-07-12-at-5.02.07-PM.png
Getting there.
@Shubham Rathore , I just started work on modeling a round edged cylinder. Will then implement it in python once I know how to construct it.
Figure it out yet?
@Jaipal Singh ? this can't be an all-day activity. it was supposed to be something quick that just takes an hour at most. there needs to be more communication, more coding, please.
if you can't figure out the caps, that's okay, say something! it's not a test.
Spent a ton of time, just not able to figure it out!
I drew an rcc (rcc1) with two tori(t1, t2) on the ends, then tried to subtract another rcc(rcc2) of the same height but lesser radius from the tori. After this fill the space with rcc2 and render. On paper it makes sense, but I just can't visualize it
so @Jaipal Singh you have the right idea with torii on the ends. you just need to fill the divets they create (with another cylinder).
a rounding is about tangency, so you need something tangent with the side and top of the torus
which method do you think would be easier to implement in code?
Method 1 seems the simplest
The only motivation I see behind method3 is that it could allow the user to have two different types of rounded edges (different on top and bottom)?
that's a great point regarding the differences!
however, that would also imply not using canonical torus
canonical as in isometric?
but that's a great point, one could use an elliptical torus to taper sides differently or arb8's to create hexagonal pattern or ...
The only issue with the arb8 is that it might overflow right. then we'll have edges that are beyond the tori
canonical == ring torus with a circular cross-section
if you unioned them, sure, but that wouldn't be the way to go -- you'd want to subtract them
chamfers instead of rounds
We'd have to have restrictions on the relationship between the tube radius and the width of the arb8 as well...
so for the script, just keep it as simple as possible -- the parameters we talked about yesterday were perfect: cylinder start/end points, cylinder radius, and rounding radius
see if you can implement a function that takes those four and produces a method1 result
Ok sure
note my comment about needing to reduce the principal cylinder's length by the rounding radius on both ends
so if you specify a cylinder 100 long (e.g., from 0,0,0 to 0,0,100) with rounding 10, you'll create a cylinder 80 long (because you have to +10 rounding on each end), and then create your interior cylinder 100 long, but with a radius reduced by the rounding too.
make sense?
Yea does!
So, only the z co-ordinates would be impacted right
No no!
heh, not at all if the user is allowed to specify two random points
Yes, I'm just thinking my way around it (i'm poor at 3d visualization)
since the point of this isn't figuring out math, you can keep it simple and now support two points -- you could support a cylinder length instead and just model it at the origin, up the Z axis
if you want to figure it out, I can talk you through what's needed
I suggest keeping it simple
can always come back and make it better :)
since the point of this isn't figuring out math, you can keep it simple and now support two points -- you could support a cylinder length instead and just model it at the origin, up the Z axis
I'll do this for now, but I'd really appreciate if you could talk me through the math too :P (I want it to be able to handle everything)
Yea!
I'll give the math a thought while I'm creating the simple version, will maybe hit you up later if I don't get it
so a python function then will take a cylinder length, cylinder radius, and rounding radius
Can we keep it to be two vertices, cylinder radius and rounding radius? We'll just pass it arguments such that only the z-coordinate changes
That way if we change the math later, we won't have to change a lot of the code
that way you can follow exactly what's in method1 in the sample geometry, which essentially is the result of "function(1100, 250, 50)" iirc
I'd keep it simple arguments that are valid, not plan for future but be wrong in the meantime.. there's not going to be a lot of code to change
Ok sure
this whole thing is probably going to be < 40 lines with validation and bounds checking
Yea. Sean, why do you use "no tree"?
the geometry is made in six lines
what do you mean "no tree"?
... comb region no tree {u {u ... . Is it because you don't want it to print the tree structure?
heh
you're reading the .asc file ... just because it's text doesn't mean you should be reading it like it's text ;)
that's the serialization format of a comb in .asc format
those are key value pairings in Tcl list form
Oooooh!
region=no
tree="{u {u ..."
Makes a lot more sense :|
if you compile, you'll have a rounds.g in your share/db folder, or directly run asc2g rounds.asc rounds.g
then open that .g in archer or mged
Alright
that's a v5 asc file .. if I had uploaded it as a v4 asc, you probably wouldn't have tried to read it ;)
if you look at the other .asc files, you'll notice how they're different
Haha! Just saw some of those, I don't think I can really spend time deducing them. :sweat:
basically, you're not supposed to read them ;)
I'm a little stuck with respect to the geometry. For the end of the cylinder away from the vertex, I'm able to achieve a perfect rounded edge.
On the end of the cylinder near the origin, I make the outer cylinder with : in outer rcc 0 0 10 0 0 90 40 and the filler cylinder with : in filler rcc 0 0 0 0 0 100 30
r/sphere/cylinder
Despite having different inital vertices both the cylinders seem to have the same start point. But if I change to : in outer rcc 0 0 0 10 0 0 80 40, I can see the outer cylinder moving away from the origin
your filler cylinder shouldn't have a radius larger than your outer...
Filler had a radius of 30 and the outer of 40, that's not an issue right
if you create them in mged, you can highlight them with "sed outer", followed by "reject"
I think you may be misinterpreting the wireframe
Could be, I'll figure it out.
it can be confusing to read them right if you never have before. turning on "depth queuing" in the Misc menu may help a little
Done!
@Sean : https://github.com/Killthebug/python-brlcad/blob/master/examples/rounded_rcc.py
excellent! let's see some examples...
@Shubham Rathore excellent too, can you commit what you have? I can probably finish is up today.
@Sean , what's the plan for the next month then?
@Jaipal Singh you tell me first :)
and where are those examples? :)
Just saw the chat, will make em soon and share. :)
Also, should I include some sort of validation/check in the script to prevent possibly incorrect values being passed
sure, sanity checks for what actually works is always a good idea
I think the final part of the project would be to pair python-brlcad with the script primitive
can't have a bend radius greater than the cylinder radius, can't be more than half the cylinder length, ...
Sure! I'll think of anything else if that might be an issue
I think the final part of the project would be to pair python-brlcad with the script primitive
I'm hoping we can get further than this, but I fully agree with this as a goal as it puts python into user hands
one thing we need to figure out quickly is how this all gets used
True, that's what I wanted to know. Once we couple with with the script primitive what happens?? What's the workflow like? When is it used?
what the actual mechanism looks like and how it's hooked up via script objects, whether we need separate objects to instantiate them or not
I'm hoping we can get further than this, but I fully agree with this as a goal as it puts python into user hands
I think the project will have a lot more thing to be worked on, I was just setting the month's target as perfecting the pairing between them
so I think we need to think about end-user design
what we want that to look like since that will drive some of the implementation decisions
Uh-huh.. So let's say I want to construct a lot of rounded cylinders
And let's also assume, there isn't a script for rounded cylinders.
k
So I write a script in python (like the one I had shared above)
first question is whether that script can go into the .g or if it MUST live in an outside file
I think it should be able to go into the .g since we do want a .g to fully function if someone wants it to be portable by itself, but not limited to being in the .g
which would be similar to how we handle image data like textures, they can be embedded or in external files
Yea, first off I don't know how it can be inside a .g file and secondly I don't think it should be because it locks up a lot of flexibility
you can put anything into a .g, it's just a collection of objects -- you can stash a microsoft word document in there, for example
Uh-huh
Woah, didn't know that (too)!
Once I make the script, I can pass it to the script primitive and some params with it to construct my objects in mged or archer..
and you can pull them out, use external tools on them, etc
right, so script exists (somewhere)
Woah, is .g a universal format or something that was made by brlcad?
Yea, somewhere (we've got to figure out how paths are decided then)
Woah, is .g a universal format or something that was made by brlcad?
yes ;)
Or we could have a predecided directory, but that would be a pain.
Damn, sweet!
it was designed, has a formal specification, we've talked about maybe submitting it to ISO, but it's pretty flexible as-is
we could even require that the script be embedded and if a user wants it to be external, they'd #import or whatever in the embedded source
so options there, I don't see any problems
Amazing. (Just out of curiosity regarding the .g files, is there some documentation about how it was made?)
so the script exists, and we need some way to instantiate what it creates
Be embeded?
there's an old out-of-date spec file here https://brlcad.org/w/images/2/2d/BRL_CAD_g_format_V5.pdf
that's a conversion from the real source with lots of sections removed, that was some 15 years ago
Oh embeded as in, in the script primitive? So we can have some important procedures be embeded?
the documentation on how it was made is in old mailing list archives, not easy to get to (might be some details in the source repo doc dir)
embedded as in inside the .g file, we could require that there be at least a snippet of code to import and call a function \
Great, I'll try and gather all that I can! (It's very sad so much documentation get's lost over the years, but again, can't do anything about that)
the only reason for doing that would be to simplify the usage -- wouldn't have to have options for specifying whether the script is in an object or in a file
Alright alright
that wasn't in response to gathering docs :)
Haha yea! :P
the only reason for requiring a script be in the .g would be to simply usage
you're welcome to gather docs or not -- I'm not sure what you'd do with them, and you definitely don't have access to all of them :)
definitely not helpful for your project, but spelunking is fun :)
the only reason for requiring a script be in the .g would be to simply usage
True. I hadn't thought of it like this. I always assumed that we'd have a directory where we'd have a bunch of scripts that could be used.
so ...
well that's a good point
we'll likely end up shipping a set of standard scripts that are available to users, and those definitely won't be embedded in the .g
And that way people could modify any of the scripts depending on how they might want it to
do you know how python's import mechanism works?
I mean how it searches, how that's controlled?
Not very specifically, but I have vague ideas. I could learn by tomorrow
don't worry about it then, just wondering
back to instantiation...
I know it can import modules and objects and usually looks up in a standard directory (where all packages are present) or the same directory if you a __init__.py in it.
Yea..
*you have a
so the 'in' command is the canonical entry point for creating objects by hand
in mysphere sph ...
Uh-huh
Yea
so first thought that comes to my mind is whether we want to propagate scripts up to being first-class primitives or not
in myroundedrcc rounded_rcc ...
probably not that low, but it's an interesting thought
Ohh! I don't think we should do something like that
But then that way if I introduce a new script, I'll have to recompile the code so that it reflects in the in command
next would be whether instantiations are separate from the scripts themselves if they're embedded
How about something life : in myroundedrcc script rounded_rcc
yes, that's more likely if we don't propagate to first-class
good
so there's specification of the script source and specification of the instantiation
Yea..
they could be one in the same, but I'm not sure they should
Now that I think of it, it might be different..
for example, both together might be something like: in myrcc script FILE FUNCTION ARGS
Alright..
in myrcc script /path/to/rounded_rcc.py rounded_rcc 100 50 10
Perfect
with that, the script lives in a file, we specify the entry point, and arguments to pass -- does that work for all argument types a script might want to pass?
I think so ...
Uhm, so I don't know about things sketch.. but for the primitives that we're dealing with for now, I think it should all go through
well basically it's asking if there's anything we might need to pass to a python function
that isn't easiliy described as an int/float/string
Nothing other than those would be required
so let's call that "option 1" .. script objects that specify source and instantiation
other options?
_thinking_
I've always had only the option1 in my mind when I've thought of including the scripts..
How about re-using instantiations?
No, that's just complicating some simple things..
think about what you originally said -- say you have a bunch of instantiations
say 100
easy enough to create them all. now we decide to change the name of our function from rounded_rcc to rounded_cylinder ...
Uh-huh..
wham, 100 broken objects .. what can we do about that
Taking a step back, what are instantiations here?
Even if you change the function name, you need to re-compile all the code
Now, talking about the instances we had created earlier, they're independent of the function_name right cause what matters to us is the object name (myrcc) which contains commands on how to build the object we want
instantiations are separate instances of that script being run
so in that first example, it's a rounded cylinder length 100, radius 50, rounding 10
OK
that's 1 instantiation, an object in the database with name 'myrcc'
I can copy that, rename it, delete it, scale it, translate it, etc
Yea..
so instantiation == geometry
geometry resulting from running the script
Alright, yea. So the instantiation is independent of the function name in the script right?
in "option 1" yes ...
I suppose we could run the script right then and there, and be done with it, so renaming the function wouldn't break the objects
Yea.. So this way even changing the function name doesn't become an issue
let's call that "option 2"
downside being say instead of changing the function name, I change the implementation ... now I have to re-run all my instantiations
Yea, that's almost like creating a new script in it's own.
basically, it's not much different than just running the script, importing the result .. no association
I was thinking something more dynamic that stays in sync and gets evaluated on-demand
Hmm.. So we track changes in the script and then modify all the instances of a script before it was changed?
I don't need script objects if all i'm going to do is run "exec ./rounded_rcc 100 50 10 ; dbconcat file.g"
I don't think we could reliably track changes in the script
but we shouldn't need to
if it's on-demand, the script can be evaluated as needed
I suppose we could run the script right then and there, and be done with it, so renaming the function wouldn't break the objects
Like you said
hey, so I see the time for you -- is this something to pick up later?
or keep going, i'm fine either way :)
I've got 10 minutes before it's bedtime so I'd like to continue a little more :P
okay
I mean, if that's okay with you?
like I said, I'm fine either way :)
I like the option of running the script then and there and finishing it off
my point earlier is that if we just run the script and are done with it -- that's not a very helpful feature
users could do that now just by running the script outside of mged for example
there's not really much added value
we save them 1 step, importing what they created (dbconcat)
Alright..
that's where my original thinking is with scripts that live in the database, I want to edit code on the fly and see geometry change :)
like what if while you were writing your rounded_rcc.py script, you could see the geometry pop up in the window, add one more line to create a torus and you see it
instead of re-running, opening the geometry file, running ls, drawing the geometry object, etc
edit, see it
I think that's what we want
Ahhh!
I get it
So, are .g files that are being rendered refreshed constantly?
Yes!
or at least we could make them do that
Again, something I just learnt!
everything goes through the primitive callbacks, so in the case of a script object we can choose to re-evaluate the script every time or only once
I think it should re-evaluate every time for starters
Alright, alright.. So that'd be something we account for when we're creating the script primitive?
right, so some basic background there -- every primitive defines a set of functions
Ok..
one of those functions for example, plot(), creates the wireframe you see when you run "draw someobject"
when you run "rt someobject", it happens to call prep() once and shot() lots of times to render an image
when you run "l someobject", it calls describe()
Alright
so we define all of those functions, and would for a script object
Are these defined in each primitive or are they defined somewhere else and then called for a specific primitive?
so the basic idea is that we'd call the python interp before most if not all of those functions to get the geometry
Yea
Are these defined in each primitive or are they defined somewhere else and then called for a specific primitive?
no comprendo .. don't understand the question
So let's say you have : describe(). It serves the same purpose for each primitive. Now, do you define a describe() for each primitive (in each file for a primitive) or is it a single function places somewhere that is called and the primitive is passed to it.
serves the same purpose, but is different for every one of them, so yeah each primitive defines itself
every primitive defines this set of callbacks (you can browse them in src/librt/primitives ... 1 subdir per primitive) -- this is what @Shubham Rathore is stubbing for us empty
Yea, I've gone through some of those to get a basic idea about them
it's not describe(), it's actually rt_ell_describe() and rt_arb8_describe() and ... we'll have an rt_script_describe()
Ahh! Ok.
there is a general rt_obj_describe where you pass the object, but it automatically calls the rt_*_describe() for that object
it's all implemented in a form of object-oriented C
Sweet
so we have options 1 and 2 which are "in obj script file func params..." and then only difference being whether we evaluate file every time or once and forget the file
Hmm yea. Now again, I think it's best if you decide this, cause you'd know what the users would prefer
Can we continue this tomorrow? :) It's 2:30AM and I'm going to spoil my weekend if I sleep into tomorrow afternoon!
there's an option 3 where we separate the script specification from instantiation, so that might be something like: in rrcc script /path/to/rounded_rcc.py rounded_rcc .... and another command like "script create myrcc rrcc 100 50 10"
Oooh! So if you change the script, you recompile and it then changes the instantiation?
option 4: or even two separate primitives, one for script, another for instance: in myrcc instance rounded_rcc 100 50 10
But this won't do the real-time rendering thing (option3)
I think option 4 could be reached once we implement option 2 followed by option 3
Oooh! So if you change the script, you recompile and it then changes the instantiation?
right, there'd be some way to propagate updates or re-evaluate, maybe "script update myrcc"
Yea
we can do the on-demand evaluation with all but option 2 since that's specifically what it's about
so I think 2's out
Alright
okay
so let's think on it some more
you working this weekend or not?
Second half of tomorrow and first half of Sunday, yes!
World Cup Finals on Sunday night :D
okay, so maybe we can continue the discussion tomorrow
right!
Sure!
fun
alright, well good talking -- sleep on it some ;)
Was that sarcastic? :P
nope :)
Indeed! :D
Sorry! Night!
I do that often .. think about something late into the night, then sleep on it so I can realize how awful those ideas were ;)
night!
I do that often .. think about something late into the night, then sleep on it so I can realize how awful those ideas were ;)
hahaha! :P
I do that often .. think about something late into the night, then sleep on it so I can realize how awful those ideas were ;)
hahaha! :P
Actually helps! Specially when you need to devise an algorithm, sleep with the problems and you have a solution or maybe a rough idea the next morning. :)
@Sean the patch for the primitive is uploaded, Do let me know if you find an error : https://sourceforge.net/p/brlcad/patches/500/ . @Jaipal Singh Have a look !
Sure!
Thanks! :)
@Shubham Rathore that's outstanding work!
looks pretty good to me, only thing I notice is that you have a couple unrelated files in there modified
annot/annot.c and src/libdm/dm-X.c have changes that don't look related
other than that, looks good to commit!
for what it's worth (it's a minor point, not a problem) -- you don't need to add v4 support for new primitives (db4.h)
Yesss.... i know db4 is of no use now, just added them :).
Yes, there were some indentation issues with annot.c that I rectified
Yes, there were some indentation issues with annot.c that I rectified
that's fine, they should just be in a separate commit, and the src/libdm/dm-X.c change looked like commented/uncommented code
Ah ! sorry for that
@Sean I've uploaded a revised patch (https://sourceforge.net/p/brlcad/patches/500/) in the comments. Have a look !
Some examples of rounded_rccs Screen-Shot-2018-07-16-at-2.50.02-PM.png
Added basic sanity checks as well.
@Sean I've uploaded a revised patch (https://sourceforge.net/p/brlcad/patches/500/) in the comments. Have a look !
this looks great, please commit it
@Jaipal Singh so what's next?
we talked about 4 options for the user side, eliminated one of the options, and we still have to sort out how to bridge from object to script
there's an option 3 where we separate the script specification from instantiation, so that might be something like: in rrcc script /path/to/rounded_rcc.py rounded_rcc .... and another command like "script create myrcc rrcc 100 50 10"
With regards to option 3, I didn't get how the rrcc object came into picture. Could you maybe elaborate on that a little bit?
Should I start exploring libged/typec.in to understand how we'll be linking the script parser to the script primitive?
I had a look at the patch that @Shubham Rathore had submitted and gather that it's similar to the other primitives. Thanks for this!
Next would be to have functions that can read the file, invoke the python script parser and create the .g file.
Another issue I see with using the 'in' command is that for most primitives, there's a defined list of parameters that it expects from the user. In case of our procedures, we won't be able to know before hand what arguments are required, hence that becomes a problem.
We could move forward with the assumption that the user knows what parameters are required by the procedure and that he would enter only those (but that's a weak assumption)
there's an option 3 where we separate the script specification from instantiation, so that might be something like: in rrcc script /path/to/rounded_rcc.py rounded_rcc .... and another command like "script create myrcc rrcc 100 50 10"
With regards to option 3, I didn't get how the rrcc object came into picture. Could you maybe elaborate on that a little bit?
the first command (in rrcc script /path/to/script ...) just creates a handle to the code, then we'd need some other step to instantiate the code
it's a named handle like any other object, so in that example, I named it rrcc, but it could be anything -- in foo script /path/to/myscript.py func
script create myinst foo 1 2 3
Oh ok ok
I had a look at the patch that @Shubham Rathore had submitted and gather that it's similar to the other primitives. Thanks for this!
Next would be to have functions that can read the file, invoke the python script parser and create the .g file.
not quite -- one of the details that need to be figured out is not creating .g file (at least not on disk)
since it's an object, it's not dynamic if we write it out
not quite -- one of the details that need to be figured out is not creating .g file (at least not on disk.
Python BRLCAD uses the libwdb API and that takes a file_pointer whenever it has to construct a primitive. How do we prevent it from writing to a file then?
Also, it has to be saved into some .g file so that the GUI (mged or archer) can read and display it?
no it doesn't
there's an in-memory-only form of databases that we can use
it happens when you open a database, the API has a parameter that tells it to only write to memory, not to disk
all the other geometry routines remain unaffected
what I think needs to happen is that the database instance gets passed or made available automatically to the script
OR .. maybe a default state in 'wdb' that gets set before the script is run so when it runs import wdb, it's going to be an inmem database when it makes a call like wdb.WDB(database_name, "SGI.g")
what I think needs to happen is that the database instance gets passed or made available automatically to the script
Yea, this makes some sense
looking at https://github.com/Killthebug/python-brlcad/blob/master/examples/rounded_rcc.py ... there's a few ways I could see this working
when is __name__ not "__main__" in python?
If you import this module into another file and then call a specific function, then __name__ is not __main__
hmm
so doable in a couple ways
one way (A) could be to run the script and use some global variable (like __name__) for the database instance. this would require scripts to be aware of that instance and would probably be incompatible with external execution.
another way (B) could be to leave the script as-is, but preload/configure all wdb.WDB() calls to be inmem when run from inside and be a regular file when run externally. this should require no changes to the script, but will require figuring out how the script knows about the database/geometry
(C) How about moving forward with creating classes for procedures? That way the database instance can be passed as an argument to a given object otherwise it can fall back to using some default database.
another could be to only support "import script" form where __name__ is not main, and calling a specified function that takes a WDB as the first argument (or maybe it's stored in a variable akin to option A)
(C)
can you elaborate? classes for procedures?
I'm in the dark about how to go about solving (B)
(B) could be as simple as putting a line like if __name__ != "__main__" in brlcad.wdb that sets a global configuration for in-mem
Yea.. (I'm still thinking about why I said classes as procedures).
Oh yea!
So, if you look at rounded_rcc.py (A), if you import this into another file (B) and try to call it from there, then the variable __name__ takes the value of the name of the module it is being called from (B).
But it doesn't stop there, the interpreter then goes on to execute all the other functions in rounded_rcc.py from the top to bottom.
One second, let me share an example with you..
k
https://stackoverflow.com/a/419986
What I was hinting is that the functions which are responsible for creating the procedural shapes be re-written as classes
So in rounded_rcc.py : def rounder_rcc -> class rounder_rcc.
It's not a very massive change IMO, just makes things simpler. Also makes using one procedure in another procedure an easier task.
Something like : https://github.com/Killthebug/python-brlcad/blob/master/examples/class_rounded_rcc.py
mmhmm.. I'm not sure that's any better or worse -- the script would still be entirely inmem aware and run in one mode or another. ideally we need a solution that doesn't require script modification or minimal modification? flexibility would be good for usability
like not even worrying about making a def or class
Ok
writing up an example, hold on
Sure
AKF for 15
AFK for 15
something like https://gist.github.com/brlcad/7de8f35386c9e40075c07a708fc9aed5
I think I see a way
we already decided the function must take arguments, so why not make it strictly be anything that could be run as a program, just that the first argument must be the name of the database! then we can override it with a path to a temporary database file and read the contents into an in-mem automatically.
/me is liking this ...
that means we can make it work with literally anything that creates geometry and the python driver becomes incredibly simple and extendible to other command-line generators (like our proc-db and shapes examples)
we already decided the function must take arguments, so why not make it strictly be anything that could be run as a program, just that the first argument must be the name of the database! then we can override it with a path to a temporary database file and read the contents into an in-mem automatically.
Perfect!
read the contents into an in-mem automatically.
How does this happen though?
there can be a wrapper on the "import" callback to run the script and read the contents on the C side
Alright!
So what should be the next steps for me?
so then the only question is whether to actually embed a python interpreter, or just run python externally as a command
I think simplifying the WDB interface on the python side is needed
I recommend running python externally as a command.
what's in the brlcad module currently?
obviously at least brlcad.wdb and brlcad.primitives classes
what else?
vmath repo to handle basic maths
code to generate wrappers for libwdb, libged, libbu, librt, libbrep and libbn
ged?
Yea
can you elaborate, what does it wrap ... ??
It's a wrapper for ged.h. Depending on the platform (OSX, Windows, Linux) it loads the libged library.
but I mean what's it look like -- does it expose all of libged's commands?
No, only a few functions are implemented.
All before line 177 in :
https://github.com/Killthebug/python-brlcad/blob/master/brlcad/ged.py#L177
ls, close, ged_3ptarb and ged_in.
There are barebones structures for the other method but they're still to be fixed.
looks like the GED class is inmem aware
I think I got it!
https://github.com/Killthebug/python-brlcad/blob/master/brlcad/wdb.py#L72
We can change : RT_WDB_TYPE_DB_DISK to _RT_WDB_TYPE_DB_INMEM
Even after changing, it still creates a .g file... there's something I'm missing.
But if we change the mode it shouldn't right?
I'll figure this out..
@Sean I've uploaded a revised patch (https://sourceforge.net/p/brlcad/patches/500/) in the comments. Have a look !
this looks great, please commit it
Done !
Even after changing, it still creates a .g file... there's something I'm missing.
yes, it's because of the first call to libwdb.db_open()
there's a separate call for inmem's, db_open_inmem()
note, the only reason for getting inmem to work on the python side would be to avoid hitting the disk entirely (i.e., for performance) by running in an embedded interpreter
@Jaipal Singh what can we do about brlcad.wdb.WDB() ... that seems entirely not user friendly. I don't think the python public API should expose "wdb" anywhere, especially as part of a class that fully wraps wdb
@Sean , right now I'm not aware of any way to bypass brlcad.wdb.WDB(). We can maybe encapsulate in some parent class and hide it from plain sight..
eh? maybe you misunderstand.
I think so..
of course we can do something about it... we can rename the WDB class to something that isn't alphabet soup
we can rename the file it's coming from to something more meaningful
e.g., brlcad.make.Geometry
or putting something into brlcad.py like db = brlcad.Database(...)
or many other possible variations
something more usable and readable than wdb.WDB
Oh alright! Yea we can do that!
also, for later today -- can you investigate which wdb functions are on the python side and which are currently not (perhaps make a spreadsheet table showing which are in python and which are not)? grep WDB_EXPORT include/wdb.h ... compare with the WDB class implementation, what isn't used/referenced? we don't want to expose everything as some functions in wdb.h need to go away, but it'd be helpful to see a summary of where we're at and whether any functions are missing.
Oh alright! Yea we can do that!
already kind of liking brlcad.make.Geometry
but of course open to ideas if you think up something better :)
I'll make the spreadsheet today! And also work on renaming the functions.
Sure thing will keep you posted :)
@Sean when we say that, the python Public API shouldn't expose wdb anywhere, changing function names still exposes the API right? (Just makes it less obvious)
what do you mean?
there's the C api, which shouldn't matter to python scripters -- it only matters as an implementation detail
e.g., the geometry creation functions happen to be in a "wdb" C library, but they don't need to know that (nor should they care)
Alright. So abstract as much information as we can?
they want to know how to create/modify geometry
Ok ok, makes sense.
at some point in the near future, we're going to move functions in wdb closer to the primitives in librt ... and we're going to move the primitives out of librt into their own "libg" library along with the other .g related functions
oh, when you make a spreadsheet, would you add a column for the primitives listed in src/librt/primitives/tables.cpp and itemize which one's don't have an mk_* function ...?
Sure thing, could do that! :)
at risk of lining up too much, when you get all that done -- try to implement rt_script_describe() in src/librt/primitives/script.c -- you'll need to modify the rt_script_internal in include/rt/geom.h to hold a filename, src/libged/typein.c needs to ask for and safe the filename, and src/librt/primitives/script.c needs to load the filename during import5 and write it during export5, then print the file's contents during describe... then if you get it all working right, it should show a files contents when you run 'l script' after 'in script script yourscript'!
should hopefully keep you busy all week -- I"m going to be a bit preoccupied
Sure!
Another issue I see with using the 'in' command is that for most primitives, there's a defined list of parameters that it expects from the user. In case of our procedures, we won't be able to know before hand what arguments are required, hence that becomes a problem.
usually we prompt the user in such cases !
at risk of lining up too much, when you get all that done -- try to implement rt_script_describe() in src/librt/primitives/script.c -- you'll need to modify the rt_script_internal in include/rt/geom.h to hold a filename, src/libged/typein.c needs to ask for and safe the filename, and src/librt/primitives/script.c needs to load the filename during import5 and write it during export5, then print the file's contents during describe... then if you get it all working right, it should show a files contents when you run 'l script' after 'in script script yourscript'!
How's it going? Hope you are not stuck
@Jaipal Singh What is the current status? What is the plan, to execute the script using the script primitive that you are sticking to ?
usually we prompt the user in such cases quote
The prompt that is generated (for each primitive) is hardcoded as your can see in libged/typein.c. The issue we face is that we don't have prior knowledge about what primitives are there in a procedure.
at risk of lining up too much, when you get all that done -- try to implement rt_script_describe() in src/librt/primitives/script.c -- you'll need to modify the rt_script_internal in include/rt/geom.h to hold a filename, src/libged/typein.c needs to ask for and safe the filename, and src/librt/primitives/script.c needs to load the filename during import5 and write it during export5, then print the file's contents during describe... then if you get it all working right, it should show a files contents when you run 'l script' after 'in script script yourscript'!
How's it going? Hope you are not stuck
I haven't started on this yet, I'll get started tonight. I was just completing a couple of other tasks :) Will keep you updated!
usually we prompt the user in such cases quote
The prompt that is generated (for each primitive) is hardcoded as your can see in libged/typein.c. The issue we face is that we don't have prior knowledge about what primitives are there in a procedure.
That is absolutely correct. What I meant to say is to ask the user the numerical occurences of all the relevant primitives. This can be a hack till things start working. Once we have a running model we could parse the details of the primitives present through the script and dynamically modify the typein.c ! This wont be a major task to handle "once we have a running model "
So the work that you've done till now, converts a script to a .g file. The script primitive (just for understanding) runs the python script and makes an object. Now this object should be a part of the .g mentioned previously.( The object is a concatenation of various primitives as mentioned by the user). We need to modify things such that we don't get a .g immediately, rather we include the script object and then go for a .g . This is what I thought ! @Sean any insights.
I haven't started on this yet, I'll get started tonight. I was just completing a couple of other tasks :) Will keep you updated!
yes... and how are those going too?? there's been no update since our talk.
talked about a symbol mapping spreadsheet, a column for primitives without a mk_ function, and implementing the 'l' command (it's ft_describe() callback)
something more usable and readable than wdb.WDB
Hey @Sean I've completed renaming the libraries and I've updated all other dependent files, examples and tests.
also, for later today -- can you investigate which wdb functions are on the python side and which are currently not (perhaps make a spreadsheet table showing which are in python and which are not)? grep WDB_EXPORT include/wdb.h ... compare with the WDB class implementation, what isn't used/referenced? we don't want to expose everything as some functions in wdb.h need to go away, but it'd be helpful to see a summary of where we're at and whether any functions are missing.
I've completed this too.
at risk of lining up too much, when you get all that done -- try to implement rt_script_describe() in src/librt/primitives/script.c -- you'll need to modify the rt_script_internal in include/rt/geom.h to hold a filename, src/libged/typein.c needs to ask for and safe the filename, and src/librt/primitives/script.c needs to load the filename during import5 and write it during export5, then print the file's contents during describe... then if you get it all working right, it should show a files contents when you run 'l script' after 'in script script yourscript'!
I've almost completed this, will finish it and submit a patch in a couple of hours.
I've been travelling this weekend, and will also be travelling in the week after this one. My communication lapsed because of the same.
I will update the daily logs too right now.
You can check the commits here. https://github.com/Killthebug/python-brlcad/commits/master
Regarding implementing l describe, I've modified rt_script_describe() in script.c to print out the the contents of the files. But there seems to be an issue with typein.c where in mged stops accepting any response after all the parameters for the in command are passed.
Screen-Shot-2018-07-23-at-9.45.48-AM.png
What do you think could be a possible fix for this?
Probably some issue with the args(). Not a major issue. I don't have access to the code right now, it'll be rectified by the evening. Meanwhile you could focus on opening the script.py file and listing out its contents when prompted by the 'l' command (basically the describe function).
Ah yes, I was thinking along the same lines. The args() in typein.c.
So when you do : in scriptobj script myscript.py, what gets stored in the scriptobj "right now"? Does it create a null objects (scriptobj = null)?
Of course later it would hold the procedurally generated object but we've not coupled the python compiler with the C code yet.
So when you do : in scriptobj script myscript.py, what gets stored in the scriptobj "right now"? Does it create a null objects (scriptobj = null)?
Of course later it would hold the procedurally generated object but we've not coupled the python compiler with the C code yet.
It does not make a .s currently. Null object comes into the picture when the .s is created but stubbed empty for some reason.
Alright
I'll make the spreadsheet today! And also work on renaming the functions.
Sure thing will keep you posted :)
@Jaipal Singh if you have the spreadsheet, please post it somewhere as that will help us figure out our path forward
https://github.com/Killthebug/python-brlcad/blob/master/wdb_functions_python_brlcad.xlsx
So when you do : in scriptobj script myscript.py, what gets stored in the scriptobj "right now"? Does it create a null objects (scriptobj = null)?
You can see this in src/libged/typein.c in the script_in() function -- it allocates an rt_script_internal object but only sets the script type (see p_script) .. which you specified as "myscript.py" in response. If you run the 'in' command without arguments, it will prompt interactively based on the p_script prompts.
https://github.com/Killthebug/python-brlcad/blob/master/wdb_functions_python_brlcad.xlsx
That looks good, thanks. Are you still working on adding a column for the primitives with/without a mk_ function?
They're all listed in src/librt/primitives/tables.cpp or you can look at the subdirectories in src/librt/primitives/* -- two live elsewhere (comb and binunif). Note that some of the mk_ functions map to the same primitive like arb8 and arb5 are both src/librt/primitives/arb8 (not to be confused with src/librt/primitives/arbn which is a completely different 'arbn' object).
So when you do : in scriptobj script myscript.py, what gets stored in the scriptobj "right now"? Does it create a null objects (scriptobj = null)?
You can see this in src/libged/typein.c in the script_in() function -- it allocates an rt_script_internal object but only sets the script type (see p_script) .. which you specified as "myscript.py" in response. If you run the 'in' command without arguments, it will prompt interactively based on the p_script prompts.
I get this, but why does mged not do anything after accepting the in command (in scriptobj script myscript.py) . For other primitives it draws them, but here it just prints (null) as you can see in the screenshot.
https://github.com/Killthebug/python-brlcad/blob/master/wdb_functions_python_brlcad.xlsx
That looks good, thanks. Are you still working on adding a column for the primitives with/without a mk_ function?
Yea, sharing soon!
The (null) printing is likely coming from code put into the ft_describe() callback. It could also be coming from the ft_draw() callback which is also in src/librt/primitives/script/script.c -- after the 'in' command, that callback is called since most get displayed
https://github.com/Killthebug/python-brlcad/blob/master/wdb_functions_python_brlcad.xlsx
That looks good, thanks. Are you still working on adding a column for the primitives with/without a mk_ function?
I've update the shared file with another sheet containing list of primitives without a mk_primitive() function.
comb though has two mk_primitive function, mk_comb() & mk_comb1()
excellent, thank you -- that latter sheet is particularly informative. looks like we're missing wdb hooks for 5 entities
Would these be the last 5 rows in sheet 2?
Would these be the last 5 rows in sheet 2?
no, they are: rec, superell, revolve, pnts, and datum
Uh-huh
by the way, great job finding not only the libwdb functions but also the wdb functions in librt
:)
Now, I'm trying to get l describe() to work, still haven't figured my way around the (null) printing.
a classic method, you can add some print statements into the code so you can tell where things are coming from
have you added any code to the describe() function?
Yes, I have https://hastebin.com/awugozused.cpp
Also, there is no draw function in src/librt/primitives/script.c
it's the plot() function
so you're close, but you have a bug
Ok
Yea..
what you are fopen()'ing is wrong
testing
I tried two things, the first hardcoding the absolute path for a script with in src/librt/primitives/script.c and second removing all the code that I had introduced in src/librt/primitives/script.c and just compiling with almost the original stubb. The same error persists.
you're pretty new to C I take it?
Not vey familiar :/
the error in the snippet you showed me is that you printed "Script type: ..." into buf
then you try to fopen(buf)
so you're trying to open a file named "Script type: something..."
another issue is you should be using bu_fgets() instead of fgetc(), to get the file one line at a time
the loop you have isn't quite right because you used a char when fgetc() returns an int, so your condition (character != EOF) should never be true. a little surprised it's not an infinite loop
note, vls stands for variable length string -- it's just a string like you might have in python except you access it via functions
Doesn't fgetc() return a character? http://www.cplusplus.com/reference/cstdio/fgetc/
look at the green line at the top
it returns an "int"
in the example code, it uses "int c;" for the character
:|
in C a character you find in a string like "abc" is not necessarily the "char" data type, it could be a wide variety of types (especially for foreign languages)
if you see "char a;" ... don't think of it as saying 'a' is a character in a string
Uh-huh.. So does c typecast when it prints what's returned by fgetc()?
it's saying 'a' is a character of memory, which C simply defines as being 1 "byte" on the host hardware
you specified an implicit cast from int to char data types when you assigned the result of fgetc (an int) to c (a char)
I will rewrite the file opening and reading snippet.
Though the current error ((null) printing) seems to occur before any code changes I might have made..
you then test for c != EOF in the loop ... well EOF could be anything but it's typically "(int)-1"
there very well may be nulls getting printed elsewhere in the code, the two are not exclusive
I doubt that because a (null) gets printed everytime I press 'enter' after completing the in command
i mean those aren't the only issues in the function -- the "Script is: " printing at the end is also not right :)
why would you doubt that? that would only matter if you're assuming your describe function is all that's being called when you run the 'in' command and it most certainly is not
you'd have to read the 'in' command's implementation, trace through the logic to see where describe is called, confirm that is where it's really being called from (e.g., by adding a bu_log() line), then see what other logic or functions get called.
i mean those aren't the only issues in the function -- the "Script is: " printing at the end is also not right :)
Yea, I've scratched away all that. I'll go through typein.c to figure out where it's going wrong.
you'd have to read the 'in' command's implementation, trace through the logic to see where describe is called, confirm that is where it's really being called from (e.g., by adding a bu_log() line), then see what other logic or functions get called.
On it
you were super close with what you had ...
another approach would be to start with a function that does nothing -- maybe just prints hello
I doubt that because a (null) gets printed everytime I press 'enter' after completing the in command
@Jaipal Singh This error is because nvals in ged_in() is set as 2, whereas it should be 1 only.
Try setting it 1, at least this error should go away. There will be many more errors in the way. It'll take time to encounter those, so let's work a bit fast.
Hey @Shubham Rathore , yes changed nvals to 1 but I bump into a : Segmentation fault: 11 after I execute the in command.
ah, as expected, new error pops out. I don't have access to the code right now. You familiar with gdb ?
Not very, but I can figure it out! What do I need to do?
Okay, so gdb is a tool that helps to detect seg faults. We need to set -g flag while compiling using gcc.
In this case since we use make, All you need to do is make CFLAGS= -g
Then run gdb mged
Then type "run" , and try making a script object. The moment code breaks, it'll show the line, that is breaking the code
Do you use a mac ?
Yes, I do use a mac
Okay, so you need to use sudo before gdb mged
OK sure!
Otherwise you wont land where you want to
So keeping aside the runtime issues as of now. Do you have the code for decribe() ?
Yea, I had shared it with Sean yesterday, https://hastebin.com/awugozused.cpp, He pointed out a lot of changed but also hinted that I was fairly close to completion. I'll change this and share the updated code soon.
Ah fine, I'll have a look after my office hours. I have restricted access to hastebin :P
It raises the error : During startup program terminated with signal SIGTRAP
This appears to be an OSX issue. I'm fixing it right now..
Seems to be a security issue in Sierra. https://stackoverflow.com/a/40044913
Managed to avoid SIGTRAP by creating a .gdbinit file in my user folder.
Though this has given rise to a new error : During startup program terminated with signal ?, Unknown signal.
Did you use sudo ?
I have sierra, and it works well for me usually
Yes I did use sudo.
Even on the forums online it works for some and for the rest, raises the error that I'm encountering.
Let's not just waste time. Give it another try, if it works... good! otherwise work on the describe(), I'll try to figure it out by this evening.
in /build folder i did : make 'CFLAGS=-g'
then in /build/bin I did : sudo gdb ./mged followed by 'run'
yess.... it should work
(gdb) run Starting program: /Users/Troller/Documents/GSoC/18/brlcad/build/bin/mged [New Thread 0x1603 of process 74940] [New Thread 0x1903 of process 74940] During startup program terminated with signal ?, Unknown signal.
ah.. maybe try LLDB
runs on the same line as GDB
You'll have to handle the clang and gcc stuff ! :(
Sure, will try lldb. Working on the code for l describe now..
Screen-Shot-2018-07-24-at-5.51.12-PM.png It's not complete but I've hacked my way around printing the contents of a file using l describe. Currently I modified /librt/primitives/ell/ell.c to experiment.
I'm modifying typein.c to read the input file too, but that's not working very well for me. Should fix it in a while.
If I have
struct bu_vls x char a[256]
bu_vls_strcpy(*x, a) copies the contents of x to a?
If I want to copy the contents of a to x, how do I do it?
Okay, so you need to use sudo before gdb mged
er, no you don't :)
or... maybe you do -- is this a new security feature? I've not run into it yet with lldb
looking good @Jaipal Singh .. how about a link to the code changes (svn diff > mychanges.diff)
If I have
struct bu_vls x
char a[256]
bu_vls_strcpy(*x, a) copies the contents of x to a? If I want to copy the contents of a to x, how do I do it?
no, it doesn't. several issues -- first, you should initialize both on declaration (e.g., struct bu_vls x = BU_VLS_INIT_ZERO; char a[256] = {0};)
to copy from x to a, it would be bu_strlcpy(a, bu_vls_addr(&x), 256);
to copy from a to x, it would be bu_vls_strcpy(&x, a);
to copy from a to x, it would be bu_vls_strcpy(&x, a);
I'll work with this soon and keep you posted!
Okay, so you need to use sudo before gdb mged
er, no you don't :)
https://stackoverflow.com/questions/11504377/gdb-fails-with-unable-to-find-mach-task-port-for-process-id-error
@Sean Have a look. Not a new feature. All Os'es after snow leopard have this issue.
Screen-Shot-2018-07-24-at-5.51.12-PM.png It's not complete but I've hacked my way around printing the contents of a file using l describe. Currently I modified /librt/primitives/ell/ell.c to experiment.
well, seems to be a good attempt !
https://stackoverflow.com/questions/11504377/gdb-fails-with-unable-to-find-mach-task-port-for-process-id-error
@Sean Have a look. Not a new feature. All Os'es after snow leopard have this issue.
I read up on it a bit later. I guess I hadn't noticed because GDB was removed from XCode quite some time ago, after they switched to LLVM. I don't think lldb has that issue. Or, at least, I have been using it regularly without going sudo... unless my pending update from last week changes that! :)
well, seems to be a good attempt !
I agree, that looks good! Not far off of what I would expect "l" to show for a script object. You say you did that on the ell primitive? Or that you used ell as a guide for script?
Yea, I modified the ell primitive's l describe function. I'm using as a sandbox before I move the code to the script primitive. (Could've chosen any primitive to test, picked ell randomly)
I'm having a tough time copying a char array into a bu_vls. This the code I'm using to do the same : https://hastebin.com/anapelazez.php.
no, it doesn't. several issues -- first, you should initialize both on declaration (e.g., struct bu_vls x = BU_VLS_INIT_ZERO; char a[256] = {0};)
Doing this, raises the error :
brlcad/src/libged/typein.c:1513:27: expected expression eip->reference_path = BU_VLS_INIT_ZERO;
Okay so here is something I was thinking upon. What describe() does now is.... just print the file. @Jaipal Singh If you have explored the describe() function of other primitives then you would have found out that we get the primitive params on calling describe(). What we should exactly get here is ... the details of every primitive present in the script and there corresponding params. For ex. if you've made a tank through procedural scripts, then describe should mention all the primitives used here, be it an rcc or an sph etc. This is something to think over !
Nice recommendation @Shubham Rathore! I think something like this could and should be done.. If I were to do it from scratch, it would involve write a parser for our script and then based on calls to create individual objects in the script, we could indicate/print what primitives were used. This though I feel is a bigger project on it's own. There are numerous ways to go about doing it and given the multiple ways in which the scripts can be written, it becomes a very time intensive task. IMO
You'll have to handle the clang and gcc stuff ! :(
I still haven't managed to get the bedugger to work. Spent a couple of hours breaking my head on it and tried a few solutions (https://stackoverflow.com/questions/39702871/gdb-kind-of-doesnt-work-on-macos-sierra) but kept failing :(
You'll have to handle the clang and gcc stuff ! :(
I still haven't managed to get the bedugger to work. Spent a couple of hours breaking my head on it and tried a few solutions (https://stackoverflow.com/questions/39702871/gdb-kind-of-doesnt-work-on-macos-sierra) but kept failing :(
gdb and macos are a pain !
@Sean Why do you think typein.c saves the string but it doesn't reflect in src/librt/primitives/ell.c
@Sean could you also help me figure out why the script primitive that was stubbed keeps crashing? I have wasted enough time on trying to figure it out.
Also, our immediate goal (by the end of this week) should be to be able to invoke the python compiler from C and save the procedurally created geometry in our working database.
no, it doesn't. several issues -- first, you should initialize both on declaration (e.g., struct bu_vls x = BU_VLS_INIT_ZERO; char a[256] = {0};)
Doing this, raises the error :
brlcad/src/libged/typein.c:1513:27: expected expression
eip->reference_path = BU_VLS_INIT_ZERO;
What you have there is not initialization on declaration - it's after. BU_VLS_INIT_ZERO is where it's first declared. You'd need to use something like bu_vls_init() to initialize it later. In C/C++, there's different mechanisms for initializing memory.
I'm having a tough time copying a char array into a bu_vls. This the code I'm using to do the same : https://hastebin.com/anapelazez.php.
this actually looks about right if your cmd_argvs indices are correct other than the buffer copy seeming unnecessary
What we should exactly get here is ... the details of every primitive present in the script and there corresponding params. For ex. if you've made a tank through procedural scripts, then describe should mention all the primitives used here, be it an rcc or an sph etc. This is something to think over !
Actually, I think we can get away with not knowing what the script made or how objects were named or how they were structured. All that we need is to get a list of top objects and load them.
I still haven't managed to get the bedugger to work. Spent a couple of hours breaking my head on it and tried a few solutions (https://stackoverflow.com/questions/39702871/gdb-kind-of-doesnt-work-on-macos-sierra) but kept failing :(
Is there a reason you're not using lldb?
@Sean Why do you think typein.c saves the string but it doesn't reflect in src/librt/primitives/ell.c
This is likely because the string needs to be saved and restored in two of the other callbacks. The import5 and export5 callbacks read and write geometry objects respectively.
@Sean could you also help me figure out why the script primitive that was stubbed keeps crashing? I have wasted enough time on trying to figure it out.
Sure, post a diff of what you're trying and I'll take a look.
Also, our immediate goal (by the end of this week) should be to be able to invoke the python compiler from C and save the procedurally created geometry in our working database.
That sounds good. You'll want to use bu_temp_file() to create a file for you (see header declaration in include/bu dir for documentation on that function or search the code for some examples using it, which will get specified as an arg to the script. You can probably start with something as simple as popen() to invoke python on the script.
I still haven't managed to get the bedugger to work. Spent a couple of hours breaking my head on it and tried a few solutions (https://stackoverflow.com/questions/39702871/gdb-kind-of-doesnt-work-on-macos-sierra) but kept failing :(
Is there a reason you're not using lldb?
lldb gives - >
db_lookup(EZERO) failed: EZERO does not exist
db_string_to_path() of 'EZERO' failed on 'EZERO'
db_lookup(EZERO) failed: EZERO does not exist
that looks like straight up memory corruption. EZERO is probably from a PAGEZERO literal somewhere in random memory.
found the bug
bugs
@Jaipal Singh @Shubham Rathore on latest trunk (r71268), I fixed a couple bugs. the nvals value was off by one and the function signature wasn't right on script_in(). also the vls serialization in export5/import5 doesn't look right so I commented it out. left some !!! debugging code in there so you can see what's going on now, a simple substitute for debugging without a debugger.
yes, we figured out nvals a day before. Ah fine..
script_in was the big one ... stack corruption
cmd_argvs[0] ? shouldn't it be 3 ?
Screen-Shot-2018-07-26-at-4.32.46-PM.png
Need to give this thing some time
The import_5 function body looks standard like it is for almost all the other primitives. I don't see why db_i is becoming a Zero_Magic_Number.
The structure pointer fails to get validated.
Don't have access to the code, will look into it later today
But yes, it is identical, I did this previously for the annot primitive. I didn't find much of a difference. Will have to figure this out.
cmd_argvs[0] ? shouldn't it be 3 ?
Yes!
I still haven't managed to get the bedugger to work. Spent a couple of hours breaking my head on it and tried a few solutions (https://stackoverflow.com/questions/39702871/gdb-kind-of-doesnt-work-on-macos-sierra) but kept failing :(
Is there a reason you're not using lldb?
Started using it now!
cmd_argvs[0] ? shouldn't it be 3 ?
I didn't try to fix all of the problems, just got it working with some debugging so it's clear what's going on ;)
@Jaipal Singh you should add more logging or step through the debugger and look at the value of variables for the next step. the script_in function creates the initial object, that should be going to export5 next, followed by import5... you'll want to make sure each one is doing the right thing
saving out the vls string and then recreating it
Sure.
the reports are perfect, by the way
let me know if you can't figure out the vls serialization by tomorrow, let me know -- there's a good example in the dsp.c code
Thanks for the clues! I am genuinely distraught about not being able to copy and reference a string! Positively will finish by tomorrow!
In any rt_primitive_import5, when you set : BU_ASSERT(ep->ext_nbytes = X). How do you decide what is X? Is it the sum the sizes of all the variables present in that primitives struct rt_primitive_internal?
BTW the export function is fixed and is working fine. The import function is giving in some errors, that will be fixed soon.
Awesome! Thanks! What was the issue?
Ah.. some bu_vls related stuff ;)
I'll commit it soon, once import is fixed
Great. :D
In any rt_primitive_import5, when you set : BU_ASSERT(ep->ext_nbytes = X). How do you decide what is X? Is it the sum the sizes of all the variables present in that primitives struct rt_primitive_internal?
Look for the same assert line in ell.c and look for the params of ell in rt/geom.h . I think you'll find your answer. ;)
That's exactly what the hypothesis was based on :P
Thanks for the clues! I am genuinely distraught about not being able to copy and reference a string! Positively will finish by tomorrow!
Not a big deal if you can't figure it out -- I have in mind some other things we might want to pivot onto for the time remaining. This is definitely code that will need to be written, but there's also still more work on the Python side too.
I'll revert back if I can't get it to work in an hour from now.
Yes, eager for more work on the python side!
In any rt_primitive_import5, when you set : BU_ASSERT(ep->ext_nbytes = X). How do you decide what is X? Is it the sum the sizes of all the variables present in that primitives struct rt_primitive_internal?
also would note that "ep->ext_nbytes = X" would be an error... you probably mean ==
@Sean , in (src/librt/primitives/dsp/dsp.c) dsp_export5(), line 4510, we're copying dsp_ip->dsp_name to cp. Why do we do this? cp is a local var...
@Jaipal Singh of all the primitives in your spreadsheet, which ones aren't yet bound on the python side? wasn't that was supposed to be a column too? :)
/me looks
@Sean , in (src/librt/primitives/dsp/dsp.c) dsp_export5(), line 4510, we're copying dsp_ip->dsp_name to cp. Why do we do this? cp is a local var...
see line 4451 -- cp is a pointer to a byte buffer .. so printing into cp is printing into that buffer. we're writing the name of the dsp file/object into the buffer which is then written out to disk. note that it's written to cp after a bunch of other things are written into cp and the pointer is advanced forward by the number of bytes written. this is a low-level pointer.
Correct, I get how cp works. But then cp is lost after the function call is completed right?
@Jaipal Singh of all the primitives in your spreadsheet, which ones aren't yet bound on the python side? wasn't that was supposed to be a column too? :)
I made another sheet for the same IIRC. Let me find it, else will update the sheet on github in 5 min!
Yes! I had made a sheet (https://docs.google.com/spreadsheets/d/1XeeI1mpLlPFZtc7i5GeOmjLFE-s8JMsYpwVszIPsrmQ/edit?usp=sharing) but this was for when we were working with the TCL approach. I'll add a new column and update asap.
Correct, I get how cp works. But then cp is lost after the function call is completed right?
The cp pointer does go out of scope after the function call is completed, but nothing is "lost". The buffer memory it was pointing to is still wherever it was at and is accessible via the ext_buf in the bu_external object. I could just as well declare another pointer and set it to that address.
Uh-huh!
@Sean , what's the work on the python end you were talking about?
@Sean , what's the work on the python end you were talking about?
alright, so with the time left, I think we should focus on tidying up the python side more
we've gotten things started on the C side and can finish that up later, you got us a great to-do list (the spreadsheets) for things that need to be completed there
@Jaipal Singh on the python side, there are a handful of things needed but I think one of the most useful will be a python script that creates one of everything currently supported by the interface
maybe create a 'half' for ground, then organize a scene with all the primitives on top/above it
use can your creativity on how they're organized, maybe group them by general type or shape
alternatively, you could create one "scene" per primitive type, showing the variety of shapes that primitive can make -- like how an rcc cylinder can be short and fat like a disc, tall and skinny like a pencil, or deep like a bucket, etc
then all primitives could be tiled into a bigger scene for all of them
That should take you a couple days, from there I think we need to focus on documentation -- so maybe keep that in mind when creating the primitives code -- so that the code can serve as documentation of the primitives
last but not least, how about writing up a brief 1-page installation+run tutorial
The export function was fixed. I committed the code. AFA the import function is considered, it absolutely looks fine but gives ABORT trap 6 on running.
Tried a bu_log just at the beginning of the import func() and nothing is displayed on running. The control somehow is not entering the function.
@Sean Affirmative! I've got something to do for the entire week now. Will start off with the script to create all the primitives now and then move onto implementing half! :)
Make sure, you leave time for the documentation. That is something devs tend to ignore, but is actually something of great importance. We still struggle for documentation. Cheers !
Indeed :)
Tried a bu_log just at the beginning of the import func() and nothing is displayed on running. The control somehow is not entering the function.
thank you @Shubham Rathore ! excellent work. I'll take a look to see if I can spot what's wrong. likely a mismatch between import and export (they must match byte for byte)
and in the right byte ordering
@Sean FIXED !!
@Sean , @Shubham Rathore I'm almost done with the tutorial for making all the primitives. I've shared the link in the lastest report. Will fix a couple of broken things today. I made changes in some files and I haven't updated on of the tutorials (read report for more) .
After that I'll start work on the half primitive and the big scene! :)
@Shubham Rathore Awesome!
So, check for the lastest revision. Script object is created without any issue. @Jaipal Singh Once you are done with the python work that Sean told you to do, do try to incorporate the describe function that you tried by tweaking ell's func on the script. With only a few days to go, try to make things work faster. Cheers !
Yea sure! The major body of the describe function is ready, I'll just need to modify it to sit in the script primitive. Let me know if the examples look alright btw?
Had a glimpse of the examples, couldn't look at them in detail (stuck somewhere) . There seem to be some formatting issues on the first look. I'll look at them in detail soon and let you know !
@Jaipal Singh what work is there to do on the half primitive?
@Shubham Rathore excellent work, what was wrong?
The allocation for ep->ext_nbytes was a bit messy. :P
@Jaipal Singh what work is there to do on the half primitive?
Nothing major, will share the commit soon.
maybe create a 'half' for ground, then organize a scene with all the primitives on top/above it
Just not able to create the half for ground :P Screen-Shot-2018-07-31-at-7.53.20-PM.png
Does this scene look good?
Additionally I'll create scenes for individual primitives too.
alternatively, you could create one "scene" per primitive type, showing the variety of shapes that primitive can make -- like how an rcc cylinder can be short and fat like a disc, tall and skinny like a pencil, or deep like a bucket, etc
@Sean , I'm going to work on this now! Should be done in a day or two. The will move onto documentation.
@Shubham Rathore I just came to know about the mentor summit! Are you headed for it?
Also, do you get to take along a student with you? :P
maybe create a 'half' for ground, then organize a scene with all the primitives on top/above it
Just not able to create the half for ground :P Screen-Shot-2018-07-31-at-7.53.20-PM.png
So you managed to get the most of them... wish this was aesthetically more pleasing to see.
alternatively, you could create one "scene" per primitive type, showing the variety of shapes that primitive can make -- like how an rcc cylinder can be short and fat like a disc, tall and skinny like a pencil, or deep like a bucket, etc
@Sean , I'm going to work on this now! Should be done in a day or two. The will move onto documentation.
This shouldn't take time. Make this faster .
Ah! sorry it wasn't. I'll work on making it look better.
Hmm, ok.
@Shubham Rathore I just came to know about the mentor summit! Are you headed for it?
Limited slots! Lets see
Also, do you get to take along a student with you? :P
Sean would answer this better :P
Ah ok! [Fingers crossed]
Does this scene look good?
Additionally I'll create scenes for individual primitives too.
It looks like a good start .. they need to be organized in some meaningful manner ... they're not balanced in size, not on a horizontal plane (looks like they go vertically?), could use some color or lights to make it a showcase scene. Also, aren't there some missing? There are nearly 10 more on the spreadsheet listed as done, no?
Does this sort of grouping look alright? Screen-Shot-2018-08-01-at-12.18.21-PM.png
Yea, they're on a vertical place.
Have you included all of them ??
Looks like we are missing some objects
No, no, this is still in progress.
I'm asking about if this type of clustering is alright.
alternatively, you could create one "scene" per primitive type, showing the variety of shapes that primitive can make -- like how an rcc cylinder can be short and fat like a disc, tall and skinny like a pencil, or deep like a bucket, etc
Something like this.
Better than the last one !
@Sean will have more to say !
Cool.
I'm drawing a grip with the following attributes :
"grip.s",
center = (0, 5, 1),
normal = (1, 0, 0),
magnitude = 3,
It gets drawn alright, but when I try to render it, nothing renders. It doesn't say rt failed, it just shows a blank screen, any idea why this might be happening?
So, there's a few primitives like extrude, sketch, and a few more (will share the list) which I don't have an understanding of. Those are the ones missing from the scene that I had shared. It was also missing a few basic primitive like grip, superell and metaball which I've introduced now.
I will spend a little time to understand and implement the primitives that are new to me.
If you have any leads or good examples, please share. :)
Specifically examples of 'vol'.
Grip doesn't show in rt :P
Its absolutely normal !
So, there's a few primitives like extrude, sketch, and a few more (will share the list) which I don't have an understanding of. Those are the ones missing from the scene that I had shared. It was also missing a few basic primitive like grip, superell and metaball which I've introduced now.
Sketch, extrude aren't big things. Sketch doesn't raytrace again. Extrude is built on top of sketch. Have a read.
Yea, I've read through them. I'm just experimenting with including them in a scene..
https://docs.google.com/spreadsheets/d/1XeeI1mpLlPFZtc7i5GeOmjLFE-s8JMsYpwVszIPsrmQ/edit?usp=sharing
^Here's the primitives that can be created. I've introduced a column for those that I have not yet included in the scene with comments.
I'm asking about if this type of clustering is alright.
better! please keep them on a horizontal plane, though, so that the base of every primitive ends up at Z=0 (not centered at Z=0, the _base_ or lowest point at Z=0 ... )
Ok, sure, could do that
fyi, there are 3 or 4 other attempts at this you can check out with a search, e.g., https://www.google.com/search?q=brl-cad+primitives&safe=off&client=safari&rls=en&source=lnms&tbm=isch&sa=X&ved=2ahUKEwjona2rzs3cAhWLwFkKHXKrDSIQ_AUoAnoECAsQBA&biw=1494&bih=912
It gets drawn alright, but when I try to render it, nothing renders. It doesn't say rt failed, it just shows a blank screen, any idea why this might be happening?
grips don't have a visual representation -- they are controls for animating other geometry
Ah! The very image, was my sort of inspiration. I'll give the arrangement a little more attention now :)
Uh-huh
these may help with a few you're missing: http://brlcad.org/wiki/Sketch
http://brlcad.org/wiki/BRL-CAD_Primitives#ars
Yea, I've been using these only. Will finish off all the 2d derived primitives soon
http://brlcad.org/wiki/Extrude
Just wanted to know, how do you copy, paste in mged?
revolve is a lot like extrude, but simpler in a lot of ways as you don't need or want to define a closed loop, you just draw a 2D line or curve
Uh-huh
it depends on your platform, it's typically a system or X11 key binding
Got it! (ctrl+v and not cmd+v) :P
there's a basic 2D sketch editor in mged that you can use to create sketch objects for testing with extrude and revolve ... when you get them working, you can then figure out how to describe something similar in the python api
yeah, on mac, that's technically an X11 window -- so X11 bindings are ctrl by default
there is an native aqua version that uses cmd, but that's not readily available to you
Alright
@Sean , just curious, why not organize everything along the z-axis? Is it because it's not aesthetically pleasing?
(Something like this)[https://brlcad.org/gallery/var/resizes/diagrams/primitives.png]
you're welcome to, but it's a LOT harder to make it look aesthetically pleasing or have any organization in my experience -- that diagram you show wasn't modeled up the Z -- it would be quite hard to compose it that way
if it doesn't look good, it won't be looked at, and if it's not looked at, it won't be useful
on a horizontal plane, it becomes a landscape that is easily related with and will have optical effects that can be added to the scene like shadows, perspective, and environment mapping to make it look good
Aright! GG! :D
not the best example, but http://write.flossmanuals.net/contributors-guide-to-brl-cad/feature-overview/static/sflake2_cc.png
imagine all the primitives organized out in that checkerfield, casting nice shadows with ambient occlusion, maybe other effects
boring af: https://img1.cgtrader.com/items/31910/2e26f3ba8d/deluxe-primitives-3d-model-low-poly-obj.png
less boring: https://cdn.instructables.com/FZV/PQHS/IRXTUV78/FZVPQHSIRXTUV78.LARGE.jpg
pretty cool: http://www.renderography.com/wp-content/uploads/unit_primitives_examples.jpg
no good: http://brlcad.org/OLD/reports/arl-mr-103/images/figure_2.gif
can work tiled if all shapes (or sets of shapes) roughly fill the same area, e.g., https://cmkt-image-prd.global.ssl.fastly.net/0.1.0/ps/13124/580/386/m1/fpnw/wm0/3d_geometric_shapes_1-.png?1365485103&s=83e651804c9eae187fd3246775155dec
getting interesting: http://2.bp.blogspot.com/-rM0Yueq5t44/VXleslyHN4I/AAAAAAAABzc/56_gHGo2KT0/s1600/standard_primitives.jpg
@Jaipal Singh I hope all these examples would help you.... but don't forget to work on describe once you are done with the arrangements . Cheers !
Specifically examples of 'vol'.
You mean like http://brlcad.org/wiki/VOL ?
So, the sketch primitive doesn't work and is sort of hardcoded in the current python API. I'm working on fixing it, shouldn't take long. I guess this could be a priority before we create the bigger scene.
Specifically examples of 'vol'.
You mean like http://brlcad.org/wiki/VOL ?
Returns a 404
what's "doesn't work" mean?
Returns a 404
woah, wiki disappeared
Alright, from what I've gathered whoever wrote this code earlier, didn't complete the implementation of the script primitive.
If you look at https://github.com/Killthebug/python-brlcad/blob/efe542615971cd7fd88b41e83fc4d8b646364925/brlcad/geometry.py#L297. This is what is invoked when the user wants to create a sketch, but this doesn't take any input from the use, rather just accepts a sketch object. If you look at other functions in the file, they all take the params required to create their respective primitives.
Instead, to create a primitive, this function uses the default values that have been hard coded in the Sketch class. https://github.com/Killthebug/python-brlcad/blob/efe542615971cd7fd88b41e83fc4d8b646364925/brlcad/primitives/sketch.py#L366
I'm now modifying geometry.py to be able to accept user input and create the sketch.
wiki fixed
Thanks!
Alright, from what I've gathered whoever wrote this code earlier, didn't complete the implementation of the script primitive.
If you look at https://github.com/Killthebug/python-brlcad/blob/efe542615971cd7fd88b41e83fc4d8b646364925/brlcad/geometry.py#L297. This is what is invoked when the user wants to create a sketch, but this doesn't take any input from the use, rather just accepts a sketch object. If you look at other functions in the file, they all take the params required to create their respective primitives.
Either I'm not understand how to pass input to create a sketch object or this is genuinely wrongly implemented..
Alright, from what I've gathered whoever wrote this code earlier, didn't complete the implementation of the script primitive.
If you look at https://github.com/Killthebug/python-brlcad/blob/efe542615971cd7fd88b41e83fc4d8b646364925/brlcad/geometry.py#L297. This is what is invoked when the user wants to create a sketch, but this doesn't take any input from the use, rather just accepts a sketch object. If you look at other functions in the file, they all take the params required to create their respective primitives.
that's not how I read it -- sketch is nothing like the other primitives, so it's perfectly normal that it's construction would be different
it takes an arbitrary amount of data
would need to see how primitives.Sketch is implemented, but it otherwise looks like it could be complete at a glance
Instead, to create a primitive, this function uses the default values that have been hard coded in the Sketch class.
it only does that when the user didn't pass one
take a look at an example sketch: http://brlcad.org/wiki/Sketch
vertex list and a bunch of variadic sketch line types
In mged is it possible to save a certain POV? In the view option you have toggles for left, right, front, rear, etc. but is it possible to save a custom angle?
yes, depending on what you mean by saving a view
the 'ae' command will set an arbitrary azimuth/elevation (e.g., ae 35 25 or ae 45 65)
the saveview command will save the current view information out to a file, which can be read back with the loadview command later
there are several others too like setting based on a view direction or quaternion
the 'ae' command will set an arbitrary azimuth/elevation (e.g., ae 35 25 or ae 45 65)
Exactly what I was looking for!
@Jaipal Singh Hey what are you up to ? any leads with the sketch primitive ?
Hey @Shubham Rathore , I've been working on creating the scene with all the primitives. I've made multiple attempts in terms of arrangements, orientation, viewing angles and sizes. Finally I've been able to finalize on a particular design. I'm working on perfecting it and it should be completed in a few hours from now. Work on the sketch primitive has also progressed but it's not completed yet. I will shift focus onto it, once I'm done perfecting the scene.
I'm just stuck on getting the pipe made correctly, I have troubles figuring out the bend_radii.
Got it! xD
Just went through your report. The arrangement of the primitives is better than the previous ones. Regarding the sketch. Usually we use the gui but we can also create a sketch using put. This is what runs in the backend of the gui editor. All this shouldn't take much time ! Please try to wrap it up, we need to work on the describe as well plus the errors that we may encounter and the documentation part as well .
@Jaipal Singh are you aware of the final report submission with all the code links and the details of your work ? You need to submit this along with your final evaluation
and you'll need to separate your code from the code that was already there -- e.g., you can identify all your commits and extract them as a big patch file or pull them into a branch and tag them
you're basically required to submit all the code that you wrote, modified, removed, etc.
Sure! I could do that!
@Jaipal Singh are you aware of the final report submission with all the code links and the details of your work ? You need to submit this along with your final evaluation
Yea, I was notified via email yesterday.
Screen-Shot-2018-08-07-at-12.34.17-AM.png
This entire scene was created using :
https://github.com/Killthebug/python-brlcad/blob/master/Tutorial/scene.py
@Sean , @Shubham Rathore What do you think?
That's looking much better!
looks like a few issues, some primitives missing, some with undistinguished parameters, but looks like that'll set the stage (literally!)
mind if I share that image?
mind if I share that image?
Not at all! :D
looks like a few issues, some primitives missing, some with undistinguished parameters, but looks like that'll set the stage (literally!)
Yes, I'm missing sketch and other 2-d derived primitives. Also, not included in this scene are superell, ebm, submodel and grip. Though examples on how to implement them have been written in https://github.com/Killthebug/python-brlcad/blob/master/Tutorial/core_tutorial.py
core_tutorial.py is meant to act as a reference file for creating primitives using python brlcad.
What about the undistinguished parameters, are you referring to the arb7? (orange in top row)
Even the bot (bottom row pink) could use a better orientation, IMO
Oh yea, an rpp is also missing from the scene! :(
@Sean , @Shubham Rathore What do you think?
Looks great indeed !
Yeah, need to account for the missing primitives :P
On it!
What about the undistinguished parameters, are you referring to the arb7? (orange in top row)
arb7 is one of them, looks like an arb6. all of the arbs could use some rotation, like 20-50 degrees about Z so that we can see at least 2 sides of the arb4. green ehy(?) on second-from-top row looks like an arb6. green and red pointy cylinders -- (what are those?) look like rcc, too pointy. bot should be something more detailed (maybe teapot from the 'tea' command). and is the last red one in the corner an ars? something like the wiki example is needed, something more interesting than a wedge-looking shape.
missing I think are dsp, superell, sketch, extrude, revolve, ebm, vol? any others?
can just include the sample terrain from the 'terrain' tool for dsp, and wiki examples for sketch, extrude, ebm, and vol (maybe, it's nearly identical to ebm), just leaving superell and revolve and whatever else I missed from memory
missing I think are dsp, superell, sketch, extrude, revolve, ebm, vol? any others?
hrt !
Hey @Shubham Rathore , https://docs.google.com/spreadsheets/d/1XeeI1mpLlPFZtc7i5GeOmjLFE-s8JMsYpwVszIPsrmQ/edit?usp=sharing here's a list of primitives that are and are not a part of python brl-cad. IIRC, I had also shared this sheet ~10 days ago.
Please ignore the comments column in this sheet, it has not been updated
missing I think are dsp, superell, sketch, extrude, revolve, ebm, vol? any others?
hrt !
hrt is one of the primitives that I've not included. Few more are present in the sheet! :)
@Jaipal Singh Please update your daily logs
Yes!
And submit a patch with the describe function that you wrote... I'll try appending it to script
@Shubham Rathore https://hastebin.com/xiwohagonu.cpp . The file reading and writing out part works well, I was earlier having troubles saving and loading the filename in the import and export functions. Though all my attempts were before you had fixed it.
Also, for the last 2 days, I've been stuck on getting the sketch primitive to work, I'm able to create a script object with the points and vertices but am unable to get the curves created..
There's multiple ways in which the curves can be created as defined by the script primitive https://github.com/Killthebug/python-brlcad/blob/cd3ed94705933600f2a94f9e7ccde2e2ddd69497/brlcad/primitives/sketch.py#L408 . I
have figured out what the argument structure if for each of them, but I keep running into this error : https://hastebin.com/unapohiduq.coffeescript
I'll check in the evening and let you know !
Sure! Thanks :)
What about the undistinguished parameters, are you referring to the arb7? (orange in top row)
arb7 is one of them, looks like an arb6. all of the arbs could use some rotation, like 20-50 degrees about Z so that we can see at least 2 sides of the arb4. green ehy(?) on second-from-top row looks like an arb6. green and red pointy cylinders -- (what are those?) look like rcc, too pointy. bot should be something more detailed (maybe teapot from the 'tea' command). and is the last red one in the corner an ars? something like the wiki example is needed, something more interesting than a wedge-looking shape.
Rotating all the arb* to maximize viewing angle.
The green and red pointy cylinders are : rhc & rpc respectively. Inspired from the example at : (https://brlcad.org/gallery/diagrams/primitives)
Guys, I'm still stuck on the error that I had shared earlier ( https://hastebin.com/unapohiduq.coffeescript), could you please have a look and see if you can give any leads..
genptr_t
is "generic pointer type", which appears to have been deprecated in 7.16, and replaced with void *
https://github.com/kanzure/python-brlcad/blob/master/brlcad/primitives/sketch.py#L473
c_void_p
is what you're looking for, like on that line
have figured out what the argument structure if for each of them, but I keep running into this error : https://hastebin.com/unapohiduq.coffeescript
@Jaipal Singh it looks like the ctypesgen interface is out of sync with the C code. there are no longer genptr_t types anywhere. they were all converted to void* ... not sure what that means for you on the python side, but it's something wrong in the python binding
The green and red pointy cylinders are : rhc & rpc respectively. Inspired from the example at : (https://brlcad.org/gallery/diagrams/primitives)
That's not possible, rhc/rpc are the second row, green and fleshtone on the left (and the rhc is too pointy). I'd believe the gray and green next to it are epa and ehy, but again one of them is way too pointy -- looks like a trc. and if they are, that leaves a mystery for the red one in the 5th bottom row on the left.
thanks @Cezar ! looks spot on
Guys, I'm still stuck on the error that I had shared earlier ( https://hastebin.com/unapohiduq.coffeescript), could you please have a look and see if you can give any leads..
Cezar stands correct.
@Shubham Rathore https://hastebin.com/xiwohagonu.cpp . The file reading and writing out part works well, I was earlier having troubles saving and loading the filename in the import and export functions. Though all my attempts were before you had fixed it.
This should work now. I'll give it a try this evening
c_void_p
is what you're looking for, like on that line
This seemed to have solved that error, but I've run into many more after it.
@Sean , @Shubham Rathore There are a lot of incomplete functions in the sketch primitive api and these are not pythonic errors, rather it's not been tested in the first place when it was created. There are no tests or examples for the sketch primitive and all the code is without any sort of comments for direction.
The issue arises in creating the curves in a sketch. There are a lot of helper functions involved that seem to be acting together. If I fix one, I break the other and the cycle seems to continue.
I'm going to devote one more day to else I will re-write the entire binding on my own. The current binding might also be working but I just can't wrap my head around it.
I will soon share the primitive scene with the requested changes and we can work on perfecting that. Along with it, I will try and get the describe function for the script primitive working because I had spent a fair amount of time on it as well earlier (before @Shubham Rathore had fixed it).
genptr_t
is "generic pointer type", which appears to have been deprecated in 7.16, and replaced withvoid *
@Cezar Thanks a ton for this. I knew something was deprecated but I didn't have a clue what it was. :)
If you can make straight lines, how about just making an example using that, like a tessellated ‘S’ sketch with like 20 line segments? Then use that with extrude. Can leave a fixme in the code for curves.
Otherwise sounds look or a plan.. just please leave yourself a day to write up a summary report with images to post somewhere, showcase everything you did blogpost style. :)
@Sean , @Shubham Rathore There are a lot of incomplete functions in the sketch primitive api and these are not pythonic errors, rather it's not been tested in the first place when it was created. There are no tests or examples for the sketch primitive and all the code is without any sort of comments for direction.
I know how it feels. Don't worry we'll fix it. Don't get stuck on this, move on with the reports and the documentation.
Screen-Shot-2018-08-10-at-2.54.28-PM.png
@Shubham Rathore The describe function works :)
BTW, some of the c-code that you're seeing that has been logged was present in the new.py file :P
There are a small hack and a minor change that I had to put in place. It doesn't break anything, but it has to be fixed in the export function. I'll share the diff soon and point out in that.
I dont exactly get it.... Will you please share the code, I'll go through it
What exactly is the issue that you are facing with the buffer (ep->extbytes) ?
@Shubham Rathore , sending patch.
@Sean , @Shubham Rathore Here's a basic blog post on how to work with python brlcad, do have a look and let me know what you think? :D
https://medium.com/@Mr_Jaypee/990e3c286a63
@Shubham Rathore ^ Here's the diff file.
Daily logs updated :)
this is looking good @Jaipal Singh ! I like the overview of procedural geometry. would it make sense to say more about "Approach 2"?
you introduce it but then jump back to all the detail on Approach 1. reads a little confusing. I would suggest either explaining the downsides of Approach 2 and why Approach 1 was developed further, giving you the lead into the next section. also, suggest removing the three 'wdb' references (maybe just call them geometry) since we don't want to have to explain it. also, don't really need "brl_" prefix -- db works great and is easier to understand. it would be good to end the article with a mention of where there are more docs -- you mention the github repo, so maybe just say see comments in the code or point them to a specific file or something similar.
minor point, but it would be good to update all the BRLCAD to BRL-CAD for consistency
nice write-up regardless. did we give up on a straight-edge sketch/extrude/revolve?
Done!
nice write-up regardless. did we give up on a straight-edge sketch/extrude/revolve?
Yea, for now :/
Even the straight edge (line), depends on the curve class, which itself seems to be causing all the trouble
Awesome @Jaipal Singh !
Ill look into it by the evening !
Some issues with the buffer that need to be rectified..
Last updated: Nov 15 2024 at 00:49 UTC