Hi Sean!

Thank you a lot for the details. The visualization of Voronoi points was
really helpful. I think I understand your vision and will work on
implementing the first steps as soon as the stuff I mention below is done.

I'm running into some trouble with my code. I need to call
readDensityValues() (user input through stdin) but I don't know exactly
where I should place the call.
Placing it into view_init, view_2init, application_init or view_setup
breaks it: buffer doesn't behave correctly. My exit command isn't
recognized anymore, and when I Crtl-C, it runs the while loop two more
times (printing usage) before shutting off. It feels like there are many
threads running at once and interfering with each other. Might this be the
case?
I'm afraid I cannot deliver functioning code today, but if we solve this
problem I will be able to do so tomorrow. For now here goes the not-working
state.

Next steps:
-> store the points into a file (instead of sharing a memory pointer)
-> make the point input procedure a separate program, or ask the user at
the start of rtweight execution if he wants to create/override the point
list.
    Maybe this can solve the problem mentioned in the above paragraphs. How
do you think we should do it?

I also want to mention that the during the next three weeks I will have a
little bit more restricted available time (as I mentioned in my
application). I will steadily advance, but it might feel a little bit
slower than up to now.

PD. What you mean with 'patch' is the result of running svn diff into a
file? If so, here it goes!

Mario.


2017-08-09 7:58 GMT+02:00 Christopher Sean Morrison <brl...@mac.com>:

