예제 #1
0
// internal test to see if regions don't intersect (optimization)
bool LLRegion::NoIntersection(const LLRegion& region) const
{
    if(Empty() || region.Empty())
        return true;
    
    LLBBox box = GetBox(), rbox = region.GetBox();
    return box.IntersectOut(rbox) || NoIntersection(rbox) || region.NoIntersection(box);
}
예제 #2
0
// only works for our specialized (AABB, position centered) bboxes
BOOL bbox_overlap(LLBBox bbox1, LLBBox bbox2)
{
	const F32 FUDGE = 0.001f;  // because of SL precision/rounding
	
	LLVector3 delta = bbox1.getCenterAgent() - bbox2.getCenterAgent();

	LLVector3 half_extent = (bbox1.getExtentLocal() + bbox2.getExtentLocal()) / 2.0;

	return ((fabs(delta.mV[VX]) < half_extent.mV[VX] - FUDGE) &&
			(fabs(delta.mV[VY]) < half_extent.mV[VY] - FUDGE) &&
			(fabs(delta.mV[VZ]) < half_extent.mV[VZ] - FUDGE));
}
예제 #3
0
파일: viewport.cpp 프로젝트: thielj/OpenCPN
LLBBox ViewPort::GetBBoxView()
{
    LLBBox BBView = vpBBox;

    wxPoint2DDouble pos(360, 0), neg(-360, 0);
    if(BBView.GetMaxX()+180 < clon)
        BBView.Translate(pos);
    else if(BBView.GetMinX()-180 > clon)
        BBView.Translate(neg);

    return BBView;
}
예제 #4
0
/* This function adds a new point ensuring the resulting track is finalized
   The runtime of this routine is O(log(n)) which is an an improvment over
   blowing away the subtracks and calling Finalize which is O(n),
   but should not be used for building a large track O(n log(n)) which
   _is_ worse than blowing the subtracks and calling Finalize.
*/
void Track::AddPointFinalized( TrackPoint *pNewPoint )
{
    TrackPoints.push_back( pNewPoint );

    int pos = TrackPoints.size() - 1;

    if(pos > 0) {
        LLBBox box;
        box.SetFromSegment(TrackPoints[pos-1]->m_lat,
                           TrackPoints[pos-1]->m_lon,
                           TrackPoints[pos]->m_lat,
                           TrackPoints[pos]->m_lon);
        InsertSubTracks(box, 0, pos-1);
    }
}
예제 #5
0
// recursive subtracks fixer for appending a single point
void Track::InsertSubTracks(LLBBox &box, int level, int pos)
{
    if(level == (int)SubTracks.size()) {
        std::vector <SubTrack> new_level;
        if(level > 0)
            box.Expand(SubTracks[level-1][0].m_box);
        new_level.push_back(SubTrack());
        new_level[pos].m_box = box;
        SubTracks.push_back(new_level);
    } else
    if(pos < (int)SubTracks[level].size())
        SubTracks[level][pos].m_box.Expand(box);
    else {
        SubTracks[level].push_back(SubTrack());
        SubTracks[level][pos].m_box = box;
    }

    if(level == 0)
        SubTracks[level][pos].m_scale = 0;
    else {
        int left = pos << level;
        int right = wxMin(left + (1 << level), TrackPoints.size() - 1);
        SubTracks[level][pos].m_scale = ComputeScale(left, right);
    }
    
    if(pos > 0)
        InsertSubTracks(box, level + 1, pos >> 1);
}
예제 #6
0
/* assembles lists of line strips from the given track recursively traversing
   the subtracks data */
