void QTessellatorPrivate::addIntersections() { if (scanline.size) { QDEBUG() << "INTERSECTIONS"; // check marked edges for intersections #ifdef DEBUG for (int i = 0; i < scanline.size; ++i) { Edge *e = scanline.edges[i]; QDEBUG() << " " << i << e->edge << "isect=(" << e->intersect_left << e->intersect_right << ')'; } #endif for (int i = 0; i < scanline.size - 1; ++i) { Edge *e1 = scanline.edges[i]; Edge *e2 = scanline.edges[i + 1]; // check for intersection if (e1->intersect_right || e2->intersect_left) addIntersection(e1, e2); } } #if 0 if (intersections.constBegin().key().y == y) { QDEBUG() << "----------------> intersection on same line"; scanline.clearMarks(); scanline.processIntersections(y, &intersections); goto redo; } #endif }
bool ChartElemNavaids::addNewIntersection(const QString& intersection_id, QString& err_msg) { const Waypoint* existing_intersection = getNavaid(intersection_id, Waypoint::INTERSECTION); if (existing_intersection) { err_msg = QString("Navaids:INTERSECTION: Intersection with ID (%1) already exists"). arg(intersection_id); return false; } Intersection *intersection = (Intersection*)m_chart_model->getNavdata()->getElementsWithSignal( intersection_id, "", Waypoint::INTERSECTION); if (!intersection) { err_msg = QString("Navaids:INTERSECTION: unknown intersection with ID (%1)"). arg(intersection_id); delete intersection; return false; } QDomDocument dom_doc = m_dom_element.ownerDocument(); QDomElement new_element = dom_doc.createElement(CHART_NODE_NAME_NAVAIDS_INTERSECTION); m_dom_element.appendChild(new_element); bool ret = addIntersection(*intersection, new_element, dom_doc, err_msg); setProjectionCenterWhenAppropriate(intersection); delete intersection; return ret; }
/** * Adds EdgeIntersections for one or both * intersections found for a segment of an edge to the edge intersection list. */ void SegmentString::addIntersections(LineIntersector *li, int segmentIndex, int geomIndex) { for (int i=0; i<li->getIntersectionNum(); i++) { addIntersection(li,segmentIndex, geomIndex, i); } }
/*public*/ void NodedSegmentString::addIntersections(LineIntersector *li, unsigned int segmentIndex, int geomIndex) { for (int i=0, n=li->getIntersectionNum(); i<n; ++i) { addIntersection(li, segmentIndex, geomIndex, i); } }
/** * Add an SegmentNode for intersection intIndex. * An intersection that falls exactly on a vertex * of the SegmentString is normalized * to use the higher of the two possible segmentIndexes */ void SegmentString::addIntersection(LineIntersector *li, int segmentIndex, int geomIndex, int intIndex) { const Coordinate &intPt=li->getIntersection(intIndex); double dist=li->getEdgeDistance(geomIndex, intIndex); addIntersection((Coordinate&)intPt, segmentIndex, dist); //delete intPt; }
/*public*/ void NodedSegmentString::addIntersection(LineIntersector *li, unsigned int segmentIndex, int geomIndex, int intIndex) { ::geos::ignore_unused_variable_warning(geomIndex); const Coordinate &intPt=li->getIntersection(intIndex); addIntersection(intPt, segmentIndex); }
// handle points void operator()(const Vec3_type v1, bool /*treatVertexDataAsTemporary*/) { ++_index; if ((_dimensionMask & PolytopeIntersector::DimZero) == 0) return; if (_limitOneIntersection && !intersections.empty()) return; for (PlaneList::const_iterator it=_planes.begin(); it!=_planes.end(); ++it) { const osg::Plane& plane=*it; const value_type d1=plane.distance(v1); if (d1<0.0f) return; // point outside } _candidates.clear(); _candidates.push_back( CandList_t::value_type(_plane_mask, v1)); addIntersection(_index, _candidates); }
bool ChartElemNavaids::addNewLatLonPoint(const QString& id, double lat, double lon, QString& err_msg) { MYASSERT(!id.isEmpty()); const Waypoint* existing_intersection = getNavaid(id, Waypoint::INTERSECTION); if (existing_intersection) { err_msg = QString("Navaids:LATLONPOINT: Intersection with ID (%1) already exists").arg(id); return false; } Intersection *intersection = new Intersection(id, lat, lon, QString::null); MYASSERT(intersection != 0); QDomDocument dom_doc = m_dom_element.ownerDocument(); QDomElement new_element = dom_doc.createElement(CHART_NODE_NAME_NAVAIDS_INTERSECTION); m_dom_element.appendChild(new_element); bool ret = addIntersection(*intersection, new_element, dom_doc, err_msg); setProjectionCenterWhenAppropriate(intersection); delete intersection; return ret; }
/** * Add an EdgeIntersection for intersection intIndex. * An intersection that falls exactly on a vertex of the edge is normalized * to use the higher of the two possible segmentIndexes */ void SegmentString::addIntersection(Coordinate& intPt, int segmentIndex) { double dist=LineIntersector::computeEdgeDistance(intPt,pts->getAt(segmentIndex),pts->getAt(segmentIndex + 1)); addIntersection(intPt, segmentIndex, dist); }
// handle triangles void operator()(const Vec3_type v1, const Vec3_type v2, const Vec3_type v3, bool /*treatVertexDataAsTemporary*/) { ++_index; if ((_dimensionMask & PolytopeIntersector::DimTwo) == 0) return; if (_limitOneIntersection && !intersections.empty()) return; PlaneMask selector_mask = 0x1; PlaneMask inside_mask = 0x0; _candidates.clear(); for(PlaneList::const_iterator it=_planes.begin(); it!=_planes.end(); ++it, selector_mask <<= 1) { const osg::Plane& plane=*it; const value_type d1=plane.distance(v1); const value_type d2=plane.distance(v2); const value_type d3=plane.distance(v3); const bool d1IsNegative = (d1<0.0f); const bool d2IsNegative = (d2<0.0f); const bool d3IsNegative = (d3<0.0f); if (d1IsNegative && d2IsNegative && d3IsNegative) return; // triangle outside if (!d1IsNegative && !d2IsNegative && !d3IsNegative) { inside_mask |= selector_mask; continue; // completly inside } // edge v1-v2 intersects if (d1==0.0f) { _candidates.push_back( CandList_t::value_type(selector_mask, v1) ); } else if (d2==0.0f) { _candidates.push_back( CandList_t::value_type(selector_mask, v2) ); } else if (d1IsNegative && !d2IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v1-(v2-v1)*(d1/(-d1+d2))) ) ); } else if (!d1IsNegative && d2IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v1+(v2-v1)*(d1/(d1-d2))) ) ); } // edge v1-v3 intersects if (d3==0.0f) { _candidates.push_back( CandList_t::value_type(selector_mask, v3) ); } else if (d1IsNegative && !d3IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v1-(v3-v1)*(d1/(-d1+d3))) ) ); } else if (!d1IsNegative && d3IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v1+(v3-v1)*(d1/(d1-d3))) ) ); } // edge v2-v3 intersects if (d2IsNegative && !d3IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v2-(v3-v2)*(d2/(-d2+d3))) ) ); } else if (!d2IsNegative && d3IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v2+(v3-v2)*(d2/(d2-d3))) ) ); } } if (_plane_mask==inside_mask) { // triangle lies inside of all planes _candidates.push_back( CandList_t::value_type(_plane_mask, v1) ); _candidates.push_back( CandList_t::value_type(_plane_mask, v2) ); _candidates.push_back( CandList_t::value_type(_plane_mask, v3) ); addIntersection(_index, _candidates); return; } if (_candidates.empty() && _planes.size()<3) return; unsigned int numCands=checkCandidatePoints(inside_mask); if (numCands>0) { addIntersection(_index, _candidates); return; } // handle case where the polytope goes through the triangle // without containing any point of it LinesList& lines=getPolytopeLines(); _candidates.clear(); // check all polytope lines against the triangle // use algorithm from "Real-time rendering" (second edition) pp.580 const Vec3_type e1=v2-v1; const Vec3_type e2=v3-v1; for (LinesList::const_iterator it=lines.begin(); it!=lines.end(); ++it) { const PlanesLine& line=*it; Vec3_type p=line.dir^e2; const value_type a=e1*p; if (osg::absolute(a)<eps()) continue; const value_type f=1.0f/a; const Vec3_type s=(line.pos-v1); const value_type u=f*(s*p); if (u<0.0f || u>1.0f) continue; const Vec3_type q=s^e1; const value_type v=f*(line.dir*q); if (v<0.0f || u+v>1.0f) continue; const value_type t=f*(e2*q); _candidates.push_back(CandList_t::value_type(line.mask, line.pos+line.dir*t)); } numCands=checkCandidatePoints(inside_mask); if (numCands>0) { addIntersection(_index, _candidates); return; } }
// handle lines void operator()(const Vec3_type v1, const Vec3_type v2, bool /*treatVertexDataAsTemporary*/) { ++_index; if ((_dimensionMask & PolytopeIntersector::DimOne) == 0) return; if (_limitOneIntersection && !intersections.empty()) return; PlaneMask selector_mask = 0x1; PlaneMask inside_mask = 0x0; _candidates.clear(); bool v1Inside = true; bool v2Inside = true; for (PlaneList::const_iterator it=_planes.begin(); it!=_planes.end(); ++it, selector_mask<<=1) { const osg::Plane& plane=*it; const value_type d1=plane.distance(v1); const value_type d2=plane.distance(v2); const bool d1IsNegative = (d1<0.0f); const bool d2IsNegative = (d2<0.0f); if (d1IsNegative && d2IsNegative) return; // line outside if (!d1IsNegative && !d2IsNegative) { inside_mask |= selector_mask; continue; // completly inside } if (d1IsNegative) v1Inside = false; if (d2IsNegative) v2Inside = false; if (d1==0.0f) { _candidates.push_back( CandList_t::value_type(selector_mask, v1) ); } else if (d2==0.0f) { _candidates.push_back( CandList_t::value_type(selector_mask, v2) ); } else if (d1IsNegative && !d2IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v1-(v2-v1)*(d1/(-d1+d2))) ) ); } else if (!d1IsNegative && d2IsNegative) { _candidates.push_back( CandList_t::value_type(selector_mask, (v1+(v2-v1)*(d1/(d1-d2))) ) ); } } if (inside_mask==_plane_mask) { _candidates.push_back( CandList_t::value_type(_plane_mask, v1) ); _candidates.push_back( CandList_t::value_type(_plane_mask, v2) ); addIntersection(_index, _candidates); return; } unsigned int numCands=checkCandidatePoints(inside_mask); if (numCands>0) { if (v1Inside) _candidates.push_back( CandList_t::value_type(_plane_mask, v1) ); if (v2Inside) _candidates.push_back( CandList_t::value_type(_plane_mask, v2) ); addIntersection(_index, _candidates); } }
bool ChartElemNavaids::loadFromDomElement(QDomElement& dom_element, QDomDocument& dom_doc, QString& err_msg) { MYASSERT(!dom_element.isNull()); TreeBaseXML::loadFromDomElement(dom_element, dom_doc, err_msg); if (m_dom_element.tagName() != CHART_NODE_NAME_NAVAIDS) { err_msg = QString("Wrong node name (%s), expected (%s)"). arg(m_dom_element.tagName()).arg(CHART_NODE_NAME_NAVAIDS); return false; } // loop through all navaids QDomNode node = m_dom_element.firstChild(); for(; !node.isNull(); node = node.nextSibling()) { QDomElement element = node.toElement(); if (element.isNull()) continue; // extract info from node QString id = element.attribute(CHART_ATTR_ID); QString ctry = element.attribute(CHART_ATTR_CTRY); QString name = element.attribute(CHART_ATTR_NAME); double lat = element.attribute(CHART_ATTR_LAT).toDouble(); double lon = element.attribute(CHART_ATTR_LON).toDouble(); int freq = element.attribute(CHART_ATTR_FREQ).toUInt(); bool has_dme = element.attribute(CHART_ATTR_DME).toInt(); int elevation = element.attribute(CHART_ATTR_ELEV).toInt(); // check info if (id.isEmpty()) { err_msg = QString("Navaids: Missing ID at tag named (%1)").arg(element.tagName()); return false; } // process element if (element.tagName() == CHART_NODE_NAME_NAVAIDS_VOR) { Vor* vor = 0; if (!name.isEmpty() && lat != 0.0 && lon != 0.0 && freq != 0) vor = new Vor(id, name, lat, lon, freq, has_dme, 0, 0, ctry); else vor = (Vor*)m_chart_model->getNavdata()->getElementsWithSignal( id, ctry, Waypoint::VOR); if (!vor) { err_msg = QString("Navaids:VOR: unknown VOR with ID (%1)").arg(id); return false; } if (!addVor(*vor, element, dom_doc, err_msg)) { node = node.previousSibling(); m_dom_element.removeChild(element); } delete vor; } else if (element.tagName() == CHART_NODE_NAME_NAVAIDS_NDB) { Ndb* ndb = 0; if (!name.isEmpty() && lat != 0.0 && lon != 0.0 && freq != 0) ndb = new Ndb(id, name, lat, lon, freq, 0, 0, ctry); else ndb = (Ndb*)m_chart_model->getNavdata()->getElementsWithSignal( id, ctry, Waypoint::NDB); if (!ndb) { err_msg = QString("Navaids:NDB: unknown NDB with ID (%1)").arg(id); return false; } if (!addNdb(*ndb, element, dom_doc, err_msg)) { node = node.previousSibling(); m_dom_element.removeChild(element); } delete ndb; } else if (element.tagName() == CHART_NODE_NAME_NAVAIDS_AIRPORT) { Airport* airport = 0; if (!name.isEmpty() && lat != 0.0 && lon != 0.0 && element.hasAttribute(CHART_ATTR_ELEV)) airport = new Airport(id, name, lat, lon, elevation); else airport = (Airport*)m_chart_model->getNavdata()->getElementsWithSignal( id, ctry, Waypoint::AIRPORT); if (!airport) { err_msg = QString("Navaids:AIRPORT: unknown AIRPORT with ID (%1)").arg(id); return false; } if (!addAirport(*airport, element, dom_doc, err_msg)) { node = node.previousSibling(); m_dom_element.removeChild(element); } delete airport; } else if (element.tagName() == CHART_NODE_NAME_NAVAIDS_INTERSECTION) { Intersection* intersection = 0; if (lat != 0.0 && lon != 0.0) intersection = new Intersection(id, lat, lon, ctry); else intersection = (Intersection*)m_chart_model->getNavdata()->getElementsWithSignal( id, ctry, Waypoint::INTERSECTION); if (!intersection) { err_msg = QString("Navaids:INTERSECTION: unknown INTERSECTION with ID (%1)").arg(id); return false; } if (!addIntersection(*intersection, element, dom_doc, err_msg)) { node = node.previousSibling(); m_dom_element.removeChild(element); } delete intersection; } } return true; }