| 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 | |