void Track::Assemble(std::list< std::list<wxPoint> > &pointlists, const LLBBox &box, double scale, int &last, int level, int pos)
{
    if(pos == (int)SubTracks[level].size())
        return;

    SubTrack &s = SubTracks[level][pos];
    if(box.IntersectOut(s.m_box))
        return;

    if(s.m_scale < scale) {
        pos <<= level;

        if(last < pos - 1) {
            std::list<wxPoint> new_list;
            pointlists.push_back(new_list);
        }

        if(last < pos)
            AddPointToList(pointlists, pos);
        last = wxMin(pos + (1<<level), TrackPoints.size() - 1);
        AddPointToList(pointlists, last);
    } else {
        Assemble(pointlists, box, scale, last, level-1, pos<<1);
        Assemble(pointlists, box, scale, last, level-1, (pos<<1)+1);
    }
}
예제 #7
0
void setup_transforms_bbox(LLBBox bbox)
{
	// translate to center
	LLVector3 center = bbox.getCenterAgent();
	gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);

	// rotate
	LLQuaternion rotation = bbox.getRotation();
	F32 angle_radians, x, y, z;
	rotation.getAngleAxis(&angle_radians, &x, &y, &z);
	gGL.flush();
	gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); 

	// scale
	LLVector3 scale = bbox.getMaxLocal() - bbox.getMinLocal();
	gGL.scalef(scale.mV[VX], scale.mV[VY], scale.mV[VZ]);
}
예제 #8
0
static inline int ComputeState(const LLBBox &box, const contour_pt &p)
{
    int state = 0;
    if(p.x >= box.GetMinLon()) {
        if(p.x > box.GetMaxLon())
            state = 2;
        else
            state = 1;
    }

    if(p.y >= box.GetMinLat()) {
        if(p.y > box.GetMaxLat())
            state += 6;
        else
            state += 3;
    }
    return state;
}
예제 #9
0
void setup_transforms_bbox(LLBBox bbox)
{
	// translate to center
	LLVector3 center = bbox.getCenterAgent();
	gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);

	// rotate
	LLQuaternion rotation = bbox.getRotation();
	F32 angle_radians, x, y, z;
	rotation.getAngleAxis(&angle_radians, &x, &y, &z);
	// gGL has no rotate method (despite having translate and scale) presumably because
	// its authors smoke crack.  so we hack.
	gGL.flush();
	glRotatef(angle_radians * RAD_TO_DEG, x, y, z); 

	// scale
	LLVector3 scale = bbox.getMaxLocal() - bbox.getMinLocal();
	gGL.scalef(scale.mV[VX], scale.mV[VY], scale.mV[VZ]);
}
예제 #10
0
bool LLBBox::IntersectIn( const LLBBox &other ) const
{
    if( !GetValid() || !other.GetValid() )
        return false;

    if((m_maxlat <= other.m_maxlat) || (m_minlat >= other.m_minlat))
        return false;
    
    double minlon = m_minlon, maxlon = m_maxlon;
    if(m_maxlon < other.m_minlon)
        minlon += 360, maxlon += 360;
    else if(m_minlon > other.m_maxlon)
        minlon -= 360, maxlon -= 360;

    return (other.m_minlon > minlon) && (other.m_maxlon < maxlon);
}
예제 #11
0
bool LLBBox::IntersectOutGetBias( const LLBBox &other, double bias ) const
{
    // allow -180 to 180 or 0 to 360
    if( !GetValid() || !other.GetValid() )
        return true;
    
    if((m_maxlat < other.m_minlat) || (m_minlat > other.m_maxlat))
        return true;

    if(m_maxlon < other.m_minlon)
        bias = 360;
    else if(m_minlon > other.m_maxlon)
        bias = -360;
    else
        bias = 0;

    return (m_minlon + bias > other.m_maxlon) || (m_maxlon + bias < other.m_minlon);
}
예제 #12
0
// This function calculates the aspect ratio and the world aligned components of a selection bounding box.
F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth)
{
	// Convert the selection normal and an up vector to local coordinate space of the bbox
	LLVector3 local_normal = bbox.agentToLocalBasis(normal);
	LLVector3 z_vec = bbox.agentToLocalBasis(LLVector3(0.0f, 0.0f, 1.0f));
	
	LLVector3 comp1(0.f,0.f,0.f);
	LLVector3 comp2(0.f,0.f,0.f);
	LLVector3 bbox_max = bbox.getExtentLocal();
	F32 dot1 = 0.f;
	F32 dot2 = 0.f;
	
	lldebugs << "bounding box local size = " << bbox_max << ", local_normal = " << local_normal << llendl;

	// The largest component of the localized normal vector is the depth component
	// meaning that the other two are the legs of the rectangle.
	local_normal.abs();
	
	// Using temporary variables for these makes the logic a bit more readable.
	bool XgtY = (local_normal.mV[VX] > local_normal.mV[VY]);
	bool XgtZ = (local_normal.mV[VX] > local_normal.mV[VZ]);
	bool YgtZ = (local_normal.mV[VY] > local_normal.mV[VZ]);
	
	if(XgtY && XgtZ)
	{
		lldebugs << "x component of normal is longest, using y and z" << llendl;
		comp1.mV[VY] = bbox_max.mV[VY];
		comp2.mV[VZ] = bbox_max.mV[VZ];
		*depth = bbox_max.mV[VX];
	}
	else if(!XgtY && YgtZ)
	{
		lldebugs << "y component of normal is longest, using x and z" << llendl;
		comp1.mV[VX] = bbox_max.mV[VX];
		comp2.mV[VZ] = bbox_max.mV[VZ];
		*depth = bbox_max.mV[VY];
	}
	else
	{
		lldebugs << "z component of normal is longest, using x and y" << llendl;
		comp1.mV[VX] = bbox_max.mV[VX];
		comp2.mV[VY] = bbox_max.mV[VY];
		*depth = bbox_max.mV[VZ];
	}
	
	// The height is the vector closest to vertical in the bbox coordinate space (highest dot product value)
	dot1 = comp1 * z_vec;
	dot2 = comp2 * z_vec;
	if(fabs(dot1) > fabs(dot2))
	{
		*height = comp1.length();
		*width = comp2.length();

		lldebugs << "comp1 = " << comp1 << ", height = " << *height << llendl;
		lldebugs << "comp2 = " << comp2 << ", width = " << *width << llendl;
	}
	else
	{
		*height = comp2.length();
		*width = comp1.length();

		lldebugs << "comp2 = " << comp2 << ", height = " << *height << llendl;
		lldebugs << "comp1 = " << comp1 << ", width = " << *width << llendl;
	}
	
	lldebugs << "returning " << (*width / *height) << llendl;

	// Return the aspect ratio.
	return *width / *height;
}
예제 #13
0
void RoutePoint::DrawGL( ViewPort &vp, bool use_cached_screen_coords )
{
    if( !m_bIsVisible )
        return;

    //    Optimization, especially apparent on tracks in normal cases
    if( m_IconName == _T("empty") && !m_bShowName && !m_bPtIsSelected ) return;

    if(m_wpBBox.GetValid() &&
       vp.view_scale_ppm == m_wpBBox_view_scale_ppm &&
       vp.rotation == m_wpBBox_rotation) {
        /* see if this waypoint can intersect with bounding box */
        LLBBox vpBBox = vp.GetBBox();
        if( vpBBox.IntersectOut( m_wpBBox ) ){
            
            // Are Range Rings enabled?
            if(m_bShowWaypointRangeRings && (m_iWaypointRangeRingsNumber > 0)){
                double factor = 1.00;
                if( m_iWaypointRangeRingsStepUnits == 1 )          // convert kilometers to NMi
                    factor = 1 / 1.852;
            
                double radius = factor * m_iWaypointRangeRingsNumber * m_fWaypointRangeRingsStep  / 60.;

                LLBBox radar_box = m_wpBBox;
                radar_box.EnLarge(radius * 2 );
                if( vpBBox.IntersectOut( radar_box ) ){
                    return;
                }
            }
            else
                return;
        }
    }

    wxPoint r;
    wxRect hilitebox;
    unsigned char transparency = 150;
    double platform_pen_width = wxRound(wxMax(1.0, g_Platform->GetDisplayDPmm() / 2));             // 0.5 mm nominal, but not less than 1 pixel
    
    if(use_cached_screen_coords && m_pos_on_screen)
        r.x = m_screen_pos.m_x, r.y = m_screen_pos.m_y;
    else
        cc1->GetCanvasPointPix( m_lat, m_lon, &r );

    if(r.x == INVALID_COORD)
        return;

//    Substitute icon?
    wxBitmap *pbm;
    if( ( m_bIsActive ) && ( m_IconName != _T("mob") ) )
        pbm = pWayPointMan->GetIconBitmap(  _T ( "activepoint" ) );
    else
        pbm = m_pbmIcon;

    //  If icon is corrupt, there is really nothing else to do...
    if(!pbm->IsOk())
        return;
    
    int sx2 = pbm->GetWidth() / 2;
    int sy2 = pbm->GetHeight() / 2;

//    Calculate the mark drawing extents
    wxRect r1( r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2 );           // the bitmap extents

    wxRect r3 = r1;
    if( m_bShowName ) {
        if( !m_pMarkFont ) {
            m_pMarkFont = FontMgr::Get().GetFont( _( "Marks" ) );
            m_FontColor = FontMgr::Get().GetFontColor( _( "Marks" ) );
            CalculateNameExtents();
        }

        if( m_pMarkFont ) {
            wxRect r2( r.x + m_NameLocationOffsetX, r.y + m_NameLocationOffsetY,
                       m_NameExtents.x, m_NameExtents.y );
            r3.Union( r2 );
        }
    }

    hilitebox = r3;
    hilitebox.x -= r.x;
    hilitebox.y -= r.y;
    
    hilitebox.x *= g_ChartScaleFactorExp;
    hilitebox.y *= g_ChartScaleFactorExp;
    hilitebox.width  *= g_ChartScaleFactorExp;
    hilitebox.height *= g_ChartScaleFactorExp;
    
    float radius;
    if( g_btouch ){
        hilitebox.Inflate( 20 );
        radius = 20.0f;
    }
    else{
        hilitebox.Inflate( 4 );
        radius = 4.0f;
    }
    
    /* update bounding box */
    if(!m_wpBBox.GetValid() || vp.view_scale_ppm != m_wpBBox_view_scale_ppm || vp.rotation != m_wpBBox_rotation) {
        double lat1, lon1, lat2, lon2;
        cc1->GetCanvasPixPoint(r.x+hilitebox.x, r.y+hilitebox.y+hilitebox.height, lat1, lon1);
        cc1->GetCanvasPixPoint(r.x+hilitebox.x+hilitebox.width, r.y+hilitebox.y, lat2, lon2);

        if(lon1 > lon2)
            m_wpBBox.Set(lat1, lon1, lat2, lon2+360);
        else
            m_wpBBox.Set(lat1, lon1, lat2, lon2);

        m_wpBBox_view_scale_ppm = vp.view_scale_ppm;
        m_wpBBox_rotation = vp.rotation;
    }

//    if(region.Contains(r3) == wxOutRegion)
//        return;
    

    ocpnDC dc;

    //  Highlite any selected point
    if( m_bPtIsSelected ) {
        wxColour hi_colour;
        if( m_bBlink ){
            wxPen *pen = g_pRouteMan->GetActiveRoutePointPen();
            hi_colour = pen->GetColour();
        }
        else{
            hi_colour = GetGlobalColor( _T ( "YELO1" ) );
        }
        
        AlphaBlending( dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width, hilitebox.height, radius,
                       hi_colour, transparency );
    }
    
    bool bDrawHL = false;

    if( m_bBlink && ( gFrame->nBlinkerTick & 1 ) ) bDrawHL = true;

    if( ( !bDrawHL ) && ( NULL != m_pbmIcon ) ) {
        int glw, glh;
        unsigned int IconTexture = pWayPointMan->GetIconTexture( pbm, glw, glh );
        
        glBindTexture(GL_TEXTURE_2D, IconTexture);
        
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
        
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        
        glColor3f(1, 1, 1);
        
        int x = r1.x, y = r1.y, w = r1.width, h = r1.height;
        
        float scale = 1.0;
 //       if(g_bresponsive){
            scale =  g_ChartScaleFactorExp;
//        }
            
        float ws = r1.width * scale;
        float hs = r1.height * scale;
        float xs = r.x - ws/2.;
        float ys = r.y - hs/2.;
        float u = (float)w/glw, v = (float)h/glh;
        
        glBegin(GL_QUADS);
        glTexCoord2f(0, 0); glVertex2f(xs, ys);
        glTexCoord2f(u, 0); glVertex2f(xs+ws, ys);
        glTexCoord2f(u, v); glVertex2f(xs+ws, ys+hs);
        glTexCoord2f(0, v); glVertex2f(xs, ys+hs);
        glEnd();
        
//         glBegin(GL_QUADS);
//         glTexCoord2f(0, 0); glVertex2f(x, y);
//         glTexCoord2f(u, 0); glVertex2f(x+w, y);
//         glTexCoord2f(u, v); glVertex2f(x+w, y+h);
//         glTexCoord2f(0, v); glVertex2f(x, y+h);
//         glEnd();

        glDisable(GL_BLEND);
        glDisable(GL_TEXTURE_2D);
    }

    if( m_bShowName && m_pMarkFont ) {
        int w = m_NameExtents.x, h = m_NameExtents.y;
        if(!m_iTextTexture && w && h) {
            wxBitmap tbm(w, h); /* render text on dc */
            wxMemoryDC dc;
            dc.SelectObject( tbm );               
            dc.SetBackground( wxBrush( *wxBLACK ) );
            dc.Clear();
            dc.SetFont( *m_pMarkFont );
            dc.SetTextForeground( *wxWHITE );
            dc.DrawText( m_MarkName, 0, 0);
            dc.SelectObject( wxNullBitmap );
            
            /* make alpha texture for text */
            wxImage image = tbm.ConvertToImage();
            unsigned char *d = image.GetData();
            unsigned char *e = new unsigned char[w * h];
            if(d && e){
                for( int p = 0; p < w*h; p++)
                    e[p] = d[3*p + 0];
            }
            
            /* create texture for rendered text */
            glGenTextures(1, &m_iTextTexture);
            glBindTexture(GL_TEXTURE_2D, m_iTextTexture);
            
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

            m_iTextTextureWidth = NextPow2(w);
            m_iTextTextureHeight = NextPow2(h);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_iTextTextureWidth, m_iTextTextureHeight,
                         0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
                            GL_ALPHA, GL_UNSIGNED_BYTE, e);
            delete [] e;
        }

        if(m_iTextTexture) {
            /* draw texture with text */
            glBindTexture(GL_TEXTURE_2D, m_iTextTexture);
            
            glEnable(GL_TEXTURE_2D);
            glEnable(GL_BLEND);
        
            glColor3ub(m_FontColor.Red(), m_FontColor.Green(), m_FontColor.Blue());
            
            int x = r.x + m_NameLocationOffsetX, y = r.y + m_NameLocationOffsetY;
            float u = (float)w/m_iTextTextureWidth, v = (float)h/m_iTextTextureHeight;
            glBegin(GL_QUADS);
            glTexCoord2f(0, 0); glVertex2f(x, y);
            glTexCoord2f(u, 0); glVertex2f(x+w, y);
            glTexCoord2f(u, v); glVertex2f(x+w, y+h);
            glTexCoord2f(0, v); glVertex2f(x, y+h);
            glEnd();

            glDisable(GL_BLEND);
            glDisable(GL_TEXTURE_2D);
        }
    }
    
    // Draw waypoint radar rings if activated
    if( m_iWaypointRangeRingsNumber && m_bShowWaypointRangeRings ) {
        double factor = 1.00;
        if( m_iWaypointRangeRingsStepUnits == 1 )          // nautical miles
            factor = 1 / 1.852;
        
        factor *= m_fWaypointRangeRingsStep;
        
        double tlat, tlon;
        wxPoint r1;
        ll_gc_ll( m_lat, m_lon, 0, factor, &tlat, &tlon );
        cc1->GetCanvasPointPix( tlat, tlon, &r1 );
        
        double lpp = sqrt( pow( (double) (r.x - r1.x), 2) +
        pow( (double) (r.y - r1.y), 2 ) );
        int pix_radius = (int) lpp;
        
        wxPen ppPen1( m_wxcWaypointRangeRingsColour, platform_pen_width );
        wxBrush saveBrush = dc.GetBrush();
        wxPen savePen = dc.GetPen();
        dc.SetPen( ppPen1 );
        dc.SetBrush( wxBrush( m_wxcWaypointRangeRingsColour, wxBRUSHSTYLE_TRANSPARENT ) );
        
        for( int i = 1; i <= m_iWaypointRangeRingsNumber; i++ )
            dc.StrokeCircle( r.x, r.y, i * pix_radius );
        dc.SetPen( savePen );
        dc.SetBrush( saveBrush );
    }
    
    if( m_bBlink ) g_blink_rect = CurrentRect_in_DC;               // also save for global blinker
    
    //    This will be useful for fast icon redraws
    CurrentRect_in_DC.x = r.x + hilitebox.x;
    CurrentRect_in_DC.y = r.y + hilitebox.y;
    CurrentRect_in_DC.width = hilitebox.width;
    CurrentRect_in_DC.height = hilitebox.height;

    if( m_bBlink ) g_blink_rect = CurrentRect_in_DC;               // also save for global blinker
}
예제 #14
0
// True if you selected an object.
BOOL LLToolPie::pickLeftMouseDownCallback()
{
	S32 x = mPick.mMousePt.mX;
	S32 y = mPick.mMousePt.mY;
	MASK mask = mPick.mKeyMask;
	if (mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL)
	{
		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel();
		if (parcel)
		{
			LLViewerParcelMgr::getInstance()->selectCollisionParcel();
			if (parcel->getParcelFlag(PF_USE_PASS_LIST) 
				&& !LLViewerParcelMgr::getInstance()->isCollisionBanned())
			{
				// if selling passes, just buy one
				void* deselect_when_done = (void*)TRUE;
				LLPanelLandGeneral::onClickBuyPass(deselect_when_done);
			}
			else
			{
				// not selling passes, get info
				LLFloaterReg::showInstance("about_land");
			}
		}

		gFocusMgr.setKeyboardFocus(NULL);
		return LLTool::handleMouseDown(x, y, mask);
	}

	// didn't click in any UI object, so must have clicked in the world
	LLViewerObject *object = mPick.getObject();
	LLViewerObject *parent = NULL;

	if (mPick.mPickType != LLPickInfo::PICK_LAND)
	{
		LLViewerParcelMgr::getInstance()->deselectLand();
	}
	
	if (object)
	{
		parent = object->getRootEdit();
	}

	if (handleMediaClick(mPick))
	{
		return TRUE;
	}

	// If it's a left-click, and we have a special action, do it.
	if (useClickAction(mask, object, parent))
	{
		mClickAction = 0;
		if (object && object->getClickAction()) 
		{
			mClickAction = object->getClickAction();
		}
		else if (parent && parent->getClickAction()) 
		{
			mClickAction = parent->getClickAction();
		}

		switch(mClickAction)
		{
		case CLICK_ACTION_TOUCH:
			// touch behavior down below...
			break;
		case CLICK_ACTION_SIT:
			{
				if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // agent not already sitting
				{
					handle_object_sit_or_stand();
					// put focus in world when sitting on an object
					gFocusMgr.setKeyboardFocus(NULL);
					return TRUE;
				} // else nothing (fall through to touch)
			}
		case CLICK_ACTION_PAY:
			if ((object && object->flagTakesMoney())
				|| (parent && parent->flagTakesMoney()))
			{
				// pay event goes to object actually clicked on
				mClickActionObject = object;
				mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
				if (LLSelectMgr::getInstance()->selectGetAllValid())
				{
					// call this right away, since we have all the info we need to continue the action
					selectionPropertiesReceived();
				}
				return TRUE;
			}
			break;
		case CLICK_ACTION_BUY:
			mClickActionObject = parent;
			mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
			if (LLSelectMgr::getInstance()->selectGetAllValid())
			{
				// call this right away, since we have all the info we need to continue the action
				selectionPropertiesReceived();
			}
			return TRUE;
		case CLICK_ACTION_OPEN:
			if (parent && parent->allowOpen())
			{
				mClickActionObject = parent;
				mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
				if (LLSelectMgr::getInstance()->selectGetAllValid())
				{
					// call this right away, since we have all the info we need to continue the action
					selectionPropertiesReceived();
				}
			}
			return TRUE;	
		case CLICK_ACTION_PLAY:
			handle_click_action_play();
			return TRUE;
		case CLICK_ACTION_OPEN_MEDIA:
			// mClickActionObject = object;
			handle_click_action_open_media(object);
			return TRUE;
		case CLICK_ACTION_ZOOM:
			{	
				const F32 PADDING_FACTOR = 2.f;
				LLViewerObject* object = gObjectList.findObject(mPick.mObjectID);
				
				if (object)
				{
					gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
					
					LLBBox bbox = object->getBoundingBoxAgent() ;
					F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
					F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
				
					LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
					obj_to_cam.normVec();
					
					LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
					gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), 
													  object_center_global, 
													  mPick.mObjectID );
				}
			}
			return TRUE;			
		default:
			// nothing
			break;
		}
	}

	// put focus back "in world"
	gFocusMgr.setKeyboardFocus(NULL);

	BOOL touchable = (object && object->flagHandleTouch()) 
					 || (parent && parent->flagHandleTouch());

	// Switch to grab tool if physical or triggerable
	if (object && 
		!object->isAvatar() && 
		((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable) 
		)
	{
		gGrabTransientTool = this;
		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() );
		return LLToolGrab::getInstance()->handleObjectHit( mPick );
	}
	
	LLHUDIcon* last_hit_hud_icon = mPick.mHUDIcon;
	if (!object && last_hit_hud_icon && last_hit_hud_icon->getSourceObject())
	{
		LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID());
	}

	// If left-click never selects or spawns a menu
	// Eat the event.
	if (!gSavedSettings.getBOOL("LeftClickShowMenu"))
	{
		// mouse already released
		if (!mGrabMouseButtonDown)
		{
			return TRUE;
		}

		while( object && object->isAttachment() && !object->flagHandleTouch())
		{
			// don't pick avatar through hud attachment
			if (object->isHUDAttachment())
			{
				break;
			}
			object = (LLViewerObject*)object->getParent();
		}
		if (object && object == gAgentAvatarp)
		{
			// we left clicked on avatar, switch to focus mode
			LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance());
			gViewerWindow->hideCursor();
			LLToolCamera::getInstance()->setMouseCapture(TRUE);
			LLToolCamera::getInstance()->pickCallback(mPick);
			gAgentCamera.setFocusOnAvatar(TRUE, TRUE);

			return TRUE;
		}
	//////////
	//	// Could be first left-click on nothing
	//	LLFirstUse::useLeftClickNoHit();
	/////////
		
		// Eat the event
		return LLTool::handleMouseDown(x, y, mask);
	}

	if (gAgent.leftButtonGrabbed())
	{
		// if the left button is grabbed, don't put up the pie menu
		return LLTool::handleMouseDown(x, y, mask);
	}

	// Can't ignore children here.
	LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);

	// Spawn pie menu
	LLTool::handleRightMouseDown(x, y, mask);
	return TRUE;
}
예제 #15
0
// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value
void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor, bool zoom_in_only)
{
	if (object)
	{
		gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);

		LLBBox bbox = object->getBoundingBoxAgent();
		LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
		F32 height;
		F32 width;
		F32 depth;
		F32 angle_of_view;
		F32 distance;

		// We need the aspect ratio, and the 3 components of the bbox as height, width, and depth.
		F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth);
		F32 camera_aspect = LLViewerCamera::getInstance()->getAspect();
		
		lldebugs << "normal = " << normal << ", aspect_ratio = " << aspect_ratio << ", camera_aspect = " << camera_aspect << llendl;

		// We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for 
		// a screen in a landscape aspect ratio), however there is an edge case where the aspect ratio of the object is 
		// more extreme than the screen.  In this case we invert the logic, using the longer component of both the object
		// and the screen.  
		bool invert = (camera_aspect > 1.0f && aspect_ratio > camera_aspect) ||
			(camera_aspect < 1.0f && aspect_ratio < camera_aspect);

		// To calculate the optimum viewing distance we will need the angle of the shorter side of the view rectangle.
		// In portrait mode this is the width, and in landscape it is the height.
		// We then calculate the distance based on the corresponding side of the object bbox (width for portrait, height for landscape)
		// We will add half the depth of the bounding box, as the distance projection uses the center point of the bbox.
		if(camera_aspect < 1.0f || invert)
		{
			angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect());
			distance = width * 0.5 * padding_factor / tan(angle_of_view * 0.5f );

			lldebugs << "using width (" << width << "), angle_of_view = " << angle_of_view << ", distance = " << distance << llendl;
		}
		else
		{
			angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView());
			distance = height * 0.5 * padding_factor / tan(angle_of_view * 0.5f );

			lldebugs << "using height (" << height << "), angle_of_view = " << angle_of_view << ", distance = " << distance << llendl;
		}

		distance += depth * 0.5;

		// Finally animate the camera to this new position and focal point
		LLVector3d camera_pos, target_pos;
		// The target lookat position is the center of the selection (in global coords)
		target_pos = center;
		// Target look-from (camera) position is "distance" away from the target along the normal 
		LLVector3d pickNormal = LLVector3d(normal);
		pickNormal.normalize();
        camera_pos = target_pos + pickNormal * distance;
        if (pickNormal == LLVector3d::z_axis || pickNormal == LLVector3d::z_axis_neg)
        {
			// If the normal points directly up, the camera will "flip" around.
			// We try to avoid this by adjusting the target camera position a 
			// smidge towards current camera position
			// *NOTE: this solution is not perfect.  All it attempts to solve is the
			// "looking down" problem where the camera flips around when it animates
			// to that position.  You still are not guaranteed to be looking at the
			// media in the correct orientation.  What this solution does is it will
			// put the camera into position keeping as best it can the current 
			// orientation with respect to the face.  In other words, if before zoom
			// the media appears "upside down" from the camera, after zooming it will
			// still be upside down, but at least it will not flip.
            LLVector3d cur_camera_pos = LLVector3d(gAgentCamera.getCameraPositionGlobal());
            LLVector3d delta = (cur_camera_pos - camera_pos);
            F64 len = delta.length();
            delta.normalize();
            // Move 1% of the distance towards original camera location
            camera_pos += 0.01 * len * delta;
        }

		// If we are not allowing zooming out and the old camera position is closer to 
		// the center then the new intended camera position, don't move camera and return
		if (zoom_in_only &&
		    (dist_vec_squared(gAgentCamera.getCameraPositionGlobal(), target_pos) < dist_vec_squared(camera_pos, target_pos)))
		{
			return;
		}

		gAgentCamera.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() );

	}
	else
	{
		// If we have no object, focus back on the avatar.
		gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
	}
}
예제 #16
0
파일: Route.cpp 프로젝트: jieter/OpenCPN
void Route::DrawGLLines( ViewPort &VP, ocpnDC *dc )
{
#ifdef ocpnUSE_GL    
    float pix_full_circle = WGS84_semimajor_axis_meters * mercator_k0 * 2 * PI * VP.view_scale_ppm;

    bool r1valid = false;
    wxPoint2DDouble r1;
    wxPoint2DDouble lastpoint;
    
    wxRoutePointListNode *node = pRoutePointList->GetFirst();
    RoutePoint *prp2 = node->GetData();
    cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &lastpoint);
    
    if(m_nPoints == 1 && dc) { // single point.. make sure it shows up for highlighting
        cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r1);
        dc->DrawLine(r1.m_x, r1.m_y, r1.m_x+2, r1.m_y+2);
        return;
    }

    // dc is passed for thicker highlighted lines (performance not very important)
    if( !dc )
        glBegin(GL_LINES);

    unsigned short int FromSegNo = prp2->m_GPXTrkSegNo;
    for(node = node->GetNext(); node; node = node->GetNext()) {
        RoutePoint *prp1 = prp2;
        prp2 = node->GetData();
        unsigned short int ToSegNo = prp2->m_GPXTrkSegNo;

        // Provisional, to properly set status of last point in route
        prp2->m_pos_on_screen = false;
        
        if (FromSegNo != ToSegNo) {
            FromSegNo = ToSegNo;
            r1valid = false;
        } else {
            
            wxPoint2DDouble r2;
            cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r2);
            lastpoint = r2;             // For active track segment to ownship
            
            //    Handle offscreen points
            LLBBox bbox = VP.GetBBox();

            // don't need to perform calculations or render segment
            // if both points are past any edge of the vp
            // TODO: use these optimizations for dc mode
            bool lat1l = prp1->m_lat < bbox.GetMinY(), lat2l = prp2->m_lat < bbox.GetMinY();
            bool lat1r = prp1->m_lat > bbox.GetMaxY(), lat2r = prp2->m_lat > bbox.GetMaxY();
            if( (lat1l && lat2l) || (lat1r && lat2r) ) {
                r1valid = false;
                prp1->m_pos_on_screen = false;
                continue;
            }

            bool lon1l, lon1r, lon2l, lon2r;
            TestLongitude(prp1->m_lon, bbox.GetMinX(), bbox.GetMaxX(), lon1l, lon1r);
            TestLongitude(prp2->m_lon, bbox.GetMinX(), bbox.GetMaxX(), lon2l, lon2r);
            if( (lon1l && lon2l) || (lon1r && lon2r) ) {
                r1valid = false;
                prp1->m_pos_on_screen = false;
                continue;
            }

            if(!r1valid)
                cc1->GetDoubleCanvasPointPix( prp1->m_lat, prp1->m_lon, &r1);

            //    In the cases where one point is on, and one off
            //    we must decide which way to go in longitude

            double adder1 = 0, adder2 = 0;
            if(!(lon1l || lon1r) && (lon2l || lon2r) ) { // first point is on screen, second not
                if( r2.m_x < r1.m_x )
                    adder2 = pix_full_circle;
                else
                    adder2 = -pix_full_circle;

                if( fabs(r1.m_x - r2.m_x) < fabs(r1.m_x - ( r2.m_x + adder2 )) )
                    adder2 = 0;
            } else if(lon1l || lon1r) { // first point is off screen
                if( r1.m_x < r2.m_x )
                    adder1 = pix_full_circle;
                else
                    adder1 = -pix_full_circle;

                if( fabs(r1.m_x - r2.m_x) < fabs(r2.m_x - (r1.m_x + adder1)) )
                    adder1 = 0;
            }

            if( dc )
                dc->DrawLine(r1.m_x + adder1, r1.m_y, r2.m_x + adder2, r2.m_y);
            else {
                glVertex2f(r1.m_x + adder1, r1.m_y);
                glVertex2f(r2.m_x + adder2, r2.m_y);

                // cache screen position for arrows and points
                if(!r1valid) {
                    prp1->m_pos_on_screen = !lat1l && !lat1r && !lon1l && !lon1r;
                    prp1->m_screen_pos = r1;
                }

                prp2->m_pos_on_screen = !lat2l && !lat2r && !lon2l && !lon2r;
                prp2->m_screen_pos = r2;
            }

            r1 = r2;
            r1valid = true;
        }
    }

    //  Draw tentative segment from last point to Ownship, if running.
    if( IsTrack() ) {
        /* Active tracks */
        if( dynamic_cast<Track *>(this)->IsRunning() ){
            wxPoint2DDouble rs;
            cc1->GetDoubleCanvasPointPix( gLat, gLon, &rs);
            if( dc )
                dc->DrawLine(lastpoint.m_x, lastpoint.m_y, rs.m_x, rs.m_y);
            else {
                glVertex2f(lastpoint.m_x, lastpoint.m_y);
                glVertex2f(rs.m_x, rs.m_y);
             }
        }
    }
                
                
        
    if( !dc )
        glEnd();