>
> Fair enough. My next goal will be to make our initial minimal feature
> working. In this case this means having a way to let the user define points
> that will be used for query_density(), instead of hardcoding them. I guess
> for now I will use the .density file as I have no idea how the whole
> "material objects" thing should work, yet.
>
>
> If you have a specific idea/plan in mind, I’d love to hear it.  However, I
> can’t really envision a good way to extend the tabular .density file format
> with the information you need without introducing a problem.
>
> Two options that come to mind would be to modify rtweight to take a
> secondary input file (temporary) or implement a material object stub that
> has what you need (more complicated, but in the right direction) [1].  For
> time, I think the second option is the way to go given the time remaining
> and that’ll keep you directly working with the rtweight sources.
>
> [1] http://brlcad.org/wiki/Material_and_Shader_Objects
>
> I guess it's up to you to decide what I should focus on. I could work on
> the basics of this new approach so that future work on it can then build on
> it and eventually finish it, but that would mean quite a change to what our
> initial goal for the socis period was. I'm totally fine with either way.
>
>
> If we knowingly plan to extend the current materialID system to later
> point to an object, then you’ll just have to make sure whatever you read in
> from file fits that mental model.  Directly modifying rtweight to take a
> second specification file will more easily allow for testing N-point cases,
> so we’ll just have to be careful it can easily translate into an object.
>
> I think this [checking if there are overlapping points] can also be
>> handled by changing the way vectors are being defined (or perhaps what they
>> mean). Instead of having a concept of origins and detachment of point
>> densities, let density_vector actually refer to a density_point and let the
>> other struct fields encode the nature of the contribution (effectively
>> combining your struct combination data into one concept).
>>
>
> I'm afraid I'm not following you here. Could you detail this out a bit
> more? The referenced density_point would be the origin of the vector? (if
> not, what is it?).
>
>
> No, at least not necessarily.  Density points would be simply a density
> specification at a specific point in space.  How that value is interpreted
> or used nearby would be a separate concept (and handled in code in a
> separate struct).  In fact, it becomes possible to define reasonable
> behavior without any vector information.
>
> Consider two side by side boxes (with a gap between them) that are in the
> same region.  Under the current system, there’s a materialID=3 which maps
> to a density of 7.75 g/cm^3.  If I specified a density point somewhere in
> one of the boxes as being 8.05 g/cm^3, I would intuitively expect that to
> be the density of that box (and only that box).  No falloff, no smooth
> transition to 7.75, no override of the universe to 8.05.
>
> How to achieve that in code is going to be really tricky for concave
> shapes, but I think it’s the simplest and most natural behavior a user
> would expect.  (keep the simple easy)
>
> The 'nature' of the contribution would be something like rate: linear,
> quadratic, etc.?
>
>
> It’s only once we add a second point or define a transition vector (which
> implicitly entails two points) that we have to care about this, but
> essentially yes.
>
> And how does this change help us check if there are overlapping points?
>
>
> So again consider defining points but not defining vectors.  If we have
> one box and define two density points in the box, that is the density at
> those points.  Defining the same point as having two separate densities
> would be a definition error.  Separate them by any meaningful distance and
> we’ve effectively defined a density “binds" that maps well to a Voronoi
> tessellation of space, like this:
>
> http://alexbeutel.com/webgl/voronoi.html
>
> With that conceptualization, adding in vectors from one point to another
> merely changes the space definition to being a continuous smooth transition
> between pairs of points.  Make sense?  That becomes a fully generalize
> solution that should capture nearly any material definition while keeping
> the simple easy, and complex possible.
>
> From the rest of the answers in your emails I think I got the idea that
> you want to let the user specify both points and vectors as if they were
> two means of describing density. Then a vector should be something like a
> superset of the point, where we can specify some more information about it
> to
>
> describe the continuous transition between the two points the vector spans.
>
>
> I think you got it.  More specifically, vectors augment/extend the limited
> info of a density point, describing how it transitions out from a point.
>
> Don't we need to reference two density_points then?
>
>
> Either as two points (origin pt1 to destination pt2 with an implicit dir)
> or as one point and a direction vector, not unitized (so adding pt1+dir
> gives pt2).  Either should work fine.
>
> Doesn't this method depend too much on the direction from which the rays
> come? For example, ptA could be really far from 'IN' if you shoot from
> above but really close to it if you shoot from the side. If ptA was the
> heaviest point, then shooting from above will turn a huge part of the
> material into really heavy, and shooting from the side should weight much
> less. I'm not sure if I'm talking nonsense here, I'll check with an actual
> example to see it working, but this was my first thought when I saw it.
>
>
> Hopefully the Voronoi webgl demo helps clear that up.  There was only
> weighting when we were assuming linear interpolation or vectors to/from all
> points.  Using the Voronoi /  halfspace approach is direction invariant.
>
> For now I'll make my code fully 'complete', as you mention. Then I will
> get rid of my 'origins' and make projections onto the shotline (but this
> will require some more discussions as I'm not 100% sure how this would all
> work and fit together, especially points with no vectors [the question
> above]). At some point in the future we will need to take the distance to
> the shotline into consideration to make a 'fair' average of contributions,
> as you suggested.
>
>
> It’s also okay if you need to move back to rtexample to prove the concept
> first.  It’s when the feature is introduced into a production facility that
> it should be done “complete”, one bit at a time.
>
> For what it’s worth, projecting onto the shotline is probably only going
> to work on convex geometry.  For concave shapes, it’s a bit more complex to
> know where a given density point applies.  It’s certainly resolvable with
> the neighboring ray information (because they represent a
> quasi-voxelization of space).
>
> Cheers!
> Sean
>
>
> ------------------------------------------------------------
> ------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> BRL-CAD Developer mailing list
> brlcad-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/brlcad-devel
>
>
Index: src/rt/viewweight.c
===================================================================
--- src/rt/viewweight.c (revisi¾n: 70059)
+++ src/rt/viewweight.c (copia de trabajo)
@@ -59,26 +59,27 @@
 
 const char title[] = "RT Weight";
 
-void
-usage(const char *argv0)
-{
-    bu_log("Usage: %s [options] model.g objects...\n", argv0);
-    bu_log("Options:\n");
-    bu_log(" -s #              Grid size in pixels, default 512\n");
-    bu_log(" -g #              Grid cell width [and height] in mm\n");
-    bu_log(" -G #              Grid cell height [and width] in mm\n");
-    bu_log(" -a Az             Azimuth in degrees\n");
-    bu_log(" -e Elev   Elevation in degrees\n");
-    bu_log(" -o file.out       Weights and Moments output file\n");
-    bu_log(" -M                Read matrix, cmds on stdin\n");
-    bu_log(" -r                Report verbosely mass of each region\n");
-    bu_log(" -x #              Set librt debug flags\n");
-    bu_log("Files:\n");
-    bu_log(" .density, OR\n");
-    bu_log(" $HOME/.density\n");
-}
+struct density_point {
+       struct bu_list l;
+       point_t point;
+       fastf_t density;
+};
 
