60 | | float denominator = (ab.x()-dc.x()); |
61 | | if (denominator==0.0) |
62 | | { |
63 | | // ab and cd parallel |
64 | | return osg::Vec3(ab.y(), -ab.x(), 0.0f); |
65 | | } |
66 | | float r = (dc.x()-ab.y())/ denominator; |
67 | | float ny = 1.0f / sqrtf(r*r + 1.0f); |
68 | | float nx = r * ny; |
69 | | |
70 | | return osg::Vec3(nx,ny,0.0f); |
| 79 | |
| 80 | float e = dc.y() - ab.y(); |
| 81 | float f = ab.x() - dc.x(); |
| 82 | float denominator = sqrtf(e*e + f*f); |
| 83 | float nx = e / denominator; |
| 84 | float ny = f / denominator; |
| 85 | if (( ab.x()*ny - ab.y()*nx) > 0.0f) |
| 86 | { |
| 87 | // OSG_NOTICE<<" computeBisectorNormal(a=["<<a<<"], b=["<<b<<"], c=["<<c<<"], d=["<<d<<"]), nx="<<nx<<", ny="<<ny<<", denominator="<<denominator<<" no need to swap"<<std::endl; |
| 88 | return osg::Vec3(nx,ny,0.0f); |
| 89 | } |
| 90 | else |
| 91 | { |
| 92 | OSG_NOTICE<<" computeBisectorNormal(a=["<<a<<"], b=["<<b<<"], c=["<<c<<"], d=["<<d<<"]), nx="<<nx<<", ny="<<ny<<", denominator="<<denominator<<" need to swap!!!"<<std::endl; |
| 93 | return osg::Vec3(-nx,-ny,0.0f); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | float computeBisectorIntersectorThickness(const osg::Vec3& a, const osg::Vec3& b, const osg::Vec3& c, const osg::Vec3& d, const osg::Vec3& e, const osg::Vec3& f) |
| 98 | { |
| 99 | osg::Vec3 intersection_abcd = computeIntersectionPoint(a,b,c,d); |
| 100 | osg::Vec3 bisector_abcd = computeBisectorNormal(a,b,c,d); |
| 101 | osg::Vec3 intersection_cdef = computeIntersectionPoint(c,d,e,f); |
| 102 | osg::Vec3 bisector_cdef = computeBisectorNormal(c,d,e,f); |
| 103 | if (bisector_abcd==bisector_cdef) |
| 104 | { |
| 105 | OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl; |
| 106 | OSG_NOTICE<<" bisectors parallel, thickness = "<<FLT_MAX<<std::endl; |
| 107 | return FLT_MAX; |
| 108 | } |
| 109 | |
| 110 | osg::Vec3 bisector_intersection = computeRayIntersectionPoint(intersection_abcd,bisector_abcd, intersection_cdef, bisector_cdef); |
| 111 | osg::Vec3 normal(d.y()-c.y(), c.x()-d.x(), 0.0); |
| 112 | float cd_length = normal.normalize(); |
| 113 | if (cd_length==0) |
| 114 | { |
| 115 | OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl; |
| 116 | OSG_NOTICE<<" segment length==0, thickness = "<<FLT_MAX<<std::endl; |
| 117 | return FLT_MAX; |
| 118 | } |
| 119 | |
| 120 | float thickness = (bisector_intersection - c) * normal; |
| 121 | #if 0 |
| 122 | OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl; |
| 123 | OSG_NOTICE<<" bisector_abcd = "<<bisector_abcd<<", bisector_cdef="<<bisector_cdef<<std::endl; |
| 124 | OSG_NOTICE<<" bisector_intersection = "<<bisector_intersection<<", thickness = "<<thickness<<std::endl; |
| 125 | #endif |
| 126 | return thickness; |
91 | | Bisectors _bisectors; |
92 | | Points _boundary; |
93 | | Distances _distances; |
| 136 | Segments _segments; |
| 137 | |
| 138 | Boundary(osg::Vec3Array* vertices, unsigned int start, unsigned int count) |
| 139 | { |
| 140 | _vertices = vertices; |
| 141 | |
| 142 | if ((*_vertices)[start]==(*_vertices)[start+count-1]) |
| 143 | { |
| 144 | OSG_NOTICE<<"Boundary is a line loop"<<std::endl; |
| 145 | } |
| 146 | else |
| 147 | { |
| 148 | OSG_NOTICE<<"Boundary is not a line loop"<<std::endl; |
| 149 | } |
| 150 | |
| 151 | _segments.reserve(count-1); |
| 152 | for(unsigned int i=start; i<start+count-1; ++i) |
| 153 | { |
| 154 | _segments.push_back(Segment(i,i+1)); |
| 155 | } |
| 156 | |
| 157 | } |
| 158 | |
| 159 | float computeThickness(unsigned int i) |
| 160 | { |
| 161 | Segment& seg_before = _segments[ (i+_segments.size()-1) % _segments.size() ]; |
| 162 | Segment& seg_target = _segments[ (i) % _segments.size() ]; |
| 163 | Segment& seg_after = _segments[ (i+1) % _segments.size() ]; |
| 164 | return computeBisectorIntersectorThickness( |
| 165 | (*_vertices)[seg_before.first], (*_vertices)[seg_before.second], |
| 166 | (*_vertices)[seg_target.first], (*_vertices)[seg_target.second], |
| 167 | (*_vertices)[seg_after.first], (*_vertices)[seg_after.second]); |
| 168 | } |
| 169 | |
| 170 | void computeAllThickness() |
| 171 | { |
| 172 | for(unsigned int i=0; i<_segments.size(); ++i) |
| 173 | { |
| 174 | computeThickness(i); |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | |
| 179 | bool findMinThickness(unsigned int& minThickness_i, float& minThickness) |
| 180 | { |
| 181 | minThickness_i = _segments.size(); |
| 182 | for(unsigned int i=0; i<_segments.size(); ++i) |
| 183 | { |
| 184 | float thickness = computeThickness(i); |
| 185 | if (thickness>0.0 && thickness < minThickness) |
| 186 | { |
| 187 | minThickness = thickness; |
| 188 | minThickness_i = i; |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | return minThickness_i != _segments.size(); |
| 193 | } |
| 194 | |
| 195 | void removeAllSegmentsBelowThickness(float targetThickness) |
| 196 | { |
| 197 | OSG_NOTICE<<"removeAllSegmentsBelowThickness("<<targetThickness<<")"<<std::endl; |
| 198 | for(;;) |
| 199 | { |
| 200 | unsigned int minThickness_i = _segments.size(); |
| 201 | float minThickness = targetThickness; |
| 202 | if (!findMinThickness(minThickness_i,minThickness)) break; |
| 203 | |
| 204 | OSG_NOTICE<<" removing segment _segments["<<minThickness_i<<"] ("<<_segments[minThickness_i].first<<", "<<_segments[minThickness_i].second<<" with thickness="<<minThickness<<" "<<std::endl; |
| 205 | _segments.erase(_segments.begin()+minThickness_i); |
| 206 | } |
| 207 | } |
| 208 | |
| 409 | osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness) |
| 410 | { |
| 411 | OSG_NOTICE<<"computeThickness("<<orig_geometry<<")"<<std::endl; |
| 412 | osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(orig_geometry->getVertexArray()); |
| 413 | osg::Geometry::PrimitiveSetList& orig_primitives = orig_geometry->getPrimitiveSetList(); |
| 414 | |
| 415 | for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin(); |
| 416 | itr != orig_primitives.end(); |
| 417 | ++itr) |
| 418 | { |
| 419 | osg::DrawArrays* drawArray = dynamic_cast<osg::DrawArrays*>(itr->get()); |
| 420 | if (drawArray && drawArray->getMode()==GL_POLYGON) |
| 421 | { |
| 422 | Boundary boundary(orig_vertices, drawArray->getFirst(), drawArray->getCount()); |
| 423 | boundary.computeAllThickness(); |
| 424 | |
| 425 | boundary.removeAllSegmentsBelowThickness(thickness); |
| 426 | } |
| 427 | } |
| 428 | return 0; |
| 429 | } |
| 430 | |
| 431 | |