void EastArrowObjectImp::orient() { if (isOriented() == true) { return; } GraphicLayer* pLayer = NULL; pLayer = getLayer(); if (pLayer == NULL) { return; } View* pView = NULL; pView = pLayer->getView(); if (pView == NULL) { return; } SpatialDataView* pSpatialDataView = NULL; if (pView->isKindOf("SpatialDataView") == true) { pSpatialDataView = static_cast<SpatialDataView*> (pView); } else if (pView->isKindOf("ProductView") == true) { ProductView* pProductView = static_cast<ProductView*> (pView); GraphicLayer* pLayoutLayer = NULL; pLayoutLayer = pProductView->getLayoutLayer(); if (pLayoutLayer == pLayer) { list<GraphicObject*> viewObjects; pLayoutLayer->getObjects(VIEW_OBJECT, viewObjects); list<GraphicObject*>::iterator iter = viewObjects.begin(); while (iter != viewObjects.end()) { GraphicObject* pObject = *iter; if (pObject != NULL) { View* pObjectView = pObject->getObjectView(); if (pObjectView != NULL) { if (pObjectView->isKindOf("SpatialDataView") == true) { pSpatialDataView = static_cast<SpatialDataView*> (pObjectView); } } } ++iter; } } } if (pSpatialDataView == NULL) { return; } LayerList* pLayerList = pSpatialDataView->getLayerList(); VERIFYNRV(pLayerList != NULL); RasterElement* pRaster = pLayerList->getPrimaryRasterElement(); VERIFYNRV(pRaster != NULL); if (!pRaster->isGeoreferenced()) { return; } // Calculate the angle of the object relative to the pixel coordinates updateHandles(); LocationType pixelStart = mHandles[7]; ProductView* pProductView = dynamic_cast<ProductView*> (pView); if (pProductView != NULL) { // Convert to the screen coordinate system double dScreenX = 0; double dScreenY = 0; pLayer->translateDataToWorld(pixelStart.mX, pixelStart.mY, pixelStart.mX, pixelStart.mY); pProductView->translateWorldToScreen(pixelStart.mX, pixelStart.mY, dScreenX, dScreenY); // Convert to the spatial data view coordinate system pSpatialDataView->translateScreenToWorld(dScreenX, dScreenY, pixelStart.mX, pixelStart.mY); pLayer->translateWorldToData(pixelStart.mX, pixelStart.mY, pixelStart.mX, pixelStart.mY); } double dAngle; if (GeoAlgorithms::getAngleToNorth(pRaster, dAngle, pixelStart) == false) { return; } // Update the angle if the object is in the layout layer if (pProductView != NULL) { // Rotation dAngle -= pSpatialDataView->getRotation(); // Pitch double dPitch = pSpatialDataView->getPitch(); if (dPitch > 0.0) { dAngle *= -1.0; } } // Rotate the object setRotation(dAngle); // Update the orientation flag DirectionalArrowObjectImp::orient(); }
void MeasurementObjectImp::draw(double zoomFactor) const { const_cast<MeasurementObjectImp*>(this)->updateGeoreferenceAttachment(); // Verify that factor values are valid if ((mArrowRelStartLoc < 0.0) || (mArrowRelStartLoc > mArrowRelEndLoc) || (mArrowRelStartLoc > 1.0) || (mArrowRelEndLoc < 0.0) || (mArrowRelEndLoc > 1.0) || (mBarEndLength < 0)) { return; } // Draw the main line LineObjectImp::draw(zoomFactor); // Get the current view SpatialDataView* pView = NULL; MeasurementLayerImp* pLayer = dynamic_cast<MeasurementLayerImp*>(getLayer()); if (pLayer != NULL) { pView = dynamic_cast<SpatialDataView*>(pLayer->getView()); } if (pView == NULL) { return; } // Misc Variables LocationType junkLocation; // junk variable used to call methods that require unneeded parameters double startPerc = 0.0; // The relative start location along a line to start drawing double lineLength = 0; // The length of the main line double pixelSize = 0; // The number of screen pixels in a scene pixel double lineWidth = 0; // The width of the main line double sqrtLineWidth = 0; // The square root of the line width LocationType llCorner; // lower left corner of annotation bounding box LocationType urCorner; // upper right corner of annotation bounding box ColorType textColor; // The color to draw the text ColorType lineColor; // The color to draw the line ColorType fillColor; // The color to draw the stippled line // Misc Calculations pixelSize = DrawUtil::getPixelSize(junkLocation.mX, junkLocation.mY, junkLocation.mX, junkLocation.mY); llCorner = getLlCorner(); urCorner = getUrCorner(); lineWidth = getLineWidth(); sqrtLineWidth = sqrt(lineWidth); textColor = getTextColor(); lineLength = sqrt(pow(abs(urCorner.mX - llCorner.mX), 2) + pow(abs(urCorner.mY - llCorner.mY), 2)); lineColor = getLineColor(); fillColor = getFillColor(); // Get text font info (used for all text, set to italic if using inaccurate extrapolation) QFont font = getFont(); font.setItalic(mUsingInaccurateGeocoords); // Calculate arrow info (line only) LocationType arrowStartPoint; // The start point of the arrow line LocationType arrowEndPoint; // The end point of the arrow line double arrowOffset = 0; // Normal offset from main line to arrow double arrowLength = 0; // The length of the arrow line (in pixels) arrowOffset = (pixelSize == 0.0) ? 0.0 : mArrowOffset * sqrtLineWidth / pixelSize; DrawUtil::getParallelLine(llCorner, urCorner, arrowOffset, mArrowRelStartLoc, mArrowRelEndLoc, arrowStartPoint, arrowEndPoint); arrowLength = sqrt(pow(abs(arrowEndPoint.mX - arrowStartPoint.mX), 2) + pow(abs(arrowEndPoint.mY - arrowStartPoint.mY), 2)); // Calculate arrow head info (Only half arrow head is drawn) LocationType arrowHeadBasePoint; // Location of arrow head base point double arrowHeadOffset = 0; // Perpendicular offset from arrow line to arrow head base arrowHeadOffset = (pixelSize == 0.0) ? 0.0 : (mArrowHeadOffset * sqrtLineWidth) / pixelSize; // Adjust arrow head size if arrow length becomes smaller then arrow head length. while (arrowHeadOffset > arrowLength) { // Since arrow head is at 45 degree angle, arrowHeadOffset is same as arrow head length // Adjust size of arrow head if (arrowHeadOffset >= 1) { arrowHeadOffset -= 1; } else if (arrowHeadOffset > .2) { arrowHeadOffset = arrowHeadOffset - .1; } else { break; } arrowHeadOffset = (arrowHeadOffset < 0) ? 0.0 : arrowHeadOffset; } // Get arrow head base point coordinates from calculated arrow head info startPerc = (arrowLength == 0.0) ? 0.0 : 1 - (arrowHeadOffset/arrowLength); startPerc = (startPerc < 0.0) ? 0.0 : startPerc; startPerc = (startPerc > 1.0) ? 1.0 : startPerc; DrawUtil::getParallelLine(arrowStartPoint, arrowEndPoint, arrowHeadOffset, startPerc, 1.0f, arrowHeadBasePoint, junkLocation); // End bar coordinates LocationType barStartPoint1; LocationType barStartPoint2; // The points that make up the start bar-end (ll corner) LocationType barEndPoint1; LocationType barEndPoint2; // The points that make up the end bar-end (ur corner) double barLength = 0; // Bar-ends length barLength = (pixelSize == 0.0) ? 0.0 : (mBarEndLength * sqrtLineWidth) / pixelSize; DrawUtil::getPerpendicularLine(llCorner, urCorner, barLength, barStartPoint1, barStartPoint2); DrawUtil::getPerpendicularLine(urCorner, llCorner, barLength, barEndPoint1, barEndPoint2); // Calculate text info double textOffset = 0; // Perpendicular offset from text to text anchor int maxTextureSize = 0; // The max allowable texture size textOffset = (pixelSize == 0.0) ? 0.0 : (mTextOffset * sqrtLineWidth) / pixelSize; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); QFontMetrics ftMetrics(font); double viewRotation = pView->getRotation(); viewRotation = GeoConversions::convertDegToRad(viewRotation); if (mDrawnDistanceUnit != pLayer->getDistanceUnits() || mDrawnGeocoord != pLayer->getGeocoordType() || mDrawnDmsFormat != pLayer->getGeoFormat()) { refreshGeoInformation(); // only modifies cache stuff } if (pLayer->getDisplayEndPoints()) { // Calculate start and end text info bool startLocDrawTop = false; // Whether to draw the start lat/lon text on the top of the specified point bool endLocDrawTop = true; // Whether to draw the end lat/lon text on the top of the specified point if (urCorner.mY < llCorner.mY) { startLocDrawTop = true; endLocDrawTop = false; } // Calculate start and end location text info LocationType startLocPoint; // The location to display the "start location" text LocationType endLocPoint; // The location to display the "end location" text startLocPoint = llCorner; endLocPoint = urCorner; startLocPoint.mY += textOffset; endLocPoint.mY += textOffset; if (!mStartLocText.isEmpty()) { DrawUtil::drawRotatedText(mStartLocTextTexture, mStartLocText, font, textColor, startLocPoint, viewRotation, startLocDrawTop); } if (!mEndLocText.isEmpty()) { DrawUtil::drawRotatedText(mEndLocTextTexture, mEndLocText, font, textColor, endLocPoint, viewRotation, endLocDrawTop); } } if (pLayer->getDisplayBearing()) { // Calculate bearing text info LocationType bearingTextStartPoint; // The location to display the bearing text LocationType bearingTextEndPoint; // The pseudo end location of the baring text (only used to calculate angle) double bearingTextTheta = 0; // Angle (in radians) of bearing text bool bearingDrawTop = false; // The vertical origin to draw text from (True = top, False = bottom) QRect bearingTextBoundingBox; // Bounding box surrounding the bearing text bearingTextBoundingBox = ftMetrics.boundingRect(0, 0, maxTextureSize, maxTextureSize, Qt::AlignLeft | Qt::TextWordWrap, mBearingText); if (arrowEndPoint.mX < arrowStartPoint.mX) // To the left of the origin (text underneath line) { startPerc = ((pixelSize == 0.0) || (arrowLength == 0.0)) ? 0.0 : 1.0 - (bearingTextBoundingBox.width()/pixelSize)/arrowLength; startPerc = (startPerc < 0.0) ? 0.0 : startPerc; startPerc = (startPerc > 1.0) ? 1.0 : startPerc; DrawUtil::getParallelLine(arrowEndPoint, arrowStartPoint, (-1) * textOffset, startPerc, 1.0f, bearingTextStartPoint, bearingTextEndPoint); bearingDrawTop = true; } else // To the right of the origin (text on top of the line) { DrawUtil::getParallelLine(arrowStartPoint, arrowEndPoint, textOffset, 0.0f, 1.0f, bearingTextStartPoint, bearingTextEndPoint); bearingDrawTop = false; } bearingTextTheta = ((bearingTextEndPoint.mX - bearingTextStartPoint.mX) == 0.0) ? 0.0 : atan((bearingTextEndPoint.mY - bearingTextStartPoint.mY) / (bearingTextEndPoint.mX - bearingTextStartPoint.mX)); if (!mBearingText.isEmpty()) { DrawUtil::drawRotatedText(mBearingTextTexture, mBearingText, font, textColor, bearingTextStartPoint, bearingTextTheta, bearingDrawTop); } } if (pLayer->getDisplayDistance()) { // Calculate distance text info LocationType distanceTextStartPoint; // The location to display the distance text LocationType distanceTextEndPoint; // The pseudo end location of the distance text (only used to calculate // angle) double distanceTextTheta = 0; // Angle (in radians) of distnace text bool distanceDrawTop = false; // The vertical origin to draw text from (True = top, False = bottom) double distanceTextWidth = 0; // The width of the ditance text bounding box (in screen pixels) QRect distanceTextBoundingBox; // Bounding box that surrounds the distance text distanceTextBoundingBox = ftMetrics.boundingRect(0, 0, maxTextureSize, maxTextureSize, Qt::AlignLeft | Qt::TextWordWrap, mDistanceText); distanceTextWidth = distanceTextBoundingBox.width(); if ((pixelSize == 0.0) || (lineLength == 0.0)) { startPerc = 0.0; } else { if (urCorner.mX < llCorner.mX) { startPerc = .5 + (distanceTextWidth/pixelSize/2)/lineLength; distanceDrawTop = false; } else { startPerc = .5 - (distanceTextWidth/pixelSize/2)/lineLength; distanceDrawTop = true; } } startPerc = (startPerc < 0.0) ? 0.0 : startPerc; startPerc = (startPerc > 1.0) ? 1.0 : startPerc; DrawUtil::getParallelLine(llCorner, urCorner, (-1) * textOffset, startPerc, 1.0f, distanceTextStartPoint, distanceTextEndPoint); if (lineLength < (distanceTextBoundingBox.width()/pixelSize)) { if (urCorner.mX < llCorner.mX) { DrawUtil::getParallelLine(llCorner, urCorner, (-1) * textOffset, 0.0f, 1.0f, distanceTextEndPoint, distanceTextStartPoint); } else { DrawUtil::getParallelLine(llCorner, urCorner, (-1) * textOffset, 0.0f, 1.0f, distanceTextStartPoint, distanceTextEndPoint); } } distanceTextTheta = ((distanceTextEndPoint.mX - distanceTextStartPoint.mX) == 0.0) ? 0.0 : atan((distanceTextEndPoint.mY - distanceTextStartPoint.mY) / (distanceTextEndPoint.mX - distanceTextStartPoint.mX)); if (!mDistanceText.isEmpty()) { DrawUtil::drawRotatedText(mDistanceTextTexture, mDistanceText, font, textColor, distanceTextStartPoint, distanceTextTheta, distanceDrawTop); } } // GL options glLineWidth(lineWidth); #if defined(WIN_API) glEnable(GL_LINE_SMOOTH); #else if (lineWidth == 1.0) { glEnable(GL_LINE_SMOOTH); } else { glDisable(GL_LINE_SMOOTH); } #endif glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor3ub(lineColor.mRed, lineColor.mGreen, lineColor.mBlue); // Draw the end bar glBegin(GL_LINE_STRIP); glVertex2d(barEndPoint1.mX, barEndPoint1.mY); glVertex2d(barEndPoint2.mX, barEndPoint2.mY); glEnd(); // Draw the start bar glBegin(GL_LINE_STRIP); glVertex2d(barStartPoint1.mX, barStartPoint1.mY); glVertex2d(barStartPoint2.mX, barStartPoint2.mY); glEnd(); // Draw the arrow if bearing is displayed if (pLayer->getDisplayBearing()) { glBegin(GL_LINE_STRIP); glVertex2d(arrowStartPoint.mX, arrowStartPoint.mY); glVertex2d(arrowEndPoint.mX, arrowEndPoint.mY); glVertex2d(arrowHeadBasePoint.mX, arrowHeadBasePoint.mY); glEnd(); } // Set GL options to draw stippled line (Main line) glEnable(GL_LINE_STIPPLE); glLineStipple(3, 0xf0f0); glColor3ub(fillColor.mRed, fillColor.mGreen, fillColor.mBlue); // Draw the stippled line (on top of regular line) glBegin(GL_LINE_STRIP); glVertex2d(llCorner.mX, llCorner.mY); glVertex2d(urCorner.mX, urCorner.mY); glEnd(); // Reset GL options glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glDisable(GL_LINE_SMOOTH); glDisable(GL_LINE_STIPPLE); glLineWidth(1); }