Revision: 55710
          http://sourceforge.net/p/brlcad/code/55710
Author:   starseeker
Date:     2013-06-11 20:07:33 +0000 (Tue, 11 Jun 2013)
Log Message:
-----------
Add (commented out) file that attemps to make nicer bot wireframes using a 
surface patch breakout technique.  Proving to be too slow for interactive use 
in its current form - hot spot is determing which faces share the edges with 
any one particular face, and even if that can somehow be made fast the 
pre-processing really should be done in parallel.  Checkpointing so a revert 
point is available.

Modified Paths:
--------------
    brlcad/trunk/src/librt/CMakeLists.txt

Added Paths:
-----------
    brlcad/trunk/src/librt/primitives/bot/bot_wireframe.cpp

Modified: brlcad/trunk/src/librt/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/librt/CMakeLists.txt       2013-06-11 17:20:55 UTC (rev 
55709)
+++ brlcad/trunk/src/librt/CMakeLists.txt       2013-06-11 20:07:33 UTC (rev 
55710)
@@ -257,6 +257,7 @@
   prcomb.c
   primitives/bot/btg.h
   primitives/bot/g_bot_include.c
+  primitives/bot/bot_wireframe.cpp
   primitives/bot/tieprivate.h
   primitives/bot/tie.c
   primitives/bot/tie_kdtree.c

Added: brlcad/trunk/src/librt/primitives/bot/bot_wireframe.cpp
===================================================================
--- brlcad/trunk/src/librt/primitives/bot/bot_wireframe.cpp                     
        (rev 0)