+struct density_vector {
+       struct bu_list l;
+       vect_t vector;
+       //point_t origin; We may not need if we assume all vectors originate 
from the first point provided
+       fastf_t factor;
+};
 
+struct contribution {
+       struct bu_list l;
+       fastf_t contrib;
+       struct density_vector * dvp;
+};
+
+struct density_vector * dvlist;
+struct density_point * origin; //I WILL GET RID OF THIS REAL SOON
 int noverlaps = 0;
 FILE *densityfp;
 char *densityfile;
@@ -108,7 +109,140 @@
 extern char *outputfile;       /* name of base of output file */
 extern int output_is_binary;   /* !0 means output is binary */
 
+struct density_vector *
+vector_init(struct density_point * dplist)
+{
+       /* When no points provided we use this as fallback value */
+       fastf_t DEFAULT_DENSITY = 8.0;
 
+       /* Set up density_vector list */
+       struct density_vector * new_dvlist;
+       BU_GET(new_dvlist, struct density_vector);
+       BU_LIST_INIT(&(dvlist->l));
+
+       BU_GET(origin, struct density_point);
+
+       /* If point list is empty, no points, we assume homogeneous default 
density.
+       I set the origin point to default in this case. */
+       if (BU_LIST_IS_EMPTY(&(dplist->l))) {
+               origin->density = DEFAULT_DENSITY;
+               VSETALL(origin->point, 0.0);
+               /* dvlist will remain empty */
+       }
+       else {
+               /* If there is at least one point, take first point and make it 
origin. */
+               BU_LIST_POP(density_point, &(dplist->l), origin);
+
+               /* While there are still points, draw a vector from origin to 
point
+               and store it in list. */
+               struct density_vector * new_vect;
+               struct density_point * point_iter;
+               while (BU_LIST_WHILE(point_iter, density_point, &(dplist->l))) {
+                       BU_GET(new_vect, struct density_vector);
+                       VSUB2(new_vect->vector, point_iter->point, 
origin->point);
+                       new_vect->factor = point_iter->density / 
origin->density;
+                       BU_LIST_PUSH(&(new_dvlist->l), new_vect);
+                       BU_LIST_DEQUEUE(&(point_iter->l));
+               }
+       }
+
+       return new_dvlist;
+
+}
+
+/**
+* Returns the density value in g/mm3 at the point given. 
+* For now vectors are being recalculated every time, big impact on 
performance. 
+* We should store them as they are static. We can reuse them for any query on 
the 
+* same material.
+*/
+fastf_t
+query_density(point_t query_point)
+{
+       /* We draw the vector corresponding to the queried point */
+       vect_t query_vector;
+       VSUB2(query_vector, query_point, origin->point);
+
+       /* After this, we will always have at least one point, origin.
+       If no more points are present, we use this point's value for
+       homogeneous density. */
+       if (BU_LIST_IS_EMPTY(&(dvlist->l))) {
+               return origin->density;
+       }
+       else {
+
+               /* We now dequeue our vector list and fill in the array of 
projection values */
+
+               vect_t paral_projection; //I need this so VPROJECT doesn't 
complain?
+               vect_t orth_projection; //Orthogonally projected query_vector 
onto density_vectors
+
+               /* Set up contribution lists */
+               struct contribution * contrib_list;
+               BU_GET(contrib_list, struct contribution);
+               BU_LIST_INIT(&(contrib_list->l));
+
+               /* Variables for the loop */
+               struct density_vector * vect_iter;
+               struct contribution * new_contrib;
+               fastf_t contrib, scalar_proj, proportion;
+
+               /* Loop through vectors and build contribution list */
+               for (BU_LIST_FOR(vect_iter, density_vector, &(dvlist->l))) {
+                       VPROJECT(query_vector, vect_iter->vector, 
orth_projection, paral_projection);
+                       scalar_proj = MAGNITUDE(orth_projection);
+                       proportion = scalar_proj / MAGNITUDE(vect_iter->vector);
+                       BU_GET(new_contrib, struct contribution);
+                       /* In 'scalar_proj' proportion, our contribution value 
will be the density of dv,
+                       which is original * factor. The 'rest' is original 
density */
+                       contrib = origin->density * vect_iter->factor * 
proportion +
+                               origin->density * (1 - proportion);
+                       new_contrib->contrib = contrib;
+                       new_contrib->dvp = vect_iter;
+                       BU_LIST_PUSH(&(contrib_list->l), new_contrib);
+               }
+
+
+               /* Now go through contributions and do work on it
+               For now take average */
+               struct contribution * contrib_iter;
+               fastf_t acc_contrib = 0.0; //Accumulated contributions (total)
+               int numContribs = bu_list_len(&(contrib_list->l)); //Amount of 
entries
+               while (BU_LIST_WHILE(contrib_iter, contribution, 
&(contrib_list->l))) {
+                       acc_contrib += contrib_iter->contrib;
+                       BU_LIST_DEQUEUE(&(contrib_iter->l));
+               };
+
+               /*DEBUG
+               VPRINT("query_vector", query_vector);
+               VPRINT("orth_proj", vector_orth_proj);
+               bu_log("scalar_proj is %lf \n", scalar_proj);
+               bu_log("proportion is %lf \n", proportion);
+               */
+
+               return acc_contrib / numContribs;
+       }
+}
+
+void
+usage(const char *argv0)
+{
+       bu_log("Usage: %s [options] model.g objects...\n", argv0);
+       bu_log("Options:\n");
+       bu_log(" -s #           Grid size in pixels, default 512\n");
+       bu_log(" -g #           Grid cell width [and height] in mm\n");
+       bu_log(" -G #           Grid cell height [and width] in mm\n");
+       bu_log(" -a Az          Azimuth in degrees\n");
+       bu_log(" -e Elev        Elevation in degrees\n");
+       bu_log(" -o file.out    Weights and Moments output file\n");
+       bu_log(" -M             Read matrix, cmds on stdin\n");
+       bu_log(" -r             Report verbosely mass of each region\n");
+       bu_log(" -x #           Set librt debug flags\n");
+       bu_log("Files:\n");
+       bu_log(" .density, OR\n");
+       bu_log(" $HOME/.density\n");
+}
+
+
 static int
 hit(struct application *ap, struct partition *PartHeadp, struct seg 
*UNUSED(segp))
 {
@@ -153,24 +287,36 @@
        }
 
        {
-           /* precompute partition size */
-           const fastf_t partition_volume = depth * cell_height * cell_width / 
(hypersample + 1);
+               /* precompute partition size */
+               const fastf_t partition_volume = depth * cell_height * 
cell_width / (hypersample + 1);
 
-           /* convert reg_los percentage to factor */
-           const fastf_t los_factor = (fastf_t)reg->reg_los * 0.01;
+               /* convert reg_los percentage to factor */
+               const fastf_t los_factor = (fastf_t)reg->reg_los * 0.01;
 
-           dp->volume = partition_volume;
-           VBLEND2(dp->centroid, 0.5, ihitp->hit_point, 0.5, ohitp->hit_point);
+               dp->volume = partition_volume;
+               VBLEND2(dp->centroid, 0.5, ihitp->hit_point, 0.5, 
ohitp->hit_point);
 
+               /* Old code: 
            if (density[reg->reg_gmater] >= 0) {
-               /* density needs to be converted from g/cm^3 to g/mm^3 */
+               //density needs to be converted from g/cm^3 to g/mm^3
                const fastf_t density_factor = density[reg->reg_gmater] * 0.001;
 
+               //Compute mass in terms of grams
+               dp->weight = partition_volume * los_factor * density_factor;
+               */ 
+
+               /* For now we will hardcode the vectors that define our box 
inside the
+               query_density function. Thus, for now this example only works 
if we load
+               exactly the required box. */
+               fastf_t inhit_density = query_density(ihitp->hit_point);
+               fastf_t outhit_density = query_density(ohitp->hit_point);
+               fastf_t avg_density = (inhit_density + outhit_density) / 2;
+
                /* Compute mass in terms of grams */
-               dp->weight = partition_volume * los_factor * density_factor;
+               dp->weight = partition_volume * los_factor * avg_density;
+
            }
        }
