I'm working on integrating the code into viewweight. As a first step I thought it would be a good idea to not touch the existing code (and let it read from the .density file) and just override the hit() function to call my segment_density instead of taking the file data. However I'm getting segmentation faults whenever I try to run the code. This happened to me before and I managed to solve it by changing the codification of the .density file, however this time I don't seem to be able to fix it.
Here is result screencap, and I also attach the modified viewweight and the density file. https://puu.sh/xAmiE/b5fa0dfab8.png Mario. On 8 September 2017 at 21:04, Mario Meissner <mr.rash....@gmail.com> wrote: > Peopleee! > > Here goes today's work. I'm proud to announce the example I modeled a few > days ago now works correctly!! > Code still contains my debug prints and lots of random 'puts' to know > where and why stuff crashes. I feel I will need it in the future so for now > it remains. > I probably should keep looking for flaws by setting up other examples, and > while doing so I should also clean it up a bit since the code grew over 600 > lines now, quite difficult to read and understand. > > Screenshot: > https://puu.sh/xuIXk/9626ce2fb6.png > > Mario. > > On 8 September 2017 at 19:56, Mario Meissner <mr.rash....@gmail.com> > wrote: > >> Hi Daniel! >> >> Thank you a lot for your reply. I was focused on generating the bisector >> to intersect two lines, but intersecting the actual plane is much simpler. >> I made a little function to intersect a plane with a line (partially taken >> from this stackoverflow post >> <https://stackoverflow.com/questions/5666222/3d-line-plane-intersection>, >> so credits to user ideasman42 >> <https://stackoverflow.com/users/432509/ideasman42>). I am now finishing >> of the 'patch' to my code that is supposed to now correctly skip >> unnecessary points and create a list with those who's regions we will >> actually cross. Code probably tomorrow. >> >> Mario. >> >> On 8 September 2017 at 09:35, Daniel Roßberg <danielmrossb...@gmail.com> >> wrote: >> >>> Hi Mario, >>> >>> In 3D space, rectangular to a vector you have a plane and the vector is >>> a normal vector of this plane. In this plane are all vectors which are >>> perpendicular to your first vector, i.e. the vectors which products with >>> your first vector are 0. This gives you a first equation with two >>> variables. >>> >>> Next, you want to intersect the plane with a ray. I.e., one vector from >>> your plan has to be a multiple of the ray which gives you another equation. >>> >>> However, there should be examples in the BRL-CAD source code for this. >>> E.g., the ray-trace of the half primitive is very similar to your problem. >>> There, the intersection of a plane, given by a normal vector and a point in >>> it, and a ray, given by a start point and a direction, will be computed. >>> >>> I hope this helps. >>> >>> >>> Regards, >>> Daniel >>> >>> >>> >>> I'm facing a wall. I need to find a perpendicular vector with the >>> condition that it will intersect a third vector. >>> Basically, I have the ray and a vector drawn from my current point to >>> the previous point. >>> I want the perpendicular bisector of that vector to cross my ray, so >>> that I can obtain the intersection between the bisector and the ray. >>> >>> For that I need two things: >>> 1) Obtain the perpendicular vector. in 3D there are infinite options, >>> but only one will cross the ray. How do I get the one I need? >>> 2) Obtain the intersection point. >>> >>> I browsed through vmath.h but I didn't find anything that could help me. >>> Do you know any macro that could be useful here? >>> Otherwise I will need to make some of my own for this! If so, any ideas >>> on how to approach it? >>> >>> Mario. >>> >>> >>> ------------------------------------------------------------ >>> ------------------ >>> 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 (revision 70280) +++ src/rt/viewweight.c (working copy) @@ -48,7 +48,30 @@ #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; +}; + +/*FIXME: This is global for now because I need this pointer through all the +hit calls. How can I make it available for all calls without a global variable? */ +struct density_point * user_plist; + +const int MAX_POINTS = 99; + extern struct resource resource[]; /* Viewing module specific "set" variables */ @@ -59,6 +82,273 @@ const char title[] = "RT Weight"; +int compare_dpoints(const void *, const void *); +point_t * intersection(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\n")) { + 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); + /* 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); + point_t * intersectionp; + 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); + intersectionp = intersection(inhit, outhit, plane_point, new_projection->original->point); + VSUB2(intersect_to_original, *intersectionp, 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) { @@ -162,13 +452,19 @@ dp->volume = partition_volume; VBLEND2(dp->centroid, 0.5, ihitp->hit_point, 0.5, ohitp->hit_point); + const fastf_t density_factor = segment_density(ihitp->hit_point, ohitp->hit_point); + + /* Compute mass in terms of grams */ + dp->weight = partition_volume * los_factor * density_factor; + + /* 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; - } + } } return 1; /* report hit to main routine */ @@ -608,7 +904,32 @@ { } +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; +} +point_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; + point_t intersect; + VSUB2(u, p1, p0); + fastf_t dot = VDOT(p_no, u); + if (abs(dot) > epsilon) { + VSUB2(w, p0, p_co); + fac = -VDOT(p_no, w) / dot; + VSCALE(u, u, fac); + VADD2(intersect, p0, u); + return &intersect; + } + else { + return NULL; + } +} + + /* * Local Variables: * mode: C
.density
Description: Binary data
------------------------------------------------------------------------------ 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