+++ brlcad/trunk/src/librt/primitives/bot/bot_wireframe.cpp     2013-06-11 
20:07:33 UTC (rev 55710)
@@ -0,0 +1,288 @@
+#include "common.h"
+
+#include <map>
+#include <set>
+#include <queue>
+#include <list>
+#include <vector>
+
+#include "vmath.h"
+#include "raytrace.h"
+#include "wdb.h"
+
+/*************************
+ *   Utility functions 
+ *************************/
+
+#if 0
+// Make an edge id using the Szudzik pairing function:
+long unsigned int edge_id(size_t pt_A, size_t pt_B)
+{
+    return (pt_A >= pt_B) ? (pt_A * pt_A + pt_A + pt_B) : (pt_B * pt_B + pt_A);
+}
+
+// shift one of the vertex index numbers up to form a unique ID.  Offset is
+// log10(bot->num_vertices) + 1
+long unsigned int edge_id(size_t pt_A, size_t pt_B, int offset)
+{
+    return (pt_A <= pt_B) ? (pt_A * pow(10,offset) + pt_B) : (pt_B * 
pow(10,offset) + pt_A);
+}
+
+void breakout(long unsigned int id, int offset, size_t *A, size_t *B)
+{
+    (*B) = (size_t)((long)id % (int)pow(10,offset));
+    (*A) = (size_t)(id - (*B))/ (int)(pow(10, offset));
+}
+#endif
+
+// Make an edge using consistent vertex ordering
+static std::pair<size_t, size_t>
+mk_edge(size_t pt_A, size_t pt_B)
+{
+    if (pt_A <= pt_B) {
+       return std::make_pair(pt_A, pt_B);
+    } else {
+       return std::make_pair(pt_B, pt_A);
+    }
+}
+
+
+// Calculate area of a face
+static double
+face_area(struct rt_bot_internal *bot, size_t face_num)
+{
+    point_t ptA, ptB, ptC;
+    double a, b, c, p;
+    double area;
+    VMOVE(ptA, &bot->vertices[bot->faces[face_num*3+0]*3]);
+    VMOVE(ptB, &bot->vertices[bot->faces[face_num*3+1]*3]);
+    VMOVE(ptC, &bot->vertices[bot->faces[face_num*3+2]*3]);
+    a = DIST_PT_PT(ptA, ptB);
+    b = DIST_PT_PT(ptB, ptC);
+    c = DIST_PT_PT(ptC, ptA);
+    p = (a + b + c)/2;
+    area = sqrt(p*(p-a)*(p-b)*(p-c));
+    return area;
+}
+
+// Given a BoT face, return the three other faces that share an edge with that 
face
+static void
+get_connected_faces(struct rt_bot_internal *bot, size_t face_num,  
std::map<size_t, std::set<size_t> > *vert_to_face, std::set<size_t> *faces)
+{
+    std::map<size_t, size_t> face_cnt;
+    size_t points[3];
+    points[0] = bot->faces[face_num*3+0]*3;
+    points[1] = bot->faces[face_num*3+1]*3;
+    points[2] = bot->faces[face_num*3+2]*3;
+    std::set<size_t>::iterator it;
+    for (int i = 0; i < 3; ++i) { 
+       for (it = (*vert_to_face)[points[i]].begin(); it != 
(*vert_to_face)[points[i]].end(); it++) {
+           face_cnt[(*it)] += 1;
+       }
+    }
+    std::map<size_t, size_t>::iterator mit;
+    for (mit = face_cnt.begin(); mit != face_cnt.end(); ++mit) {
+       if ((*mit).second > 1) {
+           faces->insert((*mit).first);
+       }
+    }
+}
+
+/* To avoid drawing dupliate lines, build the final vlist using a set */
+static void
+plot_patch_borders(std::vector<std::map<std::pair<size_t, size_t>, size_t> > 
*patch_edge_cnt, struct rt_bot_internal *bot, struct bu_list *vhead)
+{
+    std::set<std::pair<size_t, size_t> > final_edge_set;
+    std::set<std::pair<size_t, size_t> >::iterator fe_it;
+    std::map<std::pair<size_t, size_t>, size_t>::iterator e_it;
+    for (int i = 0; i < patch_edge_cnt->size(); i++) {
+       for (e_it = (*patch_edge_cnt)[i].begin(); e_it != 
(*patch_edge_cnt)[i].end(); e_it++) {
+           if ((*e_it).second == 1) {
+                final_edge_set.insert((*e_it).first);
+           }
+       }
+    }
+    for (fe_it = final_edge_set.begin(); fe_it != final_edge_set.end(); 
fe_it++) {
+       RT_ADD_VLIST(vhead, &(bot->vertices[(*fe_it).first]), 
BN_VLIST_LINE_MOVE);
+       RT_ADD_VLIST(vhead, &(bot->vertices[(*fe_it).second]), 
BN_VLIST_LINE_DRAW);
+    }
+}
+
+/**********************************************************
+ *   Code for identifying semi-flat patches in bots
+ *   and creating wireframe edges
+ **********************************************************/
+extern "C" int
+rt_bot_adaptive_plot(struct rt_db_internal *ip, const struct rt_view_info 
*info)
+{
+    struct rt_bot_internal *bot;
+    RT_CK_DB_INTERNAL(ip);
+    BU_CK_LIST_HEAD(info->vhead);
+    bot = (struct rt_bot_internal *)ip->idb_ptr;
+    RT_BOT_CK_MAGIC(bot);
+
+    if (bot->num_vertices <= 0 || !bot->vertices || bot->num_faces <= 0 || 
!bot->faces)
+        return 0;
+
+    /* Declare key containers */
+    vect_t gvects[6];
+    std::vector<double> face_areas;
+    std::vector<double> face_normals;
+    std::vector<std::vector<size_t> > groups;
+    std::vector<std::map<std::pair<size_t, size_t>, size_t> > 
groups_edge_face_cnt;
+    std::vector<std::vector<size_t> > categorization_results;
+    std::vector<int> face_to_plane;
+    std::vector<std::set<size_t> > patches;
+    std::map<size_t, std::set<size_t> > vert_to_face;
+    
+    /* Initialize containers */
+    face_areas.resize(bot->num_faces);
+    face_to_plane.resize(bot->num_faces);
+    face_normals.resize(bot->num_faces*3);
+    groups.resize(6);
+    groups_edge_face_cnt.resize(6);
+    categorization_results.resize(6);
+    for (int i = 0; i < 6; ++i) {
+       categorization_results[i].resize(bot->num_faces); //categories can hold 
at most all faces in bot
+    }
+    patches.resize(bot->num_faces*3); // Max number of patches should be the 
same as the face cnt, but it isn't always
+    VSET(gvects[0], -1,0,0);
+    VSET(gvects[1], 0,-1,0);
+    VSET(gvects[2], 0,0,-1);
+    VSET(gvects[3], 1,0,0);
+    VSET(gvects[4], 0,1,0);
+    VSET(gvects[5], 0,0,1);
+ 
+    // Calculate face normals dot product with bounding rpp planes
+    for (size_t i=0; i < bot->num_faces; ++i) {
+       size_t pt_A, pt_B, pt_C;
+       size_t result_max;
+       double vdot = 0.0;
+       double result = 0.0;
+       vect_t a, b, norm_dir;
+       // Add vert -> edge and edge -> face mappings to global map.
+       pt_A = bot->faces[i*3+0]*3;
+       pt_B = bot->faces[i*3+1]*3;
+       pt_C = bot->faces[i*3+2]*3;
+       vert_to_face[pt_A].insert(i);
+       vert_to_face[pt_B].insert(i);
+       vert_to_face[pt_C].insert(i);
+       // Categorize face
+       VSUB2(a, &bot->vertices[bot->faces[i*3+1]*3], 
&bot->vertices[bot->faces[i*3]*3]);
+       VSUB2(b, &bot->vertices[bot->faces[i*3+2]*3], 
&bot->vertices[bot->faces[i*3]*3]);
+       VCROSS(norm_dir, a, b);
+       VUNITIZE(norm_dir);
+        face_normals[i*3]=norm_dir[0];
+        face_normals[i*3+1]=norm_dir[1];
+        face_normals[i*3+2]=norm_dir[2];
+       for (int j=0; j < 6; j++) {
+           vdot = VDOT(gvects[j],norm_dir);
+            categorization_results[j][i] = vdot;
+           if (vdot > result) {
+               result_max = j;
+               result = vdot;
+           }
+       }
+       groups[result_max].push_back(i);
+       face_to_plane[i]=result_max;
+        face_areas[i] = face_area(bot, i); 
+    }
+
+    // Order the groups by number of bots
+    std::vector<int> ordered_groups;
+    int group_ids[] = {0, 1, 2, 3, 4, 5};
+    std::set<int> group_bin (group_ids, group_ids+6);
+    std::set<int>::iterator fg_it;
+    while (!group_bin.empty()) {
+        int largest_group = 0;
+        int max = 0;
+       for (fg_it = group_bin.begin(); fg_it != group_bin.end(); fg_it++) {
+           if (groups[(*fg_it)].size() == 0) {
+                group_bin.erase((*fg_it));
+           } else {
+               if (groups[(*fg_it)].size() > max) {
+                   max = groups[(*fg_it)].size();
+                   largest_group = (*fg_it);
+               }
+           }
+       }
+       if (max > 0) 
+           ordered_groups.push_back(largest_group);
+       group_bin.erase(largest_group); 
+    }
+
+    // All faces must belong to some patch - continue until all faces are 
processed
+    std::vector<int> face_pool (bot->num_faces, 1);
+    std::vector<int> face_to_patch (bot->num_faces, -1);
+    int patch_cnt = -1;
+    for (int i = 0; i < ordered_groups.size(); i++) {
+       int largest_face = 0;
+       int curr_group = ordered_groups[i];
+       while (largest_face != -1) {
+           // Start a new patch
+           vect_t largest_face_normal;
+           largest_face = -1;
+            patch_cnt++;
+           // Find largest remaining face in group
+           double face_size_criteria = 0.0;
+           for (int f_it = 0; f_it < groups[curr_group].size(); f_it++) { 
+               if (face_pool[groups[curr_group][f_it]]) {
+                   double fa = face_areas[groups[curr_group][f_it]];
+                   if (fa > face_size_criteria) {
+                       largest_face = groups[curr_group][f_it];
+                       face_size_criteria = fa;
+                   }
+               }
+           }
+           if (largest_face != -1) {
+               std::queue<int> face_queue;
+               face_queue.push(largest_face);
+
+               VSET(largest_face_normal, face_normals[largest_face*3], 
face_normals[largest_face*3+1], face_normals[largest_face*3+2]);
+               face_pool[largest_face] = 0;
+               while (!face_queue.empty()) {
+                   size_t pt_A, pt_B, pt_C;
+                   int face_num = face_queue.front();
+                   face_queue.pop();
+                   patches[patch_cnt].insert(face_num);
+                   face_to_patch[face_num] = patch_cnt;
+                   pt_A = bot->faces[face_num*3+0]*3;
+                   pt_B = bot->faces[face_num*3+1]*3;
+                   pt_C = bot->faces[face_num*3+2]*3;
+                   groups_edge_face_cnt[curr_group][mk_edge(pt_A, pt_B)] += 1;
+                   groups_edge_face_cnt[curr_group][mk_edge(pt_B, pt_C)] += 1;
+                   groups_edge_face_cnt[curr_group][mk_edge(pt_C, pt_A)] += 1;
+
+                   std::set<size_t> connected_faces;
+                   std::set<size_t>::iterator cf_it;
+                   get_connected_faces(bot, face_num, &(vert_to_face), 
&connected_faces);
+                   for (cf_it = connected_faces.begin(); cf_it != 
connected_faces.end() ; cf_it++) {
+                       if (face_pool[(*cf_it)]) {
+                           double curr_face_area = face_areas[(*cf_it)];
+                           if (curr_face_area < (face_size_criteria*10) && 
curr_face_area > (face_size_criteria*0.1)) {
+                               vect_t face_normal;
+                               VSET(face_normal, face_normals[face_num*3], 
face_normals[face_num*3+1], face_normals[face_num*3+2]);
+                               if (VDOT(largest_face_normal, face_normal) > 
0.85) {
+                                   face_queue.push((*cf_it));
+                                   face_pool[(*cf_it)] = 0;
+                               } 
+                           }
+                       }
+                   }
+               }
+           }
+       }
+    }
+    plot_patch_borders(&(groups_edge_face_cnt), bot, info->vhead);
+
+    return 0;
+}
+
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8


Property changes on: brlcad/trunk/src/librt/primitives/bot/bot_wireframe.cpp
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to