Hello!
Mass being 0 all the time was because the reg_los of my region was 0 for
whatever reason. Hard-coding a reg_los of 100 (and thus a 'factor' of 1)
works and I now get a mass value (however unfortunately not the value I
expect, yet). Attached goes code. Any hints on why the reg->reg_los isn't
set correctly?
When and where is it computed? Also, what is it's meaning exactly? I know
it should be something like 'amount of the region actually filled with the
material' or something, but I don't really understand it yet.
I'll work on figuring out why the numbers don't fit expectations.
Mario.
On 21 September 2017 at 18:42, Vasco Alexandre da Silva Costa <
vasco.co...@gmail.com> wrote:
> BTW, do you have a Chinese OS version? Your diff files contain Chinese
>> comments.
>>
>
> Because Japanese uses Kanji (Chinese characters) sometimes it becomes hard
> to tell the two languages apart. But in this case you can see some Katakana
> in there so it's clearly Japanese.
> https://en.wikipedia.org/wiki/Katakana
>
> --
> Vasco Alexandre da Silva Costa
> PhD in Computer Engineering (Computer Graphics)
> Instituto Superior Técnico/University of Lisbon, Portugal
>
> ------------------------------------------------------------
> ------------------
> 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 (リビジョン 70327)
+++ src/rt/viewweight.c (作業コピー)
@@ -48,7 +48,32 @@
#include "./rtuif.h"
#include "./ext.h"
+fastf_t MARGIN = 0.0001;
+struct density_point {
+ struct bu_list l;
+ point_t point;
+ fastf_t density;
+};
+struct projection {
+ //If we store the density here again we might not need the original
+ //fastf_t density;
+ struct density_point * original;
+ point_t point;
+ vect_t vect;
+ fastf_t inhit_dist;
+ fastf_t prev_dist;
+ fastf_t origin_dist;
+};
+
+struct intersection_t {
+ int intersect;
+ point_t intersection_point;
+};
+
+struct density_point * user_plist;
+const int MAX_POINTS = 99;
+
extern struct resource resource[];
/* Viewing module specific "set" variables */
@@ -59,6 +84,281 @@
const char title[] = "RT Weight";
+int compare_dpoints(const void *, const void *);
+void compute_intersection(struct intersection_t * , point_t, point_t, point_t,
vect_t);
+/*
+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
+read_density_points(struct density_point * dplist_head)
+{
+
+ /* If we are given no proper bu_lists ... */
+ if (!BU_LIST_IS_INITIALIZED(&(dplist_head->l))) {
+ bu_log("No valid heads of bu_list has been provided.\n");
+ /* Maybe also check if bu_list is of correct type? */
+ }
+
+ /* Local variables */
+ int count = 0;
+ struct density_point * entry;
+ int correct;
+ int reading = 1;
+ char input[30];
+ struct density_point * entries[99]; //Hardcoded max for now
+
+
/* 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:");
+ bu_log(" X Y Z density_value(in g / cm3). \n");
+ bu_log("Type 'exit' to finish. \n");
+ correct = 1;
+
+ /* Inner loop. While user inputs points in correct format we
loop here */
+ while (correct) {
+ bu_fgets(input, 30, stdin);
+ /* If user typed continue we need to exit both loops */
+ if (!strcmp(input, "exit\r")) {
+ bu_log("Finished inserting points.\n");
+ correct = 0;
+ reading = 0;
+ }
+
+ /* User didn't type continue */
+ 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));
+ entries[count] = entry;
+ 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;
+}
+
+/* Receives a segment and returns average density
+Uses memory pointer to user point list */
+fastf_t segment_density(point_t inhit, point_t outhit) {
+
+ /* If no user points available it means either no mass or default
density.
+ I will display a message indicating no points are defined so no mass*/
+ if (BU_LIST_IS_EMPTY(&(user_plist->l))) {
+ bu_log("No points available, thus object has no mass.\n");
+ return 0;
+ }
+
+ /* DEBUG */
+ //VPRINT("inhit", inhit);
+ //VPRINT("outhit", outhit);
+
+ /* Segment vector (for projections) */
+ vect_t segment_vect;
+ VSUB2(segment_vect, outhit, inhit);
+ fastf_t total_segment_len = MAGNITUDE(segment_vect);
+
+ /* Projections Loop prep */
+ struct projection * new_projection;
+ struct density_point * dpoint_iter_ext; //External
+ struct density_point * dpoint_iter_mid; //Middle
+ struct density_point * dpoint_iter_int; //Internal
+ vect_t dpoint_vect;
+ vect_t prev_to_current_vect;
+ vect_t proj_to_original_vect;
+ vect_t temp;
+ vect_t paral_projection; //I need this to VPROJECT doesn't complain?
+ int array_pointer = 0;
+ int is_valid;
+ /* Bu_calloc has given me some problems, so temporary hardcoded max */
+ /* FIXME: I should be allocating space dynamically */
+ struct projection * proj_array[99];
+
+ /* Loop through points and project them onto segment if they need to be
*/
+ for (BU_LIST_FOR(dpoint_iter_ext, density_point, &(user_plist->l))) {
+ is_valid = 1;
+ BU_GET(new_projection, struct projection);
+ /* Create userpoint vector */
+ VSUB2(dpoint_vect, dpoint_iter_ext->point, inhit);
+ new_projection->original = dpoint_iter_ext;
+ /* Project vector onto segment */
+ VPROJECT(dpoint_vect, segment_vect,
+ new_projection->vect, paral_projection);
+ /* Compute absolute point of projection */
+ VADD2(new_projection->point, new_projection->vect, inhit);
+ new_projection->inhit_dist = MAGNITUDE(new_projection->vect);
+ //bu_log("inhit_dist: %lf \n", new_projection->inhit_dist);
+ /* Compute distance to original */
+ VSUB2(proj_to_original_vect, dpoint_iter_ext->point,
new_projection->point);
+ new_projection->origin_dist = MAGNITUDE(proj_to_original_vect);
+
+ /* Check if we need to project or not based on distance to all
other points */
+ for (BU_LIST_FOR(dpoint_iter_mid, density_point,
&(user_plist->l))) {
+ VSUB2(temp, new_projection->point,
dpoint_iter_mid->point);
+ /* If distance to some user point is shorter than to
the origin then we need to check boundaries */
+ if (dpoint_iter_ext != dpoint_iter_mid &&
+ MAGNITUDE(temp) < new_projection->origin_dist) {
+
+ /* If we are here it means projection has
closer neighbor than original,
+ we now check if intersection falls inside
segment and has closer neighbor.
+ Also it should not be our first point. */
+ if (array_pointer > 0) {
+ //puts("array pointer bigger than
zero");
+ vect_t prev_to_curr;
+ point_t plane_point;
+ struct projection * previous =
proj_array[array_pointer - 1];
+ //VPRINT("previous",
previous->original->point);
+ //VPRINT("current",
new_projection->original->point);
+ //puts("read current and previous, now
computing plane");
+ VSUB2(prev_to_curr,
new_projection->original->point, previous->original->point);
+ struct intersection_t * intersection;
+ BU_GET(intersection, struct
intersection_t);
+ vect_t intersect_to_original;
+ fastf_t distance_to_originals;
+ VSCALE(prev_to_curr, prev_to_curr, 0.5);
+ //puts("computing intersection");
+ VADD2(plane_point, previous->point,
prev_to_curr);
+ compute_intersection(intersection,
inhit, outhit, plane_point, new_projection->original->point);
+ if (intersection->intersect == 0) {
+ bu_log("Error: No intersection
happened. \n");
+ return 0;
+ }
+ VSUB2(intersect_to_original,
intersection->intersection_point, new_projection->original->point);
+ distance_to_originals =
MAGNITUDE(intersect_to_original);
+ /* Look for points closer to
intersection than the two original ones */
+ //puts("arrived at inner for");
+ for (BU_LIST_FOR(dpoint_iter_int,
density_point, &(user_plist->l))) {
+ VSUB2(temp,
new_projection->point, dpoint_iter_int->point);
+ if (dpoint_iter_ext !=
dpoint_iter_int &&
+ MAGNITUDE(temp) <
distance_to_originals + MARGIN) {
+ //puts("inner loop
found something");
+ /* FIXME: Deallocate
space we used for new_projection */
+ is_valid = 0;
+ //bu_log("Skipped
projection. \n");
+ break;
+ }
+ }
+
+ }
+ }
+ /* We are at the end of one iteration on the outer
check loop.
+ If we detected a nonvalid point we should stop looking.
*/
+ if (!is_valid) break;
+ }
+ if (is_valid) {
+
+ if (array_pointer == 0) {
+ new_projection->prev_dist =
new_projection->inhit_dist;
+ }
+ else {
+ VSUB2(prev_to_current_vect,
new_projection->vect,
+ proj_array[array_pointer - 1]->vect);
+ new_projection->prev_dist =
MAGNITUDE(prev_to_current_vect);
+ }
+ proj_array[array_pointer] = new_projection;
+ array_pointer++;
+ /* DEBUG */
+ //VPRINT("projection vector", new_projection->vect);
+ }
+
+
+
+
+ }
+
+ /* Sort projection list based on distance to inhit */
+ /* DEBUG */
+ //puts("Unordered Projection distances:");
+ for (int i = 0; i < array_pointer; i++) {
+ //bu_log("Point at distance %lf \n", proj_array[i]->inhit_dist);
+ }
+
+ qsort(proj_array, array_pointer, sizeof(struct projection *),
compare_dpoints);
+
+ /* DEBUG */
+ //puts("Ordered projection distances:");
+ for (int i = 0; i < array_pointer; i++) {
+ //bu_log("Point at distance %lf \n", proj_array[i]->inhit_dist);
+ }
+
+ /* Density Computation Loop preparation */
+ struct projection * curr_proj;
+ fastf_t acc_avg_density = 0.0;
+ struct projection * next_proj;
+
+ /* WARNING: From now on I refer to 'segment' as each piece of ray
inbetween two
+ points (projection or in/out */
+
+ /* First segment, we take everything as having density of first point */
+ curr_proj = proj_array[0];
+ acc_avg_density += curr_proj->original->density *
+ curr_proj->inhit_dist / total_segment_len;
+
+ /* DEBUG
+ bu_log("First projection. Proportion %f, added %lf to accumulator.\n",
+ curr_proj->inhit_dist / total_segment_len,
curr_proj->original->density *
+ curr_proj->inhit_dist / total_segment_len);
+ */
+ /* Distance from current projection point to boundary */
+ fastf_t boundary_dist;
+ /* Distance between current projection point and next one */
+ fastf_t partial_segment_length;
+ vect_t partial_segment;
+ //puts("loop start");
+ //printf("Array pointer is %d \n", array_pointer);
+ next_proj = proj_array[0];
+ /* Loop through remaining segments. For each segment, compute the
boundary
+ and take density of each side accordingly, add it to accumulator */
+ for (int i = 0; i < array_pointer - 1; i++) {
+ curr_proj = proj_array[i];
+ next_proj = proj_array[i + 1];
+ VSUB2(partial_segment, curr_proj->point, next_proj->point);
+ partial_segment_length = MAGNITUDE(partial_segment);
+ boundary_dist = (next_proj->origin_dist *
next_proj->origin_dist +
+ partial_segment_length * partial_segment_length -
+ curr_proj->origin_dist * curr_proj->origin_dist) /
+ (2 * partial_segment_length);
+ acc_avg_density += curr_proj->original->density *
+ boundary_dist / total_segment_len;
+ acc_avg_density += next_proj->original->density *
+ (partial_segment_length - boundary_dist) /
total_segment_len;
+ }
+ //puts("end of for loop");
+ curr_proj = next_proj;
+ /* Last segment, from the last point to the outhit point has density
value
+ of this last point */
+ vect_t last_to_outhit;
+ VSUB2(last_to_outhit, outhit, curr_proj->point);
+ acc_avg_density += curr_proj->original->density *
+ MAGNITUDE(last_to_outhit) / total_segment_len;
+ /* DEBUG
+ bu_log("Last projection. Proportion %f, added %lf to accumulator.\n",
+ curr_proj->prev_dist / total_segment_len,
curr_proj->original->density *
+ curr_proj->prev_dist / total_segment_len);
+ */
+ /* Return final value */
+ //bu_log("Avg density we saw through segment: %lf \n", acc_avg_density);
+ return acc_avg_density;
+}
+
void
usage(const char *argv0)
{
@@ -100,7 +400,6 @@
fastf_t volume;
};
-
extern int rpt_overlap; /* report region verbosely */
extern fastf_t cell_width; /* model space grid cell width */
extern fastf_t cell_height; /* model space grid cell height */
@@ -144,9 +443,9 @@
/* if we don't have a valid material density to work with, use a
default material */
if (density[reg->reg_gmater] < 0) {
- bu_log("Material type %d used, but has no density file entry.\n",
reg->reg_gmater);
- bu_log(" (region %s)\n", reg->reg_name);
- bu_log(" Mass is undefined.\n");
+ //bu_log("Material type %d used, but has no density file entry.\n",
reg->reg_gmater);
+ //bu_log(" (region %s)\n", reg->reg_name);
+ //bu_log(" Mass is undefined.\n");
bu_semaphore_acquire(BU_SEM_SYSCALL);
reg->reg_gmater = 0;
bu_semaphore_release(BU_SEM_SYSCALL);
@@ -157,18 +456,20 @@
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;
-
+ //const fastf_t los_factor = (fastf_t)reg->reg_los * 0.01;
+ const fastf_t los_factor = 1;
dp->volume = partition_volume;
VBLEND2(dp->centroid, 0.5, ihitp->hit_point, 0.5, ohitp->hit_point);
- if (density[reg->reg_gmater] >= 0) {
+ //puts("about to call segment_density");
/* density needs to be converted from g/cm^3 to g/mm^3 */
- const fastf_t density_factor = density[reg->reg_gmater] * 0.001;
-
+ const fastf_t density_factor =
segment_density(ihitp->hit_point, ohitp->hit_point);
+ //bu_log("Read %lf mass from segment_density\n",
density_factor);
/* Compute mass in terms of grams */
dp->weight = partition_volume * los_factor * density_factor;
- }
+ //bu_log("Partition volume: %lf, los_factor: %lf,
density_factor %lf \n Stored %lf in dp->weight \n",
+ //partition_volume, los_factor, density_factor,
dp->weight);
+
}
}
return 1; /* report hit to main routine */
@@ -292,7 +593,21 @@
if (minus_o) {
fclose(outfp);
}
+ /* Prepare user point list and let user fill it */
+ BU_GET(user_plist, struct density_point);
+ BU_LIST_INIT(&(user_plist->l));
+ read_density_points(user_plist);
+ //DEBUG
+ struct density_point * user_plist_iter;
+ puts("Main after user input. These are the loaded points:");
+ for (BU_LIST_FOR(user_plist_iter, density_point, &(user_plist->l))) {
+ VPRINT("density_point", user_plist_iter->point);
+ }
+ //END DEBUG
+
+
+ puts("Finish view_init");
return 0; /* no framebuffer needed */
}
@@ -451,7 +766,7 @@
weight *= conversion;
total_weight += weight;
-
+ bu_log("added %lf to total weight\n", weight);
BU_ALLOC(ptr, fastf_t);
*ptr = weight;
/* FIXME: shouldn't the existing reg_udata be bu_free'd first (see
previous loop) */
@@ -608,7 +923,32 @@
{
}
+void compute_intersection(struct intersection_t * intersection, point_t p0,
point_t p1, point_t p_co, vect_t p_no) {
+ fastf_t epsilon = 1e-6;
+ fastf_t fac;
+ vect_t u, w;
+ VSUB2(u, p1, p0);
+ fastf_t dot = VDOT(p_no, u);
+ if (abs(dot) > epsilon) {
+ intersection->intersect = 1;
+ VSUB2(w, p0, p_co);
+ fac = -VDOT(p_no, w) / dot;
+ VSCALE(u, u, fac);
+ VADD2(intersection->intersection_point, p0, u);
+ intersection->intersect = 0;
+ }
+ else {
+ intersection->intersect = 0;
+ }
+}
+
+int compare_dpoints(const void *a, const void *b) {
+ struct projection *x = *(struct projection **)a;
+ struct projection *y = *(struct projection **)b;
+ return x->inhit_dist - y->inhit_dist;
+}
+
/*
* 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