예제 #1
0
void TextObjectImp::draw(double zoomFactor) const
{
   RectangleObjectImp::draw(zoomFactor);
   if (QGLContext::currentContext() != mpDrawContext || mUpdateTexture == true)
   {
      (const_cast<TextObjectImp*> (this))->updateTexture();
   }

   if (mpDrawContext == NULL)
   {
      return;
   }

   LocationType llCorner = getLlCorner();
   LocationType urCorner = getUrCorner();
   glEnable(GL_TEXTURE_2D);

   // switch to using this tile's texture
   GLuint textureId = mTextureResource;
   if (mpDrawContext == mTempTextureResource.getContext())
   {
      textureId = mTempTextureResource;
   }

   glBindTexture(GL_TEXTURE_2D, textureId);

   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   double maxS = mDataWidth / static_cast<double>(mTextureWidth);
   double maxT = mDataHeight / static_cast<double>(mTextureHeight);

   ColorType color = getTextColor();
   glBegin(GL_QUADS);
   glColor4ub(color.mRed, color.mGreen, color.mBlue, 255);

   // Determine if the bounding box is flipped based on its screen locations
   bool bHorizontalFlip = false;
   bool bVerticalFlip = false;

   GraphicLayer* pLayer = getLayer();
   if (pLayer != NULL)
   {
      pLayer->isFlipped(llCorner, urCorner, bHorizontalFlip, bVerticalFlip);

      // Account for the difference between screen origin (upper left) and OpenGL origin (lower left)
      bVerticalFlip = !bVerticalFlip;
   }

   // Draw the text left to right and right side up
   if ((bHorizontalFlip == false) && (bVerticalFlip == false))
   {
      glTexCoord2f(0.0, 0.0);
      glVertex3f(llCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(maxS, 0.0);
      glVertex3f(urCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(maxS, maxT);
      glVertex3f(urCorner.mX, urCorner.mY, 0.0);

      glTexCoord2f(0.0, maxT);
      glVertex3f(llCorner.mX, urCorner.mY, 0.0);
   }
   else if ((bHorizontalFlip == true) && (bVerticalFlip == false))
   {
      glTexCoord2f(maxS, 0.0);
      glVertex3f(llCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(0.0, 0.0);
      glVertex3f(urCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(0.0, maxT);
      glVertex3f(urCorner.mX, urCorner.mY, 0.0);

      glTexCoord2f(maxS, maxT);
      glVertex3f(llCorner.mX, urCorner.mY, 0.0);
   }
   else if ((bHorizontalFlip == true) && (bVerticalFlip == true))
   {
      glTexCoord2f(maxS, maxT);
      glVertex3f(llCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(0.0, maxT);
      glVertex3f(urCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(0.0, 0.0);
      glVertex3f(urCorner.mX, urCorner.mY, 0.0);

      glTexCoord2f(maxS, 0.0);
      glVertex3f(llCorner.mX, urCorner.mY, 0.0);
   }
   else if ((bHorizontalFlip == false) && (bVerticalFlip == true))
   {
      glTexCoord2f(0.0, maxT);
      glVertex3f(llCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(maxS, maxT);
      glVertex3f(urCorner.mX, llCorner.mY, 0.0);

      glTexCoord2f(maxS, 0.0);
      glVertex3f(urCorner.mX, urCorner.mY, 0.0);

      glTexCoord2f(0.0, 0.0);
      glVertex3f(llCorner.mX, urCorner.mY, 0.0);
   }

   glEnd();

   glDisable(GL_BLEND);
   glDisable(GL_ALPHA_TEST);
   glDisable(GL_TEXTURE_2D);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

   // mTempTextureResource is allocated by the updateTexture method when the gl context has changed
   // Free the texture here; more importantly set mpDrawContext to mTextureResource so that the next
   // draw operation completes successfully without the need to recreate the texture.
   if (mTempTextureResource.get() != NULL)
   {
      TextObjectImp* pNonConst = const_cast<TextObjectImp*>(this);
      pNonConst->mTempTextureResource = GlTextureResource(0);
      pNonConst->mpDrawContext = mTextureResource.getContext();
   }
}
예제 #2
0
void ScaleBarObjectImp::updateLayout()
{
   if (mNeedsLayout == false)
   {
      return;
   }

   LocationType llCorner = getLlCorner();
   LocationType urCorner = getUrCorner();

   bool bHorizontalFlip = false;
   bool bVerticalFlip = false;

   GraphicLayer* pLayer = getLayer();
   if (pLayer != NULL)
   {
      pLayer->isFlipped(llCorner, urCorner, bHorizontalFlip, bVerticalFlip);
   }

   if (bHorizontalFlip == true)
   {
      double temp = llCorner.mX;
      llCorner.mX = urCorner.mX;
      urCorner.mX = temp;
   }

   if (bVerticalFlip == true)
   {
      double temp = llCorner.mY;
      llCorner.mY = urCorner.mY;
      urCorner.mY = temp;
   }

   double barHeight = urCorner.mY - llCorner.mY;

   double spacingScale = 1.0;
   string unitsText = "pix";
   double unitScale = 1.0; //mXgsd is calculated in meters
   if (mpGeoreference.get() != NULL)
   {
      if (getUnitSystem() == UNIT_KFT)
      {
         unitsText = "ft";
      }
      else if (getUnitSystem() == UNIT_KM)
      {
         unitsText = "m";
      }
      else if (getUnitSystem() == UNIT_MI)
      {
         unitsText = "mi";
      }

      // if the scalebar is an object in the layout layer, we need to scale the
      // scalebar length to scene pixels from page coordinates
      if (getUnitSystem() == UNIT_KFT)
      {
         unitScale = GeoConversions::convertMetersToFeet(1);
      }
      else if (getUnitSystem() == UNIT_MI)
      {
         unitScale = GeoConversions::convertMetersToMiles(1);
      }
   }
   else
   {
      mXgsd = 1.0;
   }

   double deltaX = urCorner.mX - llCorner.mX;
   double lengthBar = fabs(deltaX * mXgsd * unitScale);
   double totalLengthPixels = fabs(deltaX);
   double ticksize = 0.0; //ticksize in pixels
   double ticksizeDistance = pow(10.0, floor(log10(lengthBar / 5.0))); //ticksize in specific units (feet or meters)

   if (ticksizeDistance * 5.0 * 5.0 > lengthBar)
   {
      if (ticksizeDistance * 2.0 * 5.0 > lengthBar)
      {
         // times 1.0;
      }
      else
      {
         ticksizeDistance *= 2.0;
      }
   }
   else
   {
      ticksizeDistance *= 5.0;
   }

   if (mpGeoreference.get() == NULL || getUnitSystem() == UNIT_KM || getUnitSystem() == UNIT_KFT)
   {
      if (ticksizeDistance >= (1000 / 5.0)) // 5 ticks >= 1000 base units (either meters or feet)
      {
         spacingScale /= 1000.0; //meters to kilometers, feet to kilofeet
         unitsText = "k" + unitsText;
      }
   }
   else if (getUnitSystem() == UNIT_MI)
   {
      if (ticksizeDistance < (0.25 / 5.0)) //5 ticks is less than 1/4 mile, convert to feet.
      {
         spacingScale = GeoConversions::convertMilesToFeet(spacingScale);
         unitsText = "ft";
      }
   }

   // need to divide ticksize by gsd here
   if (lengthBar != 0.0)
   {
      ticksize = DrawUtil::sign(deltaX) * ticksizeDistance * totalLengthPixels / lengthBar; // ticksize in pixels
   }

   ostringstream center;
   center << (ticksizeDistance * 5.0) * spacingScale << unitsText;
   TextStringProperty centerText(center.str());

   ostringstream right;
   right << lengthBar * spacingScale << unitsText;
   string newRightVal = right.str();
   TextStringProperty rightText(right.str());
   TextStringProperty leftText("0" + unitsText);

   double width = 0.0;
   double height = 0.0;

   int i = 0;
   list<GraphicObject*> objects = mpGroup->getObjects();
   list<GraphicObject*>::iterator it = objects.begin();

   for (i = 0; it != objects.end(); ++it, ++i)
   {
      GraphicObjectImp* pObj = dynamic_cast<GraphicObjectImp*>(*it);
      TextObjectImp* pText = NULL;

      if (pObj == NULL)
      {
         continue;
      }

      LocationType llObjCorner = pObj->getLlCorner();
      LocationType urObjCorner = pObj->getUrCorner();

      switch (i)
      {
         case 0:
            // big, stretchy rectangle
            llObjCorner.mX = llCorner.mX;
            urObjCorner.mX = urCorner.mX;
            llObjCorner.mY = llCorner.mY + barHeight * (1.0-BOX_HEIGHT);
            urObjCorner.mY = llObjCorner.mY + barHeight * BOX_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            
            pObj->updateHandles();
            break;
         case 1:
         case 2:
         case 3:
         case 4:
         case 5:
            // 5 rectangles
            llObjCorner.mX = ((i-1) * ticksize) + llCorner.mX;
            urObjCorner.mX = (i * ticksize) + llCorner.mX;
            llObjCorner.mY = llCorner.mY + barHeight * (1.0-BOX_HEIGHT);
            urObjCorner.mY = llObjCorner.mY + barHeight * BOX_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            pObj->updateHandles();
            break;
         case 6:
            //center line
            llObjCorner.mX = (5.0 * ticksize) + llCorner.mX;
            urObjCorner.mX = llObjCorner.mX;
            llObjCorner.mY = llCorner.mY + barHeight * (1.0-BOX_HEIGHT - CENTER_LINE_HEIGHT);
            urObjCorner.mY = llObjCorner.mY + barHeight * CENTER_LINE_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            pObj->updateHandles();
            break;
         case 7:
            // left line
            llObjCorner.mX = llCorner.mX;
            urObjCorner.mX = llCorner.mX;
            llObjCorner.mY = llCorner.mY + barHeight * TEXT_HEIGHT;
            urObjCorner.mY = llObjCorner.mY + barHeight * LINE_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            pObj->updateHandles();
            break;
         case 8:
            //right line
            llObjCorner.mX = urCorner.mX;
            urObjCorner.mX = llObjCorner.mX;
            llObjCorner.mY = llCorner.mY + barHeight * TEXT_HEIGHT;
            urObjCorner.mY = llObjCorner.mY + barHeight * LINE_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            pObj->updateHandles();
            break;
         case 9:
         {
            //left text
            pText = dynamic_cast<TextObjectImp*>(pObj);
            VERIFYNRV(pText != NULL);
            if (pObj->getText() != leftText.getString())
            {
               pText->setProperty(&leftText);
               pText->updateTexture();
            }
            else
            {
               pText->updateBoundingBox();
            }

            LocationType textLlCorner = pText->getLlCorner();
            LocationType textUrCorner = pText->getUrCorner();
            width = textUrCorner.mX - textLlCorner.mX;
            height = textUrCorner.mY - textLlCorner.mY;
            llObjCorner.mX = llCorner.mX;
            llObjCorner.mY = llCorner.mY;
            if (height != 0.0)
            {
               urObjCorner.mX = llObjCorner.mX + width * barHeight * TEXT_HEIGHT / height;
            }
            else
            {
               urObjCorner.mX = llObjCorner.mX + width;
            }
            urObjCorner.mY = llObjCorner.mY + barHeight * TEXT_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            break;
         }
         case 10:
         {
            //center text
            pText = dynamic_cast<TextObjectImp*>(pObj);
            VERIFYNRV(pText != NULL);
            if (pObj->getText() != centerText.getString())
            {
               pText->setProperty(&centerText);
               pText->updateTexture();
            }
            else
            {
               pText->updateBoundingBox();
            }

            LocationType textLlCorner = pText->getLlCorner();
            LocationType textUrCorner = pText->getUrCorner();
            width = textUrCorner.mX - textLlCorner.mX;
            height = textUrCorner.mY - textLlCorner.mY;

            if (height != 0.0)
            {
               llObjCorner.mX = llCorner.mX + (5.0 * ticksize) - (width / 2.0) * barHeight * TEXT_HEIGHT / height;
               urObjCorner.mX = llObjCorner.mX + width * barHeight * TEXT_HEIGHT / height;
            }
            else
            {
               llObjCorner.mX = llCorner.mX + (5.0 * ticksize);
               urObjCorner.mX = llObjCorner.mX + width;
            }
            llObjCorner.mY = llCorner.mY + (1.0-BOX_HEIGHT-TEXT_HEIGHT-CENTER_LINE_HEIGHT)*barHeight;
            urObjCorner.mY = llObjCorner.mY + barHeight*TEXT_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            break;
         }
         case 11:
         {
            //right text
            pText = dynamic_cast<TextObjectImp*>(pObj);
            VERIFYNRV(pText != NULL);
            if (pObj->getText() != rightText.getString())
            {
               pText->setProperty(&rightText);
               pText->updateTexture();
            }
            else
            {
               pText->updateBoundingBox();
            }

            LocationType textLlCorner = pText->getLlCorner();
            LocationType textUrCorner = pText->getUrCorner();
            width = textUrCorner.mX - textLlCorner.mX;
            height = textUrCorner.mY - textLlCorner.mY;
            if (height != 0.0)
            {
               llObjCorner.mX = urCorner.mX - width * barHeight * TEXT_HEIGHT / height;
               urObjCorner.mX = llObjCorner.mX + width * barHeight * TEXT_HEIGHT / height;
            }
            else
            {
               llObjCorner.mX = urCorner.mX;
               urObjCorner.mX = llObjCorner.mX + width;
            }
            llObjCorner.mY = llCorner.mY;
            urObjCorner.mY = llObjCorner.mY + barHeight*TEXT_HEIGHT;
            pObj->setBoundingBox(llObjCorner, urObjCorner);
            break;
         }

         default:
            break;
      }
   }

   mpGroup->updateBoundingBox();
   mNeedsLayout = false;
}