-    }
     return 1;  /* report hit to main routine */
 }
 
@@ -199,6 +345,22 @@
 int
 view_init(struct application *ap, char *UNUSED(file), char *UNUSED(obj), int 
minus_o, int UNUSED(minus_F))
 {
+       
+       /* BEGIN MODIFICATION */
+
+       /* Here we should read from new file, but using memory pointer for now 
*/
+       /* Assuming only one material for now */
+       struct density_point * dplist;
+
+       BU_GET(dplist, struct density_point);
+       BU_LIST_INIT(&(dplist->l));
+       readDensityPoints(dplist);
+
+       /* Store pointer into global variable so that every hit call has access 
to it */
+       dvlist = vector_init(dplist);
+
+       /* END MODIFICATION */
+
     register size_t i;
     char buf[BUFSIZ+1];
     char linebuf[BUFSIZ+1];
@@ -307,6 +469,8 @@
     for (BU_LIST_FOR(rp, region, &(rtip->HeadRegion))) {
        rp->reg_udata = (void *)NULL;
     }
+
+       
 }
 
 
@@ -593,6 +757,7 @@
 void
 view_setup(struct rt_i *UNUSED(rtip))
 {
+       
 }
 
 
@@ -606,9 +771,75 @@
 void
 application_init(void)
 {
+       
 }
 
