bool XipGeomUtils::isOnPlane(const SbVec3f& pt, const SbPlane &plane) { float dist = pt.dot(plane.getNormal()) - plane.getDistanceFromOrigin(); if ( fabs(dist)<XIP_EPSILON ) return true; return false; }
void SoOrthoSlice::rayPick(SoRayPickAction * action) { if (!this->shouldRayPick(action)) return; SoState * state = action->getState(); if (!PRIVATE(this)->confirmValidInContext(state)) { return; } const CvrVoxelBlockElement * vbelem = CvrVoxelBlockElement::getInstance(state); if (vbelem == NULL) { return; } this->computeObjectSpaceRay(action); const SbLine & ray = action->getLine(); const SbPlane sliceplane = PRIVATE(this)->getSliceAsPlane(action); SbVec3f intersection; if (sliceplane.intersect(ray, intersection) && // returns FALSE if parallel action->isBetweenPlanes(intersection)) { SbVec3s ijk = vbelem->objectCoordsToIJK(intersection); const SbVec3s & voxcubedims = vbelem->getVoxelCubeDimensions(); const SbBox3s voxcubebounds(SbVec3s(0, 0, 0), voxcubedims - SbVec3s(1, 1, 1)); if (voxcubebounds.intersect(ijk)) { SoPickedPoint * pp = action->addIntersection(intersection); // if NULL, something else is obstructing the view to the // volume, the app programmer only want the nearest, and we // don't need to continue our intersection tests if (pp == NULL) return; pp->setObjectNormal(sliceplane.getNormal()); SoOrthoSliceDetail * detail = new SoOrthoSliceDetail; pp->setDetail(detail, this); detail->objectcoords = intersection; detail->ijkcoords = ijk; detail->voxelvalue = vbelem->getVoxelValue(ijk); if (CvrUtil::useFlippedYAxis()) { static SbBool flag = FALSE; if (!flag) { SoDebugError::postWarning("SoOrthoSlice::rayPick", "RayPick'ing will not be correct for SoOrthoSlice when the " "obsolete CVR_USE_FLIPPED_Y_AXIS envvar is active."); flag = TRUE; } } } } // Common clipping plane handling. SoOrthoSlice::doAction(action); }
bool XipGeomUtils::intersect(const SbVec3f &u, const SbVec3f &v, const SbPlane &plane, SbVec3f &pt) { float d0 = u.dot(plane.getNormal()) - plane.getDistanceFromOrigin(); float d1 = v.dot(plane.getNormal()) - plane.getDistanceFromOrigin(); if ( d0*d1> -XIP_EPSILON ) return false; return XipGeomUtils::intersect(SbLine(u, v), plane, pt); }
bool XipGeomUtils::isIntersect(const SbVec3f &u, const SbVec3f &v, const SbPlane &plane) { float d0 = u.dot(plane.getNormal()) - plane.getDistanceFromOrigin(); float d1 = v.dot(plane.getNormal()) - plane.getDistanceFromOrigin(); if ( d0*d1>XIP_EPSILON ) return false; return true; }
// Write SbPlane value to output stream. Used from SoSFPlane and // SoMFPlane. void sosfplane_write_value(SoOutput * out, const SbPlane & p) { out->write(p.getNormal()[0]); if (!out->isBinary()) out->write(' '); out->write(p.getNormal()[1]); if (!out->isBinary()) out->write(' '); out->write(p.getNormal()[2]); if (!out->isBinary()) out->write(" "); out->write(p.getDistanceFromOrigin()); }
/*! Clip polygon against \a plane. This might change the number of vertices in the polygon. For each time a new vertex is created, the callback supplied in the constructor (if != NULL) is called with the line being clipped and the new vertex calculated. The callback should return a new void pointer to be stored by the clipper. */ void SbClip::clip(const SbPlane & plane) { int n = this->array[this->curr].getLength(); if (n == 0) return; // create loop SbClipData dummy = this->array[this->curr][0]; this->array[this->curr].append(dummy); const SbVec3f & planeN = plane.getNormal(); for (int i = 0; i < n; i++) { SbVec3f v0, v1; void * data0, *data1; this->array[this->curr][i].get(v0, data0); this->array[this->curr][i+1].get(v1, data1); float d0 = plane.getDistance(v0); float d1 = plane.getDistance(v1); if (d0 >= 0.0f && d1 < 0.0f) { // exit plane SbVec3f dir = v1-v0; // we know that v0 != v1 since we got here (void) dir.normalize(); float dot = dir.dot(planeN); SbVec3f newvertex = v0 - dir * (d0/dot); void * newdata = NULL; if (this->callback) { newdata = this->callback(v0, data0, v1, data1, newvertex, this->cbdata); } outputVertex(newvertex, newdata); } else if (d0 < 0.0f && d1 >= 0.0f) { // enter plane SbVec3f dir = v1-v0; // we know that v0 != v1 since we got here (void) dir.normalize(); float dot = dir.dot(planeN); SbVec3f newvertex = v0 - dir * (d0/dot); void * newdata = NULL; if (this->callback) { newdata = this->callback(v0, data0, v1, data1, newvertex, this->cbdata); } outputVertex(newvertex, newdata); outputVertex(v1, data1); } else if (d0 >= 0.0f && d1 >= 0.0f) { // in plane outputVertex(v1, data1); } } this->array[this->curr].truncate(0); this->curr ^= 1; }
Base::Vector3f ViewVolumeProjection::inverse (const Base::Vector3f &pt) const { #if 1 SbVec3f pt3d(2.0f*pt.x-1.0f, 2.0f*pt.y-1.0f, 2.0f*pt.z-1.0f); viewVolume.getMatrix().inverse().multVecMatrix(pt3d, pt3d); #elif 1 SbLine line; SbVec3f pt3d; SbPlane distPlane = viewVolume.getPlane(viewVolume.getNearDist()); viewVolume.projectPointToLine(SbVec2f(pt.x,pt.x), line); distPlane.intersect(line, pt3d); #else SbVec3f pt3d = viewVolume.getPlanePoint(viewVolume.getNearDist(), SbVec2f(pt.x,pt.y)); #endif return Base::Vector3f(pt3d[0],pt3d[1],pt3d[2]); }
void ObjectSimpleViewer:: stateChanged( ClipPlaneButton::statetype state) { switch(state) { case ClipPlaneButton::ClipOn: { if(!m_clipPlaneManip) { //create at first use m_clipPlaneManip = new SoClipPlaneManip; m_clipPlaneManip->ref(); SoGetBoundingBoxAction ba(m_viewer->getViewportRegion()); ba.apply(blinker_root); SbBox3f box = ba.getBoundingBox(); m_clipPlaneManip->setValue(box, SbVec3f(1.0f, 0.0f, 0.0f), 1.00f); } SbPlane plane = m_clipPlaneManip->plane.getValue(); m_clipPlaneManip->plane.setValue(SbPlane(-plane.getNormal(), -plane.getDistanceFromOrigin())); emit addedClipPlane(m_clipPlaneManip); //remove ortho slices } break; case ClipPlaneButton::ClipOff: emit addedClipPlane(NULL); //remove ortho slices break; case ClipPlaneButton::ClipOnly: if(!m_clipPlane) { //create at first use if(!m_clipPlaneManip) { //create at first use m_clipPlaneManip = new SoClipPlaneManip; m_clipPlaneManip->ref(); } m_clipPlane = new SoClipPlane; m_clipPlane->ref(); m_clipPlane->plane.connectFrom(&(m_clipPlaneManip->plane)); } emit addedClipPlane(m_clipPlane); //remove ortho slices break; } }
bool XipGeomUtils::intersect(const SbLine &line, const SbPlane &plane, SbVec3f &pt) { float t, denom; // solve for t: // n . (l.p + t * l.d) - d == 0 denom = plane.getNormal().dot(line.getDirection()); if ( fabs(denom) < XIP_EPSILON ) return FALSE; // t = - (n . l.p - d) / (n . l.d) t = - (plane.getNormal().dot(line.getPosition()) - plane.getDistanceFromOrigin()) / denom; pt = line.getPosition() + t * line.getDirection(); return TRUE; }
void SoXipDicomExaminer::rayPick( SoRayPickAction* action ) { // Set the Dicom Element setElement( action ); action->getState()->push(); action->traverse( getCamera() ); action->setObjectSpace(); const SbViewVolume& viewVolume = getCamera()->getViewVolume(); const SbLine& line = action->getLine(); // Intersect the focal plane with the picking ray SbPlane plane = viewVolume.getPlane(-0.0001f); SbVec3f intersection; if( plane.intersect( line, intersection ) ) action->addIntersection( intersection ); action->getState()->pop(); SoXipKit::rayPick( action ); }
SbBool XipGeomUtils::planeIntersect(const SbPlane & p1, const SbPlane & p2, SbLine & line) { // Based on code from Graphics Gems III, Plane-to-Plane Intersection // by Priamos Georgiades // http://www.cs.ualberta.ca/~graphics/books/GraphicsGems/gemsiii/pl2plane.c float invdet; // inverse of 2x2 matrix determinant SbVec3f dir2; // holds the squares of the coordinates of xdir SbVec3f xpt; SbVec3f xdir; xdir = p1.getNormal().cross(p2.getNormal()); dir2[0] = xdir[0] * xdir[0]; dir2[1] = xdir[1] * xdir[1]; dir2[2] = xdir[2] * xdir[2]; const SbVec3f & pl1n = p1.getNormal(); const SbVec3f & pl2n = p2.getNormal(); const float pl1w = - p1.getDistanceFromOrigin(); const float pl2w = - p2.getDistanceFromOrigin(); if ( (dir2[2] > dir2[1]) && (dir2[2] > dir2[0]) && (dir2[2] > XIP_FLT_EPSILON) ) { // then get a point on the XY plane invdet = 1.0f / xdir[2]; xpt = SbVec3f( pl1n[1] * pl2w - pl2n[1] * pl1w, pl2n[0] * pl1w - pl1n[0] * pl2w, 0.0f); } else if ( (dir2[1] > dir2[0]) && (dir2[1] > XIP_FLT_EPSILON) ) { // then get a point on the XZ plane invdet = -1.0f / xdir[1]; xpt = SbVec3f( pl1n[2] * pl2w - pl2n[2] * pl1w, 0.0f, pl2n[0] * pl1w - pl1n[0] * pl2w); } else if (dir2[0] > XIP_FLT_EPSILON) { // then get a point on the YZ plane invdet = 1.0f / xdir[0]; xpt = SbVec3f( 0.0f, pl1n[2] * pl2w - pl2n[2] * pl1w, pl2n[1] * pl1w - pl1n[1] * pl2w); } else { // xdir is zero, then no point of intersection exists return FALSE; } xpt *= invdet; invdet = 1.0f / (float) sqrt(dir2[0] + dir2[1] + dir2[2]); xdir *= invdet; line = SbLine(xpt, xpt+xdir); return TRUE; }
void SoXipMprIntersectionPlanes::GLRender(SoGLRenderAction * action) { if (!mIntersectionPlane || !mColor) return; if (!on.getValue()) return; // check state SoState *state = action->getState(); if (!state) return; SoXipMprPlaneElement *element = SoXipMprPlaneElement::getInstance(state); if (!element) return; int numPlanes = element->getNum(); if (numPlanes <= 0) return; GLboolean lightEnabled = glIsEnabled(GL_LIGHTING); glDisable(GL_LIGHTING); mIntersectionPlane->boundingBox.setValue(viewBoundingBox.getValue()); SbPlane plane; SbColor color; for (int i = 0; i < numPlanes; i++) { plane = XipGeomUtils::planeFromMatrix(element->getMatrix(i)); color = element->getColor(i); if (i > 0) { SbPlane newPlane = mIntersectionPlane->plane.getValue(); if ((newPlane.getNormal() - plane.getNormal()).length() < 0.001) { if (fabs(newPlane.getDistanceFromOrigin() - plane.getDistanceFromOrigin()) <= 0.001) { continue; } } } mIntersectionPlane->plane.setValue(plane); if ((parts.getValue() == BACK) || (parts.getValue() == ALL)) { mColor->rgb.setValue(color * 0.6f); mIntersectionPlane->parts.setValue(SoXipIntersectionPlane::BACK); action->traverse(mSeparator); } if ((parts.getValue() == FRONT) || (parts.getValue() == ALL)) { mColor->rgb.setValue(color); mIntersectionPlane->parts.setValue(SoXipIntersectionPlane::FRONT); action->traverse(mSeparator); } } if (lightEnabled) glEnable(GL_LIGHTING); }
bool ObjectSimpleViewer:: saveAsXml( QXmlStreamWriter *xmlWriter) { Q_ASSERT(xmlWriter); xmlWriter->writeTextElement("Title", windowTitle()); if(m_mixSlider) { xmlWriter->writeTextElement("Mix", QString("%1").arg(m_mixSlider->value())); } xmlWriter->writeStartElement("Geometry"); const QRect geom = parentWidget()->geometry(); xmlWriter->writeTextElement("X", QString("%1").arg(geom .x())); xmlWriter->writeTextElement("Y", QString("%1").arg(geom .y())); xmlWriter->writeTextElement("Width", QString("%1").arg(geom .width())); xmlWriter->writeTextElement("Height", QString("%1").arg(geom .height())); xmlWriter->writeEndElement(); if(m_clipPlaneManip) { xmlWriter->writeStartElement("ClipPlane"); SbPlane plane = m_clipPlaneManip->plane.getValue(); SbVec3f vec = plane.getNormal(); xmlWriter->writeStartElement("Normal"); xmlWriter->writeTextElement("X", QString("%1").arg(vec[0])); xmlWriter->writeTextElement("Y", QString("%1").arg(vec[1])); xmlWriter->writeTextElement("Z", QString("%1").arg(vec[2])); xmlWriter->writeEndElement(); xmlWriter->writeTextElement("Distance", QString("%1").arg(plane.getDistanceFromOrigin())); vec = m_clipPlaneManip->draggerPosition.getValue(); xmlWriter->writeStartElement("Position"); xmlWriter->writeTextElement("X", QString("%1").arg(vec[0])); xmlWriter->writeTextElement("Y", QString("%1").arg(vec[1])); xmlWriter->writeTextElement("Z", QString("%1").arg(vec[2])); xmlWriter->writeEndElement(); SoDragger *dragger = m_clipPlaneManip->getDragger(); if(dragger && dragger->isOfType(SoJackDragger::getClassTypeId())) { SoJackDragger *jd = (SoJackDragger*)dragger; vec = jd->scaleFactor.getValue(); xmlWriter->writeStartElement("Scalefactor"); xmlWriter->writeTextElement("X", QString("%1").arg(vec[0])); xmlWriter->writeTextElement("Y", QString("%1").arg(vec[1])); xmlWriter->writeTextElement("Z", QString("%1").arg(vec[2])); xmlWriter->writeEndElement(); } xmlWriter->writeTextElement("Distance", QString("%1").arg(plane.getDistanceFromOrigin())); xmlWriter->writeEndElement(); } for(int i = 0; i < views.size(); ++i) { views.at(i)->saveAsXml(xmlWriter); } return(true); }