#endif    
}
예제 #17
0
LLRegion::LLRegion( const LLBBox& llbbox )
{
    InitBox(llbbox.GetMinLat(), llbbox.GetMinLon(), llbbox.GetMaxLat(), llbbox.GetMaxLon());
}
예제 #18
0
// slightly ugly, but efficient intersection algorithm
bool LLRegion::NoIntersection(const LLBBox& box) const
{
    return false; // there are occasional false positives we must fix first

#if 0    
    double minx = box.GetMinLon(), maxx = box.GetMaxLon(), miny = box.GetMinLat(), maxy = box.GetMaxLat();
    if(Contains(miny, minx))
        return false;

    // test if any segment crosses the box
    for(std::list<poly_contour>::const_iterator i = contours.begin(); i != contours.end(); i++) {
        contour_pt l = *i->rbegin();
        int state = ComputeState(box, l), lstate = state;
        if(state == 4) return false;
        for(poly_contour::const_iterator j = i->begin(); j != i->end(); j++) {
            contour_pt p = *j;
            int quadrant = p.x > l.x ? 1 : 0;
            if(p.y > l.y) quadrant += 2;
            switch(state*4 + quadrant) {
            case 0: goto skip;
            case 1: if(p.x >= minx) state = p.x > maxx ? 2 : 1; goto skip;
            case 2: if(p.y >= miny) state = p.y > maxy ? 6 : 3; goto skip;
            case 4: if(p.x < minx) state = 0; goto skip;
            case 5: if(p.x > maxx) state = 2; goto skip;
            case 8: if(p.x <= maxx) state = p.x < minx ? 0 : 1; goto skip;
            case 9: goto skip;
            case 11: if(p.y >= miny) state = p.y > maxy ? 8 : 5; goto skip;
            case 12: if(p.y < miny) state = 0; goto skip;
            case 14: if(p.y > maxy) state = 6; goto skip;
            case 21: if(p.y < miny) state = 2; goto skip;
            case 23: if(p.y > maxy) state = 8; goto skip;
            case 24: if(p.y <= maxy) state = p.y < miny ? 0 : 3; goto skip;
            case 26: goto skip;
            case 27: if(p.x >= minx) state = p.x > maxx ? 8 : 7; goto skip;
            case 30: if(p.x < minx) state = 6; goto skip;
            case 31: if(p.x > maxx) state = 8; goto skip;
            case 33: if(p.y <= maxy) state = p.y < miny ? 2 : 5; goto skip;
            case 34: if(p.x <= maxx) state = p.x < minx ? 6 : 7; goto skip;
            case 35: goto skip;
            }

            state = ComputeState(box, *j);
            if(state == 4) return false;
            switch(lstate) {
#define TEST_CASE(NO_INT, CASEA, CASEB, CASEAB, AX, AY, BX, BY) \
                switch(state) { NO_INT break; \
                    CASEAB if(TestPoint(l, p, BX##x, BY##y)) return false; \
                    CASEA  if(TestPoint(p, l, AX##x, AY##y)) return false; break;  \
                    CASEB  if(TestPoint(l, p, BX##x, BY##y)) return false; break;  \
                default: printf("invalid state inner %d %d\n", lstate, state); } break;
            case 0: TEST_CASE(case 0: case 1: case 2: case 3: case 6:,
                case 5:, case 7:, case 8:, max, min, min, max)
            case 1: TEST_CASE(case 0: case 1: case 2:,
                case 5: case 8:, case 3: case 6:, case 7:, max, min, min, min)
            case 2: TEST_CASE(case 0: case 1: case 2: case 5: case 8:,
                case 7:, case 3:, case 6:, max, max, min, min)
            case 3: TEST_CASE(case 0: case 3: case 6:,
                case 1: case 2:, case 7: case 8:, case 5:, min, min, min, max)
//            case 4: return false; // should never hit
            case 5: TEST_CASE(case 2: case 5: case 8:,
                case 6: case 7:, case 0: case 1:, case 3:, max, max, max, min)
            case 6: TEST_CASE(case 0: case 3: case 6: case 7: case 8:,
                case 1:, case 5:, case 2:, min, min, max, max)
            case 7: TEST_CASE(case 6: case 7: case 8:,
                case 0: case 3:, case 2: case 5:, case 1:, min, max, max, max)
            case 8: TEST_CASE(case 2: case 5: case 6: case 7: case 8:,
                case 3:, case 1:, case 0:, min, max, max, min)
            default: printf("invalid state\n");
            }
        skip:
            lstate = state;
            l = p;
        }
    }

    return true;
#endif    
}
예제 #19
0
// This function calculates the aspect ratio and the world aligned components of a selection bounding box.
F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth)
{
	// Convert the selection normal and an up vector to local coordinate space of the bbox
	LLVector3 local_normal = bbox.agentToLocalBasis(normal);
	LLVector3 z_vec = bbox.agentToLocalBasis(LLVector3(0.0f, 0.0f, 1.0f));
	
	LLVector3 comp1(0.f,0.f,0.f);
	LLVector3 comp2(0.f,0.f,0.f);
	LLVector3 bbox_max = bbox.getExtentLocal();
	F32 dot1 = 0.f;
	F32 dot2 = 0.f;

	// The largest component of the localized normal vector is the depth component
	// meaning that the other two are the legs of the rectangle.
	local_normal.abs();
	if(local_normal.mV[VX] > local_normal.mV[VY])
	{
		if(local_normal.mV[VX] > local_normal.mV[VZ])
		{
			// Use the y and z comps
			comp1.mV[VY] = bbox_max.mV[VY];
			comp2.mV[VZ] = bbox_max.mV[VZ];
			*depth = bbox_max.mV[VX];
		}
		else
		{
			// Use the x and y comps
			comp1.mV[VY] = bbox_max.mV[VY];
			comp2.mV[VZ] = bbox_max.mV[VZ];
			*depth = bbox_max.mV[VZ];
		}
	}
	else if(local_normal.mV[VY] > local_normal.mV[VZ])
	{
		// Use the x and z comps
		comp1.mV[VX] = bbox_max.mV[VX];
		comp2.mV[VZ] = bbox_max.mV[VZ];
		*depth = bbox_max.mV[VY];
	}
	else
	{
		// Use the x and y comps
		comp1.mV[VY] = bbox_max.mV[VY];
		comp2.mV[VZ] = bbox_max.mV[VZ];
		*depth = bbox_max.mV[VX];
	}
	
	// The height is the vector closest to vertical in the bbox coordinate space (highest dot product value)
	dot1 = comp1 * z_vec;
	dot2 = comp2 * z_vec;
	if(fabs(dot1) > fabs(dot2))
	{
		*height = comp1.length();
		*width = comp2.length();
	}
	else
	{
		*height = comp2.length();
		*width = comp1.length();
	}

	// Return the aspect ratio.
	return *width / *height;
}
예제 #20
0
void Route::DrawGLLines( ViewPort &vp, ocpnDC *dc )
{
#ifdef ocpnUSE_GL
    float pix_full_circle = WGS84_semimajor_axis_meters * mercator_k0 * 2 * PI * vp.view_scale_ppm;

    bool r1valid = false;
    wxPoint2DDouble r1;
    wxPoint2DDouble lastpoint;

    wxRoutePointListNode *node = pRoutePointList->GetFirst();
    RoutePoint *prp2 = node->GetData();
    cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &lastpoint);

    if(GetnPoints() == 1 && dc) { // single point.. make sure it shows up for highlighting
        cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r1);
        dc->DrawLine(r1.m_x, r1.m_y, r1.m_x+2, r1.m_y+2);
        return;
    }

    //    Handle offscreen points
    LLBBox bbox = vp.GetBBox();

    // dc is passed for thicker highlighted lines (performance not very important)
    if( !dc )
        glBegin(GL_LINES);

    for(node = node->GetNext(); node; node = node->GetNext()) {
        RoutePoint *prp1 = prp2;
        prp2 = node->GetData();

        // Provisional, to properly set status of last point in route
        prp2->m_pos_on_screen = false;

        {

            wxPoint2DDouble r2;
            cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r2);
            if(wxIsNaN(r2.m_x)) {
                r1valid = false;
                continue;
            }

            lastpoint = r2;             // For active track segment to ownship

            // don't need to perform calculations or render segment
            // if both points are past any edge of the vp
            // TODO: use these optimizations for dc mode
            bool lat1l = prp1->m_lat < bbox.GetMinLat(), lat2l = prp2->m_lat < bbox.GetMinLat();
            bool lat1r = prp1->m_lat > bbox.GetMaxLat(), lat2r = prp2->m_lat > bbox.GetMaxLat();
            if( (lat1l && lat2l) || (lat1r && lat2r) ) {
                r1valid = false;
                prp1->m_pos_on_screen = false;
                continue;
            }

            bool lon1l, lon1r, lon2l, lon2r;
            TestLongitude(prp1->m_lon, bbox.GetMinLon(), bbox.GetMaxLon(), lon1l, lon1r);
            TestLongitude(prp2->m_lon, bbox.GetMinLon(), bbox.GetMaxLon(), lon2l, lon2r);
            if( (lon1l && lon2l) || (lon1r && lon2r) ) {
                r1valid = false;
                prp1->m_pos_on_screen = false;
                continue;
            }

            if(!r1valid) {
                cc1->GetDoubleCanvasPointPix( prp1->m_lat, prp1->m_lon, &r1);
                if(wxIsNaN(r1.m_x))
                    continue;
            }

            //  we must decide which way to go in longitude
            //  for projections which wrap, in this case, we will render two lines
            //  (one may often be off screen which would be nice to fix but complicate things here
            //  anyway, in some cases both points are on screen, but the route wraps to either side
            //  so two lines are needed to draw this properly

            double adder = 0;
            if( (vp.m_projection_type == PROJECTION_MERCATOR ||
                    vp.m_projection_type == PROJECTION_EQUIRECTANGULAR) ) {
                float olon = vp.clon > 0 ? vp.clon - 180 : vp.clon + 180;

                if(prp1->m_lon < prp2->m_lon) {
                    if(prp2->m_lon - prp1->m_lon < 180) {
                        if(olon > prp1->m_lon && olon < prp2->m_lon)
                            adder = pix_full_circle;
                    } else if(olon < prp1->m_lon || olon > prp2->m_lon)
                        adder = -pix_full_circle;
                } else if(prp1->m_lon - prp2->m_lon < 180) {
                    if(olon < prp1->m_lon && olon > prp2->m_lon)
                        adder = -pix_full_circle;
                } else if(olon > prp1->m_lon || olon < prp2->m_lon)
                    adder = pix_full_circle;
            }

            if( dc )
                if(adder) {
                    float adderc = cos(vp.rotation)*adder, adders = sin(vp.rotation)*adder;
                    dc->DrawLine(r1.m_x, r1.m_y, r2.m_x + adderc, r2.m_y + adders);
                    dc->DrawLine(r1.m_x - adderc, r1.m_y - adders, r2.m_x, r2.m_y);
                } else
                    dc->DrawLine(r1.m_x, r1.m_y, r2.m_x, r2.m_y);
            else {
                glVertex2f(r1.m_x, r1.m_y);
                if(adder) {
                    float adderc = cos(vp.rotation)*adder, adders = sin(vp.rotation)*adder;
                    glVertex2f(r2.m_x+adderc, r2.m_y+adders);
                    glVertex2f(r1.m_x-adderc, r1.m_y-adders);
                }
                glVertex2f(r2.m_x, r2.m_y);

                // cache screen position for arrows and points
                if(!r1valid) {
                    prp1->m_pos_on_screen = !lat1l && !lat1r && !lon1l && !lon1r;
                    prp1->m_screen_pos = r1;
                }

                prp2->m_pos_on_screen = !lat2l && !lat2r && !lon2l && !lon2r;
                prp2->m_screen_pos = r2;
            }

            r1 = r2;
            r1valid = true;
        }
    }

    if( !dc )
        glEnd();
#endif
}
예제 #21
0
void Route::Draw( ocpnDC& dc, ViewPort &vp, const LLBBox &box )
{
    if( pRoutePointList->empty() )
        return;

    LLBBox test_box = GetBBox();
    if( box.IntersectOut( test_box ) ) // Route is wholly outside window
        return;

    int width = g_route_line_width;
    if( m_width != WIDTH_UNDEFINED ) width = m_width;

    if( m_bVisible && m_bRtIsSelected ) {
        wxPen spen = *g_pRouteMan->GetSelectedRoutePen();
        spen.SetWidth( width );
        dc.SetPen( spen );
        dc.SetBrush( *g_pRouteMan->GetSelectedRouteBrush() );
    }
    else if ( m_bVisible )
    {
        wxPenStyle style = wxPENSTYLE_SOLID;
        wxColour col;
        if( m_style != wxPENSTYLE_INVALID ) style = m_style;
        if( m_Colour == wxEmptyString ) {
            col = g_pRouteMan->GetRoutePen()->GetColour();
        } else {
            for( unsigned int i = 0; i < sizeof( ::GpxxColorNames ) / sizeof(wxString); i++ ) {
                if( m_Colour == ::GpxxColorNames[i] ) {
                    col = ::GpxxColors[i];
                    break;
                }
            }
        }
        dc.SetPen( *wxThePenList->FindOrCreatePen( col, width, style ) );
        dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( col, wxBRUSHSTYLE_SOLID ) );
    }

    if( m_bVisible && m_bRtIsActive )
    {
        wxPen spen = *g_pRouteMan->GetActiveRoutePen();
        spen.SetWidth( width );
        dc.SetPen( spen );
        dc.SetBrush( *g_pRouteMan->GetActiveRouteBrush() );
    }

    wxPoint rpt1, rpt2;
    if ( m_bVisible )
        DrawPointWhich( dc, 1, &rpt1 );

    wxRoutePointListNode *node = pRoutePointList->GetFirst();
    RoutePoint *prp1 = node->GetData();
    node = node->GetNext();

    if ( !m_bVisible && prp1->m_bKeepXRoute )
        prp1->Draw( dc );

    while( node ) {

        RoutePoint *prp2 = node->GetData();
        if ( !m_bVisible && prp2->m_bKeepXRoute )
            prp2->Draw( dc );
        else if (m_bVisible)
            prp2->Draw( dc, &rpt2 );

        if ( m_bVisible )
        {
            //    Handle offscreen points
            bool b_2_on = vp.GetBBox().Contains( prp2->m_lat,  prp2->m_lon );
            bool b_1_on = vp.GetBBox().Contains( prp1->m_lat,  prp1->m_lon );

            //Simple case
            if( b_1_on && b_2_on ) RenderSegment( dc, rpt1.x, rpt1.y, rpt2.x, rpt2.y, vp, true, m_hiliteWidth ); // with arrows

            //    In the cases where one point is on, and one off
            //    we must decide which way to go in longitude
            //     Arbitrarily, we will go the shortest way

            double pix_full_circle = WGS84_semimajor_axis_meters * mercator_k0 * 2 * PI
                                     * vp.view_scale_ppm;
            double dp = pow( (double) ( rpt1.x - rpt2.x ), 2 ) + pow( (double) ( rpt1.y - rpt2.y ), 2 );
            double dtest;
            int adder;
            if( b_1_on && !b_2_on ) {
                if( rpt2.x < rpt1.x ) adder = (int) pix_full_circle;
                else
                    adder = -(int) pix_full_circle;

                dtest = pow( (double) ( rpt1.x - ( rpt2.x + adder ) ), 2 )
                        + pow( (double) ( rpt1.y - rpt2.y ), 2 );

                if( dp < dtest ) adder = 0;

                RenderSegment( dc, rpt1.x, rpt1.y, rpt2.x + adder, rpt2.y, vp, true, m_hiliteWidth );
            } else if( !b_1_on ) {
                if( rpt1.x < rpt2.x ) adder = (int) pix_full_circle;
                else
                    adder = -(int) pix_full_circle;

                float rxd = rpt2.x - ( rpt1.x + adder );
                float ryd = rpt1.y - rpt2.y;
                dtest = rxd*rxd + ryd*ryd;

                if( dp < dtest ) adder = 0;

                RenderSegment( dc, rpt1.x + adder, rpt1.y, rpt2.x, rpt2.y, vp, true, m_hiliteWidth );
            }
        }

        rpt1 = rpt2;
        prp1 = prp2;

        node = node->GetNext();
    }
}
예제 #22
0
void QToolAlign::align()
{
	// no linkset parts, please
	LLSelectMgr::getInstance()->promoteSelectionToRoot();
	
	std::vector<LLPointer<LLViewerObject> > objects;
	std::map<LLPointer<LLViewerObject>, LLBBox > original_bboxes;
	
    // cycle over the nodes in selection and collect them into an array
	for (LLObjectSelection::root_iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
		 selection_iter != LLSelectMgr::getInstance()->getSelection()->root_end();
		 ++selection_iter)
	{
		LLSelectNode *select_node = *selection_iter;
		if (select_node)
		{
			LLViewerObject* object = select_node->getObject();
			if (object)
			{
				LLVector3 position = object->getPositionAgent();
	
				LLBBox bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3());
				bbox.addPointLocal(LLVector3());

				// add the parent's bbox
				bbox.addBBoxAgent(object->getBoundingBoxAgent());
				LLViewerObject::const_child_list_t& children = object->getChildren();

				for (LLViewerObject::const_child_list_t::const_iterator i = children.begin();
					 i != children.end(); i++)
				{
					// add the child's bbox
					LLViewerObject* child = *i;
					bbox.addBBoxAgent(child->getBoundingBoxAgent());
				}
				
				objects.push_back(object);
				original_bboxes[object] = bbox;
			}
		}
	}

	S32 axis = mHighlightedAxis;
	F32 direction = mHighlightedDirection;

	// sort them into positional order for proper packing
	BBoxCompare compare(axis, direction, original_bboxes);
	sort(objects.begin(), objects.end(), compare);

	// storage for their new position after alignment - start with original position first
	std::map<LLPointer<LLViewerObject>, LLBBox > new_bboxes = original_bboxes;

	// find new positions
	for (U32 i = 0; i < objects.size(); i++)
	{
		LLBBox target_bbox = mBBox;
		LLVector3 target_corner = target_bbox.getCenterAgent() - 
			direction * target_bbox.getExtentLocal() / 2.0;
	
		LLViewerObject* object = objects[i];

		LLBBox this_bbox = original_bboxes[object];
		LLVector3 this_corner = this_bbox.getCenterAgent() -
			direction * this_bbox.getExtentLocal() / 2.0;

		// for packing, we cycle over several possible positions, taking the smallest that does not overlap
		F32 smallest = direction * 9999999;  // 999999 guarenteed not to be the smallest
		for (U32 j = 0; j <= i; j++)
		{
			// how far must it move?
			LLVector3 delta = target_corner - this_corner;

			// new position moves only on one axis, please
			LLVector3 delta_one_axis = LLVector3(0,0,0);
			delta_one_axis.mV[axis] = delta.mV[axis];
			
			LLVector3 new_position = this_bbox.getCenterAgent() + delta_one_axis;

			// construct the new bbox
			LLBBox new_bbox = LLBBox(new_position, LLQuaternion(), LLVector3(), LLVector3());
			new_bbox.addPointLocal(this_bbox.getExtentLocal() / 2.0);
			new_bbox.addPointLocal(-1.0 * this_bbox.getExtentLocal() / 2.0);

			// check to see if it overlaps the previously placed objects
			BOOL overlap = FALSE;

			llwarns << "i=" << i << " j=" << j << llendl;
			
			if (!mForce) // well, don't check if in force mode
			{
				for (U32 k = 0; k < i; k++)
				{
					LLViewerObject* other_object = objects[k];
					LLBBox other_bbox = new_bboxes[other_object];

					BOOL overlaps_this = bbox_overlap(other_bbox, new_bbox);

					if (overlaps_this)
					{
						llwarns << "overlap" << new_bbox.getCenterAgent() << other_bbox.getCenterAgent() << llendl;
						llwarns << "extent" << new_bbox.getExtentLocal() << other_bbox.getExtentLocal() << llendl;
					}

					overlap = (overlap || overlaps_this);
				}
			}

			if (!overlap)
			{
				F32 this_value = (new_bbox.getCenterAgent() -
								  direction * new_bbox.getExtentLocal() / 2.0).mV[axis];

				if (direction * this_value < direction * smallest)
				{
					smallest = this_value;
					// store it
					new_bboxes[object] = new_bbox;
				}
			}

			// update target for next time through the loop
			if (j < objects.size())
			{
				LLBBox next_bbox = new_bboxes[objects[j]];
				target_corner = next_bbox.getCenterAgent() +
					direction * next_bbox.getExtentLocal() / 2.0;
			}
		}
	}

	
	// now move them in (Unsigned not Signed in 2.0)
	for (U32 i = 0; i < objects.size(); i++)
{
		LLViewerObject* object = objects[i];

		LLBBox original_bbox = original_bboxes[object];
		LLBBox new_bbox = new_bboxes[object];

		LLVector3 delta = new_bbox.getCenterAgent() - original_bbox.getCenterAgent();
		
		LLVector3 original_position = object->getPositionAgent();
		LLVector3 new_position = original_position + delta;

		object->setPosition(new_position);
	}
	
	
	LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
}