+/*
+Reads density points from stdin and stores them into density_point structs
+Receives the head of a bu_list of density_point structs
+and appends all points generated during the reading session to the list
+Returns the number of successfully read points
+*/
+int readDensityPoints(struct density_point * dplist_head) {
 
+       /* If we are given no bu_list... */
+       if (!BU_LIST_IS_INITIALIZED(&(dplist_head->l))) {
+               bu_log("No valid head of bu_list has been provided.\n");
+               /* Maybe also check if bu_list is of type density_points? */
+       }
+
+       /* Local variables */
+
+       /* I count the number of times I */
+       int count = 0;
+       struct density_point *entry;
+       int correct;
+    int reading = 1;
+       char input[30];
+
+       /* Outer loop. We come back here whenever user inputs wrong format and 
until he types exit */
+       while (reading) {
+               bu_log("Please insert density points in the format: X Y Z 
density_value (in g/cm3). \n");
+               bu_log("Type 'exit' to finish. \n");
+               correct = 1;
+               int c;
+               /* Inner loop. While user inputs points in correct format we 
loop here */
+               while (correct) {
+
+                       if (bu_fgets(input, 30, stdin) == NULL) {
+                               puts("bu_fgets error");
+                       }
+                       //gets(input); 
+                       //while ((c = getchar()) != '\n' && c != EOF) {} 
//Clean buffer
+                       /* If user typed exit we need to exit both loops */
+                       if (!strcmp(input, "exit\n")) {
+                               bu_log("Exiting...");
+                               correct = 0;
+                               reading = 0;
+                       }
+
+                       /* User didn't type exit */
+                       else {
+
+                               /* Set up new entry */
+                               BU_GET(entry, struct density_point);
+
+                               /* If the input is in correct format we load it 
and continue */
+                               if (sscanf(input, "%lf %lf %lf %lf", 
&entry->point[0], &entry->point[1], &entry->point[2], &entry->density) == 4) {
+                                       BU_LIST_PUSH(&(dplist_head->l), 
&(entry->l));
+                                       count++;
+                               }
+
+                               /* Otherwise we dont load it and jump back to 
outer loop to print usage again */
+                               else {
+                                       correct = 0;
+                               }
+                       }
+               } /* Close inner loop */
+       } /* Close outer loop */
+       return count;
+} /* Close function */
+
 /*
  * Local Variables:
  * mode: C
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
BRL-CAD Developer mailing list
brlcad-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/brlcad-devel

Reply via email to