<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// M113 track shoe subsystem (single pin).
//
// =============================================================================

#include "chrono/assets/ChCylinderShape.h"
#include "chrono/assets/ChTriangleMeshShape.h"
#include "chrono/assets/ChColorAsset.h"
#include "chrono/utils/ChUtilsInputOutput.h"

#include "chrono_vehicle/ChVehicleModelData.h"

#include "m113/M113_TrackShoe.h"

using namespace chrono;
using namespace chrono::vehicle;

namespace m113 {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------
const double M113_TrackShoe::m_shoe_height = 0.06;
const double M113_TrackShoe::m_shoe_pitch = 0.154;
const double M113_TrackShoe::m_shoe_mass = 18.02;
const chrono::ChVector<> M113_TrackShoe::m_shoe_inertia(0.22, 0.04, 0.25);

const double M113_TrackShoe::m_cyl_radius = 0.015;
const double M113_TrackShoe::m_front_cyl_loc = 0.0535;
const double M113_TrackShoe::m_rear_cyl_loc = -0.061;

const std::string M113_TrackShoe::m_meshName = "TrackShoe_POV_geom";
const std::string M113_TrackShoe::m_meshFile = vehicle::GetDataFile("M113/TrackShoe.obj");

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
M113_TrackShoe::M113_TrackShoe(VisualizationType vis_type) : ChSinglePinShoe("M113_TrackShoe"), m_vis_type(vis_type) {
    SetContactMaterial(0.4f, 0.1f, 1e8f, 0.3f);
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void M113_TrackShoe::AddShoeContact() {
    m_shoe->GetCollisionModel()->ClearModel();
    m_shoe->GetCollisionModel()->AddBox(0.055, 0.095, 0.03);
    m_shoe->GetCollisionModel()->AddBox(0.0142, 0.0055, 0.0375, ChVector<>(0.05, 0, 0.0375));
    m_shoe->GetCollisionModel()->BuildModel();
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void M113_TrackShoe::AddShoeVisualization() {
    switch (m_vis_type) {
        case PRIMITIVES: {
            ChSharedPtr<ChCylinderShape> rev_axis(new ChCylinderShape);
            rev_axis->GetCylinderGeometry().p1 = ChVector<>(0.077, -0.15, 0);
            rev_axis->GetCylinderGeometry().p2 = ChVector<>(0.077, 0.15, 0);
            rev_axis->GetCylinderGeometry().rad = 0.01;
            m_shoe->AddAsset(rev_axis);

            ChSharedPtr<ChCylinderShape> cyl_FR(new ChCylinderShape);
            cyl_FR->GetCylinderGeometry().p1 = ChVector<>(m_front_cyl_loc, -0.1402, 0);
            cyl_FR->GetCylinderGeometry().p2 = ChVector<>(m_front_cyl_loc, -0.0512, 0);
            cyl_FR->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_FR);

            ChSharedPtr<ChCylinderShape> cyl_RR(new ChCylinderShape);
            cyl_RR->GetCylinderGeometry().p1 = ChVector<>(m_rear_cyl_loc, -0.1402, 0);
            cyl_RR->GetCylinderGeometry().p2 = ChVector<>(m_rear_cyl_loc, -0.0512, 0);
            cyl_RR->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_RR);

            ChSharedPtr<ChCylinderShape> cyl_FL(new ChCylinderShape);
            cyl_FL->GetCylinderGeometry().p1 = ChVector<>(m_front_cyl_loc, 0.1402, 0);
            cyl_FL->GetCylinderGeometry().p2 = ChVector<>(m_front_cyl_loc, 0.0512, 0);
            cyl_FL->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_FL);

            ChSharedPtr<ChCylinderShape> cyl_RL(new ChCylinderShape);
            cyl_RL->GetCylinderGeometry().p1 = ChVector<>(m_rear_cyl_loc, 0.1402, 0);
            cyl_RL->GetCylinderGeometry().p2 = ChVector<>(m_rear_cyl_loc, 0.0512, 0);
            cyl_RL->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_RL);

            ChSharedPtr<ChBoxShape> box_shoe(new ChBoxShape);
            box_shoe->GetBoxGeometry().SetLengths(ChVector<>(0.11, 0.19, 0.06));
            box_shoe->GetBoxGeometry().Pos = ChVector<>(0, 0, 0);
            m_shoe->AddAsset(box_shoe);

            ChSharedPtr<ChBoxShape> box_pin(new ChBoxShape);
            box_pin->GetBoxGeometry().SetLengths(ChVector<>(0.0284, 0.0114, 0.075));
            box_pin->GetBoxGeometry().Pos = ChVector<>(0.0562, 0, 0.0375);
            m_shoe->AddAsset(box_pin);

            ChSharedPtr<ChColorAsset> col(new ChColorAsset);
            if (m_index == 0)
                col->SetColor(ChColor(0.6f, 0.3f, 0.3f));
            else if (m_index % 2 == 0)
                col->SetColor(ChColor(0.3f, 0.6f, 0.3f));
            else
                col->SetColor(ChColor(0.3f, 0.3f, 0.6f));
            m_shoe->AddAsset(col);

            break;
        }
        case MESH: {
            geometry::ChTriangleMeshConnected trimesh;
            trimesh.LoadWavefrontMesh(m_meshFile, false, false);

            ChSharedPtr<ChTriangleMeshShape> trimesh_shape(new ChTriangleMeshShape);
            trimesh_shape->SetMesh(trimesh);
            trimesh_shape->SetName(m_meshName);
            m_shoe->AddAsset(trimesh_shape);

            break;
        }
    }
}

}  // end namespace m113
<commit_msg>Adjust contact geometry for M113 track shoe.<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// M113 track shoe subsystem (single pin).
//
// =============================================================================

#include "chrono/assets/ChCylinderShape.h"
#include "chrono/assets/ChTriangleMeshShape.h"
#include "chrono/assets/ChColorAsset.h"
#include "chrono/utils/ChUtilsInputOutput.h"

#include "chrono_vehicle/ChVehicleModelData.h"

#include "m113/M113_TrackShoe.h"

using namespace chrono;
using namespace chrono::vehicle;

namespace m113 {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------
const double M113_TrackShoe::m_shoe_height = 0.06;
const double M113_TrackShoe::m_shoe_pitch = 0.154;
const double M113_TrackShoe::m_shoe_mass = 18.02;
const chrono::ChVector<> M113_TrackShoe::m_shoe_inertia(0.22, 0.04, 0.25);

const double M113_TrackShoe::m_cyl_radius = 0.015;
const double M113_TrackShoe::m_front_cyl_loc = 0.0535;
const double M113_TrackShoe::m_rear_cyl_loc = -0.061;

const std::string M113_TrackShoe::m_meshName = "TrackShoe_POV_geom";
const std::string M113_TrackShoe::m_meshFile = vehicle::GetDataFile("M113/TrackShoe.obj");

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
M113_TrackShoe::M113_TrackShoe(VisualizationType vis_type) : ChSinglePinShoe("M113_TrackShoe"), m_vis_type(vis_type) {
    SetContactMaterial(0.4f, 0.1f, 1e8f, 0.3f);
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void M113_TrackShoe::AddShoeContact() {
    m_shoe->GetCollisionModel()->ClearModel();
    m_shoe->GetCollisionModel()->AddBox(0.055, 0.095, 0.03);
    m_shoe->GetCollisionModel()->AddBox(0.0142, 0.0055, 0.0375, ChVector<>(0.045, 0, 0.0375));
    m_shoe->GetCollisionModel()->BuildModel();
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void M113_TrackShoe::AddShoeVisualization() {
    switch (m_vis_type) {
        case PRIMITIVES: {
            ChSharedPtr<ChCylinderShape> rev_axis(new ChCylinderShape);
            rev_axis->GetCylinderGeometry().p1 = ChVector<>(0.077, -0.15, 0);
            rev_axis->GetCylinderGeometry().p2 = ChVector<>(0.077, 0.15, 0);
            rev_axis->GetCylinderGeometry().rad = 0.01;
            m_shoe->AddAsset(rev_axis);

            ChSharedPtr<ChCylinderShape> cyl_FR(new ChCylinderShape);
            cyl_FR->GetCylinderGeometry().p1 = ChVector<>(m_front_cyl_loc, -0.1402, 0);
            cyl_FR->GetCylinderGeometry().p2 = ChVector<>(m_front_cyl_loc, -0.0512, 0);
            cyl_FR->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_FR);

            ChSharedPtr<ChCylinderShape> cyl_RR(new ChCylinderShape);
            cyl_RR->GetCylinderGeometry().p1 = ChVector<>(m_rear_cyl_loc, -0.1402, 0);
            cyl_RR->GetCylinderGeometry().p2 = ChVector<>(m_rear_cyl_loc, -0.0512, 0);
            cyl_RR->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_RR);

            ChSharedPtr<ChCylinderShape> cyl_FL(new ChCylinderShape);
            cyl_FL->GetCylinderGeometry().p1 = ChVector<>(m_front_cyl_loc, 0.1402, 0);
            cyl_FL->GetCylinderGeometry().p2 = ChVector<>(m_front_cyl_loc, 0.0512, 0);
            cyl_FL->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_FL);

            ChSharedPtr<ChCylinderShape> cyl_RL(new ChCylinderShape);
            cyl_RL->GetCylinderGeometry().p1 = ChVector<>(m_rear_cyl_loc, 0.1402, 0);
            cyl_RL->GetCylinderGeometry().p2 = ChVector<>(m_rear_cyl_loc, 0.0512, 0);
            cyl_RL->GetCylinderGeometry().rad = m_cyl_radius;
            m_shoe->AddAsset(cyl_RL);

            ChSharedPtr<ChBoxShape> box_shoe(new ChBoxShape);
            box_shoe->GetBoxGeometry().SetLengths(ChVector<>(0.11, 0.19, 0.06));
            box_shoe->GetBoxGeometry().Pos = ChVector<>(0, 0, 0);
            m_shoe->AddAsset(box_shoe);

            ChSharedPtr<ChBoxShape> box_pin(new ChBoxShape);
            box_pin->GetBoxGeometry().SetLengths(ChVector<>(0.0284, 0.0114, 0.075));
            box_pin->GetBoxGeometry().Pos = ChVector<>(0.045, 0, 0.0375);
            m_shoe->AddAsset(box_pin);

            ChSharedPtr<ChColorAsset> col(new ChColorAsset);
            if (m_index == 0)
                col->SetColor(ChColor(0.6f, 0.3f, 0.3f));
            else if (m_index % 2 == 0)
                col->SetColor(ChColor(0.3f, 0.6f, 0.3f));
            else
                col->SetColor(ChColor(0.3f, 0.3f, 0.6f));
            m_shoe->AddAsset(col);

            break;
        }
        case MESH: {
            geometry::ChTriangleMeshConnected trimesh;
            trimesh.LoadWavefrontMesh(m_meshFile, false, false);

            ChSharedPtr<ChTriangleMeshShape> trimesh_shape(new ChTriangleMeshShape);
            trimesh_shape->SetMesh(trimesh);
            trimesh_shape->SetName(m_meshName);
            m_shoe->AddAsset(trimesh_shape);

            break;
        }
    }
}

}  // end namespace m113
<|endoftext|>


<commit_before>//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a set of flow-insensitive security checks.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

namespace {
class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
  BugReporter &BR;
  IdentifierInfo *II_gets;
public:
  WalkAST(BugReporter &br) : BR(br),
    II_gets(0) {}

  // Statement visitor methods.
  void VisitCallExpr(CallExpr *CE);
  void VisitForStmt(ForStmt *S);
  void VisitStmt(Stmt *S) { VisitChildren(S); }

  void VisitChildren(Stmt *S);

  // Helpers.
  IdentifierInfo *GetIdentifier(IdentifierInfo *& II, const char *str);

  // Checker-specific methods.
  void CheckLoopConditionForFloat(const ForStmt *FS);
  void CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD);
};
} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Helper methods.
//===----------------------------------------------------------------------===//

IdentifierInfo *WalkAST::GetIdentifier(IdentifierInfo *& II, const char *str) {
  if (!II)
    II = &BR.getContext().Idents.get(str);

  return II;
}

//===----------------------------------------------------------------------===//
// AST walking.
//===----------------------------------------------------------------------===//

void WalkAST::VisitChildren(Stmt *S) {
  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
    if (Stmt *child = *I)
      Visit(child);
}

void WalkAST::VisitCallExpr(CallExpr *CE) {
  if (const FunctionDecl *FD = CE->getDirectCallee()) {
    CheckCall_gets(CE, FD);
  }

  // Recurse and check children.
  VisitChildren(CE);
}

void WalkAST::VisitForStmt(ForStmt *FS) {
  CheckLoopConditionForFloat(FS);

  // Recurse and check children.
  VisitChildren(FS);
}

//===----------------------------------------------------------------------===//
// Check: floating poing variable used as loop counter.
// Originally: <rdar://problem/6336718>
// Implements: CERT security coding advisory FLP-30.
//===----------------------------------------------------------------------===//

static const DeclRefExpr*
GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
  expr = expr->IgnoreParenCasts();

  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
    if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
          B->getOpcode() == BinaryOperator::Comma))
      return NULL;

    if (const DeclRefExpr *lhs = GetIncrementedVar(B->getLHS(), x, y))
      return lhs;

    if (const DeclRefExpr *rhs = GetIncrementedVar(B->getRHS(), x, y))
      return rhs;

    return NULL;
  }

  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
    const NamedDecl *ND = DR->getDecl();
    return ND == x || ND == y ? DR : NULL;
  }

  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
    return U->isIncrementDecrementOp()
      ? GetIncrementedVar(U->getSubExpr(), x, y) : NULL;

  return NULL;
}

/// CheckLoopConditionForFloat - This check looks for 'for' statements that
///  use a floating point variable as a loop counter.
///  CERT: FLP30-C, FLP30-CPP.
///
void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) {
  // Does the loop have a condition?
  const Expr *condition = FS->getCond();

  if (!condition)
    return;

  // Does the loop have an increment?
  const Expr *increment = FS->getInc();

  if (!increment)
    return;

  // Strip away '()' and casts.
  condition = condition->IgnoreParenCasts();
  increment = increment->IgnoreParenCasts();

  // Is the loop condition a comparison?
  const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);

  if (!B)
    return;

  // The actual error condition.
  if (!((B->isRelationalOp() || B->isEqualityOp()) &&
        ((B->getLHS()->getType()->isFloatingType() ||
          B->getRHS()->getType()->isFloatingType()))))
    return;

  // Are we comparing variables?
  const DeclRefExpr *drLHS = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens());
  const DeclRefExpr *drRHS = dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParens());

  if (!drLHS && !drRHS)
    return;

  const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : NULL;
  const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : NULL;

  if (!vdLHS && !vdRHS)
    return;

  // Does either variable appear in increment?
  const DeclRefExpr *drInc = GetIncrementedVar(increment, vdLHS, vdRHS);

  if (!drInc)
    return;

  // Emit the error.  First figure out which DeclRefExpr in the condition
  // referenced the compared variable.
  const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;

  llvm::SmallVector<SourceRange, 2> ranges;
  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);

  os << "Variable '" << drCond->getDecl()->getNameAsCString()
     << "' with floating point type '" << drCond->getType().getAsString()
     << "' should not be used as a loop counter";

  ranges.push_back(drCond->getSourceRange());
  ranges.push_back(drInc->getSourceRange());

  const char *bugType = "Floating point variable used as loop counter";
  BR.EmitBasicReport(bugType, "Security", os.str().c_str(),
                     FS->getLocStart(), ranges.data(), ranges.size());
}

//===----------------------------------------------------------------------===//
// Check: Any use of 'gets' is insecure.
// Originally: <rdar://problem/6335715>
// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
//===----------------------------------------------------------------------===//

void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
  if (FD->getIdentifier() != GetIdentifier(II_gets, "gets"))
    return;

  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FD->getType());
  if (!FTP)
    return;

  // Verify that the function takes a single argument.
  if (FTP->getNumArgs() != 1)
    return;

  // Is the argument a 'char*'?
  const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0));
  if (!PT)
    return;

  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
    return;

  // Issue a warning.
  SourceRange R = CE->getCallee()->getSourceRange();
  BR.EmitBasicReport("Potential buffer overflow in call to 'gets'",
                     "Security",
                     "Call to function 'gets' is extremely insecure as it can "
                     "always result in a buffer overflow",
                     CE->getLocStart(), &R, 1);
}

//===----------------------------------------------------------------------===//
// Entry point for check.
//===----------------------------------------------------------------------===//

void clang::CheckSecuritySyntaxOnly(Decl *D, BugReporter &BR) {
  WalkAST walker(BR);
  walker.Visit(D->getBody());
}
<commit_msg>In the "use of floating point variable as loop counter" check, check if the DeclRefExpr is a float, not just either argument.<commit_after>//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a set of flow-insensitive security checks.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

namespace {
class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
  BugReporter &BR;
  IdentifierInfo *II_gets;
public:
  WalkAST(BugReporter &br) : BR(br),
    II_gets(0) {}

  // Statement visitor methods.
  void VisitCallExpr(CallExpr *CE);
  void VisitForStmt(ForStmt *S);
  void VisitStmt(Stmt *S) { VisitChildren(S); }

  void VisitChildren(Stmt *S);

  // Helpers.
  IdentifierInfo *GetIdentifier(IdentifierInfo *& II, const char *str);

  // Checker-specific methods.
  void CheckLoopConditionForFloat(const ForStmt *FS);
  void CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD);
};
} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Helper methods.
//===----------------------------------------------------------------------===//

IdentifierInfo *WalkAST::GetIdentifier(IdentifierInfo *& II, const char *str) {
  if (!II)
    II = &BR.getContext().Idents.get(str);

  return II;
}

//===----------------------------------------------------------------------===//
// AST walking.
//===----------------------------------------------------------------------===//

void WalkAST::VisitChildren(Stmt *S) {
  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
    if (Stmt *child = *I)
      Visit(child);
}

void WalkAST::VisitCallExpr(CallExpr *CE) {
  if (const FunctionDecl *FD = CE->getDirectCallee()) {
    CheckCall_gets(CE, FD);
  }

  // Recurse and check children.
  VisitChildren(CE);
}

void WalkAST::VisitForStmt(ForStmt *FS) {
  CheckLoopConditionForFloat(FS);

  // Recurse and check children.
  VisitChildren(FS);
}

//===----------------------------------------------------------------------===//
// Check: floating poing variable used as loop counter.
// Originally: <rdar://problem/6336718>
// Implements: CERT security coding advisory FLP-30.
//===----------------------------------------------------------------------===//

static const DeclRefExpr*
GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
  expr = expr->IgnoreParenCasts();

  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
    if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
          B->getOpcode() == BinaryOperator::Comma))
      return NULL;

    if (const DeclRefExpr *lhs = GetIncrementedVar(B->getLHS(), x, y))
      return lhs;

    if (const DeclRefExpr *rhs = GetIncrementedVar(B->getRHS(), x, y))
      return rhs;

    return NULL;
  }

  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
    const NamedDecl *ND = DR->getDecl();
    return ND == x || ND == y ? DR : NULL;
  }

  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
    return U->isIncrementDecrementOp()
      ? GetIncrementedVar(U->getSubExpr(), x, y) : NULL;

  return NULL;
}

/// CheckLoopConditionForFloat - This check looks for 'for' statements that
///  use a floating point variable as a loop counter.
///  CERT: FLP30-C, FLP30-CPP.
///
void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) {
  // Does the loop have a condition?
  const Expr *condition = FS->getCond();

  if (!condition)
    return;

  // Does the loop have an increment?
  const Expr *increment = FS->getInc();

  if (!increment)
    return;

  // Strip away '()' and casts.
  condition = condition->IgnoreParenCasts();
  increment = increment->IgnoreParenCasts();

  // Is the loop condition a comparison?
  const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);

  if (!B)
    return;

  // Is this a comparison?
  if (!(B->isRelationalOp() || B->isEqualityOp()))
    return;

  // Are we comparing variables?
  const DeclRefExpr *drLHS = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens());
  const DeclRefExpr *drRHS = dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParens());

  // Does at least one of the variables have a floating point type?
  drLHS = drLHS && drLHS->getType()->isFloatingType() ? drLHS : NULL;
  drRHS = drRHS && drRHS->getType()->isFloatingType() ? drRHS : NULL;

  if (!drLHS && !drRHS)
    return;

  const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : NULL;
  const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : NULL;

  if (!vdLHS && !vdRHS)
    return;

  // Does either variable appear in increment?
  const DeclRefExpr *drInc = GetIncrementedVar(increment, vdLHS, vdRHS);

  if (!drInc)
    return;

  // Emit the error.  First figure out which DeclRefExpr in the condition
  // referenced the compared variable.
  const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;

  llvm::SmallVector<SourceRange, 2> ranges;
  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);

  os << "Variable '" << drCond->getDecl()->getNameAsCString()
     << "' with floating point type '" << drCond->getType().getAsString()
     << "' should not be used as a loop counter";

  ranges.push_back(drCond->getSourceRange());
  ranges.push_back(drInc->getSourceRange());

  const char *bugType = "Floating point variable used as loop counter";
  BR.EmitBasicReport(bugType, "Security", os.str().c_str(),
                     FS->getLocStart(), ranges.data(), ranges.size());
}

//===----------------------------------------------------------------------===//
// Check: Any use of 'gets' is insecure.
// Originally: <rdar://problem/6335715>
// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
//===----------------------------------------------------------------------===//

void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
  if (FD->getIdentifier() != GetIdentifier(II_gets, "gets"))
    return;

  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FD->getType());
  if (!FTP)
    return;

  // Verify that the function takes a single argument.
  if (FTP->getNumArgs() != 1)
    return;

  // Is the argument a 'char*'?
  const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0));
  if (!PT)
    return;

  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
    return;

  // Issue a warning.
  SourceRange R = CE->getCallee()->getSourceRange();
  BR.EmitBasicReport("Potential buffer overflow in call to 'gets'",
                     "Security",
                     "Call to function 'gets' is extremely insecure as it can "
                     "always result in a buffer overflow",
                     CE->getLocStart(), &R, 1);
}

//===----------------------------------------------------------------------===//
// Entry point for check.
//===----------------------------------------------------------------------===//

void clang::CheckSecuritySyntaxOnly(Decl *D, BugReporter &BR) {
  WalkAST walker(BR);
  walker.Visit(D->getBody());
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrTextureDomainEffect.h"
#include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLEffectMatrix.h"
#include "SkFloatingPoint.h"

class GrGLTextureDomainEffect : public GrGLEffect {
public:
    GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrEffect&);

    virtual void emitCode(GrGLShaderBuilder*,
                          const GrEffectStage&,
                          EffectKey,
                          const char* vertexCoords,
                          const char* outputColor,
                          const char* inputColor,
                          const TextureSamplerArray&) SK_OVERRIDE;

    virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;

    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);

private:
    GrGLUniformManager::UniformHandle fNameUni;
    GrGLEffectMatrix                  fEffectMatrix;
    GrGLfloat                         fPrevDomain[4];

    typedef GrGLEffect INHERITED;
};

GrGLTextureDomainEffect::GrGLTextureDomainEffect(const GrBackendEffectFactory& factory,
                                                 const GrEffect&)
    : INHERITED(factory)
    , fNameUni(GrGLUniformManager::kInvalidUniformHandle) {
    fPrevDomain[0] = SK_FloatNaN;
}

void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder,
                                       const GrEffectStage&,
                                       EffectKey key,
                                       const char* vertexCoords,
                                       const char* outputColor,
                                       const char* inputColor,
                                       const TextureSamplerArray& samplers) {
    const char* coords;
    fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
    fNameUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
                                   kVec4f_GrSLType, "TexDom");

    builder->fFSCode.appendf("\tvec2 clampCoord = clamp(%s, %s.xy, %s.zw);\n",
                           coords,
                           builder->getUniformCStr(fNameUni),
                           builder->getUniformCStr(fNameUni));

    builder->fFSCode.appendf("\t%s = ", outputColor);
    builder->appendTextureLookupAndModulate(&builder->fFSCode,
                                            inputColor,
                                            samplers[0],
                                            "clampCoord");
    builder->fFSCode.append(";\n");
}

void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
    const GrTextureDomainEffect& effect =
        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
    const GrRect& domain = effect.domain();

    float values[4] = {
        SkScalarToFloat(domain.left()),
        SkScalarToFloat(domain.top()),
        SkScalarToFloat(domain.right()),
        SkScalarToFloat(domain.bottom())
    };
    // vertical flip if necessary
    if (GrSurface::kBottomLeft_Origin == effect.texture(0)->origin()) {
        values[1] = 1.0f - values[1];
        values[3] = 1.0f - values[3];
        // The top and bottom were just flipped, so correct the ordering
        // of elements so that values = (l, t, r, b).
        SkTSwap(values[1], values[3]);
    }
    if (0 != memcmp(values, fPrevDomain, 4 * sizeof(GrGLfloat))) {
        uman.set4fv(fNameUni, 0, 1, values);
    }
    fEffectMatrix.setData(uman,
                          effect.getMatrix(),
                          stage.getCoordChangeMatrix(),
                          effect.texture(0));
}

GrGLEffect::EffectKey GrGLTextureDomainEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
    const GrTextureDomainEffect& effect =
        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
    return GrGLEffectMatrix::GenKey(effect.getMatrix(), effect.getMatrix(), effect.texture(0));
}

///////////////////////////////////////////////////////////////////////////////

GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture, const GrRect& domain)
    : GrSingleTextureEffect(texture)
    , fTextureDomain(domain) {
}

GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
                                             const GrRect& domain,
                                             const GrTextureParams& params)
    : GrSingleTextureEffect(texture, params)
    , fTextureDomain(domain) {
}

GrTextureDomainEffect::~GrTextureDomainEffect() {

}

const GrBackendEffectFactory& GrTextureDomainEffect::getFactory() const {
    return GrTBackendEffectFactory<GrTextureDomainEffect>::getInstance();
}

bool GrTextureDomainEffect::isEqual(const GrEffect& sBase) const {
    const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase);
    return (INHERITED::isEqual(sBase) && this->fTextureDomain == s.fTextureDomain);
}

///////////////////////////////////////////////////////////////////////////////

GR_DEFINE_EFFECT_TEST(GrTextureDomainEffect);

GrEffect* GrTextureDomainEffect::TestCreate(SkRandom* random,
                                            GrContext* context,
                                            GrTexture* textures[]) {
    int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
                                      GrEffectUnitTest::kAlphaTextureIdx;
    GrRect domain;
    domain.fLeft = random->nextUScalar1();
    domain.fRight = random->nextRangeScalar(domain.fLeft, SK_Scalar1);
    domain.fTop = random->nextUScalar1();
    domain.fBottom = random->nextRangeScalar(domain.fTop, SK_Scalar1);
    return SkNEW_ARGS(GrTextureDomainEffect, (textures[texIdx], domain));
}
<commit_msg>Fix dumb mistake of passing the same matrix to both matrix params of GrGLMatrixEffect::GenKey in texture domain effect.<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrTextureDomainEffect.h"
#include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLEffectMatrix.h"
#include "SkFloatingPoint.h"

class GrGLTextureDomainEffect : public GrGLEffect {
public:
    GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrEffect&);

    virtual void emitCode(GrGLShaderBuilder*,
                          const GrEffectStage&,
                          EffectKey,
                          const char* vertexCoords,
                          const char* outputColor,
                          const char* inputColor,
                          const TextureSamplerArray&) SK_OVERRIDE;

    virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;

    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);

private:
    GrGLUniformManager::UniformHandle fNameUni;
    GrGLEffectMatrix                  fEffectMatrix;
    GrGLfloat                         fPrevDomain[4];

    typedef GrGLEffect INHERITED;
};

GrGLTextureDomainEffect::GrGLTextureDomainEffect(const GrBackendEffectFactory& factory,
                                                 const GrEffect&)
    : INHERITED(factory)
    , fNameUni(GrGLUniformManager::kInvalidUniformHandle) {
    fPrevDomain[0] = SK_FloatNaN;
}

void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder,
                                       const GrEffectStage&,
                                       EffectKey key,
                                       const char* vertexCoords,
                                       const char* outputColor,
                                       const char* inputColor,
                                       const TextureSamplerArray& samplers) {
    const char* coords;
    fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
    fNameUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
                                   kVec4f_GrSLType, "TexDom");

    builder->fFSCode.appendf("\tvec2 clampCoord = clamp(%s, %s.xy, %s.zw);\n",
                           coords,
                           builder->getUniformCStr(fNameUni),
                           builder->getUniformCStr(fNameUni));

    builder->fFSCode.appendf("\t%s = ", outputColor);
    builder->appendTextureLookupAndModulate(&builder->fFSCode,
                                            inputColor,
                                            samplers[0],
                                            "clampCoord");
    builder->fFSCode.append(";\n");
}

void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
    const GrTextureDomainEffect& effect =
        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
    const GrRect& domain = effect.domain();

    float values[4] = {
        SkScalarToFloat(domain.left()),
        SkScalarToFloat(domain.top()),
        SkScalarToFloat(domain.right()),
        SkScalarToFloat(domain.bottom())
    };
    // vertical flip if necessary
    if (GrSurface::kBottomLeft_Origin == effect.texture(0)->origin()) {
        values[1] = 1.0f - values[1];
        values[3] = 1.0f - values[3];
        // The top and bottom were just flipped, so correct the ordering
        // of elements so that values = (l, t, r, b).
        SkTSwap(values[1], values[3]);
    }
    if (0 != memcmp(values, fPrevDomain, 4 * sizeof(GrGLfloat))) {
        uman.set4fv(fNameUni, 0, 1, values);
    }
    fEffectMatrix.setData(uman,
                          effect.getMatrix(),
                          stage.getCoordChangeMatrix(),
                          effect.texture(0));
}

GrGLEffect::EffectKey GrGLTextureDomainEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
    const GrTextureDomainEffect& effect =
        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
    return GrGLEffectMatrix::GenKey(effect.getMatrix(), stage.getCoordChangeMatrix(), effect.texture(0));
}

///////////////////////////////////////////////////////////////////////////////

GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture, const GrRect& domain)
    : GrSingleTextureEffect(texture)
    , fTextureDomain(domain) {
}

GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
                                             const GrRect& domain,
                                             const GrTextureParams& params)
    : GrSingleTextureEffect(texture, params)
    , fTextureDomain(domain) {
}

GrTextureDomainEffect::~GrTextureDomainEffect() {

}

const GrBackendEffectFactory& GrTextureDomainEffect::getFactory() const {
    return GrTBackendEffectFactory<GrTextureDomainEffect>::getInstance();
}

bool GrTextureDomainEffect::isEqual(const GrEffect& sBase) const {
    const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase);
    return (INHERITED::isEqual(sBase) && this->fTextureDomain == s.fTextureDomain);
}

///////////////////////////////////////////////////////////////////////////////

GR_DEFINE_EFFECT_TEST(GrTextureDomainEffect);

GrEffect* GrTextureDomainEffect::TestCreate(SkRandom* random,
                                            GrContext* context,
                                            GrTexture* textures[]) {
    int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
                                      GrEffectUnitTest::kAlphaTextureIdx;
    GrRect domain;
    domain.fLeft = random->nextUScalar1();
    domain.fRight = random->nextRangeScalar(domain.fLeft, SK_Scalar1);
    domain.fTop = random->nextUScalar1();
    domain.fBottom = random->nextRangeScalar(domain.fTop, SK_Scalar1);
    return SkNEW_ARGS(GrTextureDomainEffect, (textures[texIdx], domain));
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      Carlos Licea     <carlos _licea@hotmail.com>
//

#include "AbstractScanlineTextureMapper.h"

#include <QtCore/QDebug>

#include "GeoPolygon.h"
#include "GeoSceneTexture.h"
#include "MarbleDirs.h"
#include "TextureTile.h"
#include "TileLoader.h"
#include "TileLoaderHelper.h"
#include "ViewParams.h"

using namespace Marble;

// Defining INTERLACE will make sure that for two subsequent scanlines
// every second scanline will be a deep copy of the first scanline.
// This results in a more coarse resolution and in a speedup for the
// texture mapping of approx. 25%.

AbstractScanlineTextureMapper::AbstractScanlineTextureMapper( TileLoader *tileLoader, QObject * parent )
    : QObject( parent ),
      m_iPosX( 0 ),
      m_iPosY( 0 ),
      m_posX( 0.0 ),
      m_posY( 0.0 ),
      m_maxGlobalX( 0 ),
      m_maxGlobalY( 0 ),
      m_imageHeight( 0 ),
      m_imageWidth( 0 ),
      m_imageRadius( 0 ),
      m_prevLat( 0.0 ),
      m_prevLon( 0.0 ),
      m_toTileCoordinatesLon( 0.0 ),
      m_toTileCoordinatesLat( 0.0 ),
      m_interlaced( false ),
      m_tileLoader( tileLoader ),
      m_scanLine( 0 ),
      m_tile( 0 ),
      m_tileLevel( 0 ),
      m_maxTileLevel( 0 ),
      m_preloadTileLevel( -1 ),
      m_previousRadius( 0 ),
      m_tilePosX( 0 ),
      m_tilePosY( 0 ),
      m_globalWidth( 0 ),
      m_globalHeight( 0 ),
      m_normGlobalWidth( 0.0 ),
      m_normGlobalHeight( 0.0 )
{
    GeoSceneTexture * texture = 0;

    if ( tileLoader ) {
        GeoSceneLayer * layer = tileLoader->layer();
        texture = static_cast<GeoSceneTexture *>( layer->groundDataset() );
    }

    m_tileProjection = tileLoader && texture
                        ? texture->projection()
                        : GeoSceneTexture::Equirectangular;

    connect( m_tileLoader, SIGNAL( tileUpdateAvailable() ),
             this,         SLOT( notifyMapChanged() ) );

    detectMaxTileLevel();
}

AbstractScanlineTextureMapper::~AbstractScanlineTextureMapper()
{
      m_tileLoader->disconnect();
//      delete m_tileLoader;
}

void AbstractScanlineTextureMapper::setLayer( GeoSceneLayer * layer )
{
    m_tileLoader->setLayer( layer );
    GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( layer->groundDataset() );
    m_tileProjection = texture->projection();
    m_tileLevel = -1;
    detectMaxTileLevel();

    m_preloadTileLevel = -1;
    m_previousRadius = 0;
}

void AbstractScanlineTextureMapper::selectTileLevel( ViewParams* viewParams )
{
    const int radius = viewParams->radius();

    // As our tile resolution doubles with each level we calculate
    // the tile level from tilesize and the globe radius via log(2)

    qreal  linearLevel = ( 2.0 * (qreal)( radius )
			    / (qreal) ( m_tileLoader->tileWidth() ) );
    int     tileLevel   = 0;

    if ( linearLevel < 1.0 )
        linearLevel = 1.0; // Dirty fix for invalid entry linearLevel

    qreal tileLevelF = log( linearLevel ) / log( 2.0 ) + 1.0;
    tileLevel = (int)( tileLevelF );

//    qDebug() << "tileLevelF: " << tileLevelF << " tileLevel: " << tileLevel;

    qreal tileCol = 0.0;
    qreal tileRow = 0.0;

    if (    tileLevelF > tileLevel + 0.3
         && m_preloadTileLevel != tileLevel + 1
         && m_previousRadius < radius
         && tileLevel > 0 && tileLevel < m_maxTileLevel ) {

        m_preloadTileLevel = tileLevel + 1;

        centerTiles( viewParams, m_preloadTileLevel, tileCol, tileRow );
//        qDebug() << "Preload tileLevel: " << m_preloadTileLevel
//        << " tileCol: " << tileCol << " tileRow: " << tileRow;
    }
    if (    tileLevelF < tileLevel + 0.7
         && m_preloadTileLevel != tileLevel - 1
         && m_previousRadius > radius
         && tileLevel > 1 && tileLevel < m_maxTileLevel + 1 ) {

        m_preloadTileLevel = tileLevel - 1;

        centerTiles( viewParams, m_preloadTileLevel, tileCol, tileRow );
//        qDebug() << "Preload tileLevel: " << m_preloadTileLevel
//        << " tileCol: " << tileCol << " tileRow: " << tileRow;
    }
    if ( m_previousRadius == radius ) m_preloadTileLevel = -1;
    else m_previousRadius = radius;

    if ( tileLevel > m_maxTileLevel )
        tileLevel = m_maxTileLevel;

    if ( tileLevel != m_tileLevel ) {
        m_tileLoader->flush();
        tileLevelInit( tileLevel );
    }
}

void AbstractScanlineTextureMapper::centerTiles( ViewParams *viewParams,
    const int tileLevel, qreal& tileCol, qreal& tileRow )
{
    qreal centerLon, centerLat;
    viewParams->centerCoordinates( centerLon, centerLat );

    GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( m_tileLoader->layer()->groundDataset() );

    tileCol = TileLoaderHelper::levelToColumn(
                                texture->levelZeroColumns(),
                                tileLevel ) * ( 1.0 + centerLon / M_PI ) / 2.0;

    tileRow = TileLoaderHelper::levelToRow(
                                texture->levelZeroRows(),
                                tileLevel ) * ( 0.5 - centerLat / M_PI );
}

void AbstractScanlineTextureMapper::tileLevelInit( int tileLevel )
{
    //    qDebug() << "Texture Level was set to: " << tileLevel;
    m_tileLevel = tileLevel;

    m_globalWidth = m_tileLoader->globalWidth( m_tileLevel );
    m_normGlobalWidth = (qreal)( m_globalWidth / ( 2 * M_PI ) );
    m_globalHeight = m_tileLoader->globalHeight( m_tileLevel );
    m_normGlobalHeight = (qreal)( m_globalHeight /  M_PI );

    m_maxGlobalX = m_globalWidth  - 1;
    m_maxGlobalY = m_globalHeight - 1;

    // These variables move the origin of global texture coordinates from
    // the center to the upper left corner and subtract the tile position
    // in that coordinate system. In total this equals a coordinate
    // transformation to tile coordinates.

    m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
    m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
}

void AbstractScanlineTextureMapper::resizeMap(int width, int height)
{
    m_imageHeight = height;
    m_imageWidth  = width;

    m_imageRadius = ( m_imageWidth * m_imageWidth / 4
                      + m_imageHeight * m_imageHeight / 4 );
}

void AbstractScanlineTextureMapper::pixelValue(const qreal& lon,
                                               const qreal& lat,
                                               QRgb* scanLine,
                                               bool smooth )
{
    // The same method using integers performs about 33% faster.
    // However we need the qreal version to create the high quality mode.

    if ( smooth ) {
        // Convert the lon and lat coordinates of the position on the scanline
        // measured in radian to the pixel position of the requested
        // coordinate on the current tile.

        m_posX = m_toTileCoordinatesLon + rad2PixelX( lon );
        m_posY = m_toTileCoordinatesLat + rad2PixelY( lat );

        // Most of the time while moving along the scanLine we'll stay on the
        // same tile. However at the tile border we might "fall off". If that
        // happens we need to find out the next tile that needs to be loaded.

        if ( m_posX  >= (qreal)( m_tileLoader->tileWidth() )
            || m_posX < 0.0
            || m_posY >= (qreal)( m_tileLoader->tileHeight() )
            || m_posY < 0.0 )
        {
            nextTile( m_posX, m_posY );
        }

        QRgb topLeftValue = m_tile->pixel( (int)(m_posX), (int)(m_posY) );
        *scanLine = bilinearSmooth( topLeftValue );
    }
    else {
        // Convert the lon and lat coordinates of the position on the scanline
        // measured in radian to the pixel position of the requested
        // coordinate on the current tile.

        m_iPosX = (int)( m_toTileCoordinatesLon + rad2PixelX( lon ) );
        m_iPosY = (int)( m_toTileCoordinatesLat + rad2PixelY( lat ) );

        // Most of the time while moving along the scanLine we'll stay on the
        // same tile. However at the tile border we might "fall off". If that
        // happens we need to find out the next tile that needs to be loaded.

        if ( m_iPosX  >= m_tileLoader->tileWidth()
            || m_iPosX < 0
            || m_iPosY >= m_tileLoader->tileHeight()
            || m_iPosY < 0 )
        {
            nextTile( m_iPosX, m_iPosY );
        }

        *scanLine = m_tile->pixel( m_iPosX, m_iPosY );
    }
}

void AbstractScanlineTextureMapper::nextTile( int &posX, int &posY )
{
    // Move from tile coordinates to global texture coordinates
    // ( with origin in upper left corner, measured in pixel)

    int lon = posX + m_tilePosX;
    if ( lon > m_maxGlobalX ) lon -= m_maxGlobalX;
    if ( lon < 0 ) lon += m_maxGlobalX;

    int lat = posY + m_tilePosY;
    if ( lat > m_maxGlobalY ) lat -= m_maxGlobalY;
    if ( lat < 0 ) lat += m_maxGlobalY;

    // tileCol counts the tile columns left from the current tile.
    // tileRow counts the tile rows on the top from the current tile.

    int tileCol = lon / m_tileLoader->tileWidth();
    int tileRow = lat / m_tileLoader->tileHeight();

    m_tile = m_tileLoader->loadTile( tileCol, tileRow, m_tileLevel );

    // Update position variables:
    // m_tilePosX/Y stores the position of the tiles in
    // global texture coordinates
    // ( origin upper left, measured in pixels )

    m_tilePosX = tileCol * m_tileLoader->tileWidth();
    m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
    posX = lon - m_tilePosX;

    m_tilePosY = tileRow * m_tileLoader->tileHeight();
    m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
    posY = lat - m_tilePosY;
}

void AbstractScanlineTextureMapper::nextTile( qreal &posX, qreal &posY )
{
    // Move from tile coordinates to global texture coordinates
    // ( with origin in upper left corner, measured in pixel)

    int lon = (int)(posX + m_tilePosX);
    if ( lon > m_maxGlobalX ) lon -= m_maxGlobalX;
    if ( lon < 0 ) lon += m_maxGlobalX;

    int lat = (int)(posY + m_tilePosY);
    if ( lat > m_maxGlobalY ) lat -= m_maxGlobalY;
    if ( lat < 0 ) lat += m_maxGlobalY;

    // tileCol counts the tile columns left from the current tile.
    // tileRow counts the tile rows on the top from the current tile.

    int tileCol = lon / m_tileLoader->tileWidth();
    int tileRow = lat / m_tileLoader->tileHeight();

    m_tile = m_tileLoader->loadTile( tileCol, tileRow, m_tileLevel );

    // Update position variables:
    // m_tilePosX/Y stores the position of the tiles in
    // global texture coordinates
    // ( origin upper left, measured in pixels )

    m_tilePosX = tileCol * m_tileLoader->tileWidth();
    m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
    posX = lon - m_tilePosX;

    m_tilePosY = tileRow * m_tileLoader->tileHeight();
    m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
    posY = lat - m_tilePosY;
}

void AbstractScanlineTextureMapper::notifyMapChanged()
{
    detectMaxTileLevel();
//    qDebug() << "MAPCHANGED";
    emit mapChanged();
}

void AbstractScanlineTextureMapper::detectMaxTileLevel()
{
    m_maxTileLevel = TileLoader::maxPartialTileLevel( m_tileLoader->layer() ) + 1 ;
//    qDebug() << "MaxTileLevel: " << m_maxTileLevel;
}

#include "AbstractScanlineTextureMapper.moc"
<commit_msg>- Second try ... <commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      Carlos Licea     <carlos _licea@hotmail.com>
//

#include "AbstractScanlineTextureMapper.h"

#include <QtCore/QDebug>

#include "GeoPolygon.h"
#include "GeoSceneTexture.h"
#include "MarbleDirs.h"
#include "TextureTile.h"
#include "TileLoader.h"
#include "TileLoaderHelper.h"
#include "ViewParams.h"

using namespace Marble;

// Defining INTERLACE will make sure that for two subsequent scanlines
// every second scanline will be a deep copy of the first scanline.
// This results in a more coarse resolution and in a speedup for the
// texture mapping of approx. 25%.

AbstractScanlineTextureMapper::AbstractScanlineTextureMapper( TileLoader *tileLoader, QObject * parent )
    : QObject( parent ),
      m_iPosX( 0 ),
      m_iPosY( 0 ),
      m_posX( 0.0 ),
      m_posY( 0.0 ),
      m_maxGlobalX( 0 ),
      m_maxGlobalY( 0 ),
      m_imageHeight( 0 ),
      m_imageWidth( 0 ),
      m_imageRadius( 0 ),
      m_prevLat( 0.0 ),
      m_prevLon( 0.0 ),
      m_toTileCoordinatesLon( 0.0 ),
      m_toTileCoordinatesLat( 0.0 ),
      m_interlaced( false ),
      m_tileLoader( tileLoader ),
      m_scanLine( 0 ),
      m_tile( 0 ),
      m_tileLevel( 0 ),
      m_maxTileLevel( 0 ),
      m_preloadTileLevel( -1 ),
      m_previousRadius( 0 ),
      m_tilePosX( 0 ),
      m_tilePosY( 0 ),
      m_globalWidth( 0 ),
      m_globalHeight( 0 ),
      m_normGlobalWidth( 0.0 ),
      m_normGlobalHeight( 0.0 )
{
    GeoSceneTexture * texture = 0;

    if ( tileLoader ) {
        GeoSceneLayer * layer = tileLoader->layer();
        if ( layer ) {
            texture = static_cast<GeoSceneTexture *>( layer->groundDataset() );
        }
    }

    m_tileProjection = tileLoader && texture
                        ? texture->projection()
                        : GeoSceneTexture::Equirectangular;

    connect( m_tileLoader, SIGNAL( tileUpdateAvailable() ),
             this,         SLOT( notifyMapChanged() ) );

    detectMaxTileLevel();
}

AbstractScanlineTextureMapper::~AbstractScanlineTextureMapper()
{
      m_tileLoader->disconnect();
//      delete m_tileLoader;
}

void AbstractScanlineTextureMapper::setLayer( GeoSceneLayer * layer )
{
    m_tileLoader->setLayer( layer );
    GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( layer->groundDataset() );
    m_tileProjection = texture->projection();
    m_tileLevel = -1;
    detectMaxTileLevel();

    m_preloadTileLevel = -1;
    m_previousRadius = 0;
}

void AbstractScanlineTextureMapper::selectTileLevel( ViewParams* viewParams )
{
    const int radius = viewParams->radius();

    // As our tile resolution doubles with each level we calculate
    // the tile level from tilesize and the globe radius via log(2)

    qreal  linearLevel = ( 2.0 * (qreal)( radius )
			    / (qreal) ( m_tileLoader->tileWidth() ) );
    int     tileLevel   = 0;

    if ( linearLevel < 1.0 )
        linearLevel = 1.0; // Dirty fix for invalid entry linearLevel

    qreal tileLevelF = log( linearLevel ) / log( 2.0 ) + 1.0;
    tileLevel = (int)( tileLevelF );

//    qDebug() << "tileLevelF: " << tileLevelF << " tileLevel: " << tileLevel;

    qreal tileCol = 0.0;
    qreal tileRow = 0.0;

    if (    tileLevelF > tileLevel + 0.3
         && m_preloadTileLevel != tileLevel + 1
         && m_previousRadius < radius
         && tileLevel > 0 && tileLevel < m_maxTileLevel ) {

        m_preloadTileLevel = tileLevel + 1;

        centerTiles( viewParams, m_preloadTileLevel, tileCol, tileRow );
//        qDebug() << "Preload tileLevel: " << m_preloadTileLevel
//        << " tileCol: " << tileCol << " tileRow: " << tileRow;
    }
    if (    tileLevelF < tileLevel + 0.7
         && m_preloadTileLevel != tileLevel - 1
         && m_previousRadius > radius
         && tileLevel > 1 && tileLevel < m_maxTileLevel + 1 ) {

        m_preloadTileLevel = tileLevel - 1;

        centerTiles( viewParams, m_preloadTileLevel, tileCol, tileRow );
//        qDebug() << "Preload tileLevel: " << m_preloadTileLevel
//        << " tileCol: " << tileCol << " tileRow: " << tileRow;
    }
    if ( m_previousRadius == radius ) m_preloadTileLevel = -1;
    else m_previousRadius = radius;

    if ( tileLevel > m_maxTileLevel )
        tileLevel = m_maxTileLevel;

    if ( tileLevel != m_tileLevel ) {
        m_tileLoader->flush();
        tileLevelInit( tileLevel );
    }
}

void AbstractScanlineTextureMapper::centerTiles( ViewParams *viewParams,
    const int tileLevel, qreal& tileCol, qreal& tileRow )
{
    qreal centerLon, centerLat;
    viewParams->centerCoordinates( centerLon, centerLat );

    GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( m_tileLoader->layer()->groundDataset() );

    tileCol = TileLoaderHelper::levelToColumn(
                                texture->levelZeroColumns(),
                                tileLevel ) * ( 1.0 + centerLon / M_PI ) / 2.0;

    tileRow = TileLoaderHelper::levelToRow(
                                texture->levelZeroRows(),
                                tileLevel ) * ( 0.5 - centerLat / M_PI );
}

void AbstractScanlineTextureMapper::tileLevelInit( int tileLevel )
{
    //    qDebug() << "Texture Level was set to: " << tileLevel;
    m_tileLevel = tileLevel;

    m_globalWidth = m_tileLoader->globalWidth( m_tileLevel );
    m_normGlobalWidth = (qreal)( m_globalWidth / ( 2 * M_PI ) );
    m_globalHeight = m_tileLoader->globalHeight( m_tileLevel );
    m_normGlobalHeight = (qreal)( m_globalHeight /  M_PI );

    m_maxGlobalX = m_globalWidth  - 1;
    m_maxGlobalY = m_globalHeight - 1;

    // These variables move the origin of global texture coordinates from
    // the center to the upper left corner and subtract the tile position
    // in that coordinate system. In total this equals a coordinate
    // transformation to tile coordinates.

    m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
    m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
}

void AbstractScanlineTextureMapper::resizeMap(int width, int height)
{
    m_imageHeight = height;
    m_imageWidth  = width;

    m_imageRadius = ( m_imageWidth * m_imageWidth / 4
                      + m_imageHeight * m_imageHeight / 4 );
}

void AbstractScanlineTextureMapper::pixelValue(const qreal& lon,
                                               const qreal& lat,
                                               QRgb* scanLine,
                                               bool smooth )
{
    // The same method using integers performs about 33% faster.
    // However we need the qreal version to create the high quality mode.

    if ( smooth ) {
        // Convert the lon and lat coordinates of the position on the scanline
        // measured in radian to the pixel position of the requested
        // coordinate on the current tile.

        m_posX = m_toTileCoordinatesLon + rad2PixelX( lon );
        m_posY = m_toTileCoordinatesLat + rad2PixelY( lat );

        // Most of the time while moving along the scanLine we'll stay on the
        // same tile. However at the tile border we might "fall off". If that
        // happens we need to find out the next tile that needs to be loaded.

        if ( m_posX  >= (qreal)( m_tileLoader->tileWidth() )
            || m_posX < 0.0
            || m_posY >= (qreal)( m_tileLoader->tileHeight() )
            || m_posY < 0.0 )
        {
            nextTile( m_posX, m_posY );
        }

        QRgb topLeftValue = m_tile->pixel( (int)(m_posX), (int)(m_posY) );
        *scanLine = bilinearSmooth( topLeftValue );
    }
    else {
        // Convert the lon and lat coordinates of the position on the scanline
        // measured in radian to the pixel position of the requested
        // coordinate on the current tile.

        m_iPosX = (int)( m_toTileCoordinatesLon + rad2PixelX( lon ) );
        m_iPosY = (int)( m_toTileCoordinatesLat + rad2PixelY( lat ) );

        // Most of the time while moving along the scanLine we'll stay on the
        // same tile. However at the tile border we might "fall off". If that
        // happens we need to find out the next tile that needs to be loaded.

        if ( m_iPosX  >= m_tileLoader->tileWidth()
            || m_iPosX < 0
            || m_iPosY >= m_tileLoader->tileHeight()
            || m_iPosY < 0 )
        {
            nextTile( m_iPosX, m_iPosY );
        }

        *scanLine = m_tile->pixel( m_iPosX, m_iPosY );
    }
}

void AbstractScanlineTextureMapper::nextTile( int &posX, int &posY )
{
    // Move from tile coordinates to global texture coordinates
    // ( with origin in upper left corner, measured in pixel)

    int lon = posX + m_tilePosX;
    if ( lon > m_maxGlobalX ) lon -= m_maxGlobalX;
    if ( lon < 0 ) lon += m_maxGlobalX;

    int lat = posY + m_tilePosY;
    if ( lat > m_maxGlobalY ) lat -= m_maxGlobalY;
    if ( lat < 0 ) lat += m_maxGlobalY;

    // tileCol counts the tile columns left from the current tile.
    // tileRow counts the tile rows on the top from the current tile.

    int tileCol = lon / m_tileLoader->tileWidth();
    int tileRow = lat / m_tileLoader->tileHeight();

    m_tile = m_tileLoader->loadTile( tileCol, tileRow, m_tileLevel );

    // Update position variables:
    // m_tilePosX/Y stores the position of the tiles in
    // global texture coordinates
    // ( origin upper left, measured in pixels )

    m_tilePosX = tileCol * m_tileLoader->tileWidth();
    m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
    posX = lon - m_tilePosX;

    m_tilePosY = tileRow * m_tileLoader->tileHeight();
    m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
    posY = lat - m_tilePosY;
}

void AbstractScanlineTextureMapper::nextTile( qreal &posX, qreal &posY )
{
    // Move from tile coordinates to global texture coordinates
    // ( with origin in upper left corner, measured in pixel)

    int lon = (int)(posX + m_tilePosX);
    if ( lon > m_maxGlobalX ) lon -= m_maxGlobalX;
    if ( lon < 0 ) lon += m_maxGlobalX;

    int lat = (int)(posY + m_tilePosY);
    if ( lat > m_maxGlobalY ) lat -= m_maxGlobalY;
    if ( lat < 0 ) lat += m_maxGlobalY;

    // tileCol counts the tile columns left from the current tile.
    // tileRow counts the tile rows on the top from the current tile.

    int tileCol = lon / m_tileLoader->tileWidth();
    int tileRow = lat / m_tileLoader->tileHeight();

    m_tile = m_tileLoader->loadTile( tileCol, tileRow, m_tileLevel );

    // Update position variables:
    // m_tilePosX/Y stores the position of the tiles in
    // global texture coordinates
    // ( origin upper left, measured in pixels )

    m_tilePosX = tileCol * m_tileLoader->tileWidth();
    m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
    posX = lon - m_tilePosX;

    m_tilePosY = tileRow * m_tileLoader->tileHeight();
    m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
    posY = lat - m_tilePosY;
}

void AbstractScanlineTextureMapper::notifyMapChanged()
{
    detectMaxTileLevel();
//    qDebug() << "MAPCHANGED";
    emit mapChanged();
}

void AbstractScanlineTextureMapper::detectMaxTileLevel()
{
    m_maxTileLevel = TileLoader::maxPartialTileLevel( m_tileLoader->layer() ) + 1 ;
//    qDebug() << "MaxTileLevel: " << m_maxTileLevel;
}

#include "AbstractScanlineTextureMapper.moc"
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "IWORKGeometryElement.h"

#include <boost/lexical_cast.hpp>

#include "libetonyek_xml.h"
#include "IWORKCollector.h"
#include "IWORKDictionary.h"
#include "IWORKPositionElement.h"
#include "IWORKSizeElement.h"
#include "IWORKToken.h"
#include "IWORKXMLParserState.h"

namespace libetonyek
{

using boost::lexical_cast;

IWORKGeometryElement::IWORKGeometryElement(IWORKXMLParserState &state)
  : IWORKXMLElementContextBase(state)
  , m_geometry(0)
{
}

IWORKGeometryElement::IWORKGeometryElement(IWORKXMLParserState &state, IWORKGeometryPtr_t &geometry)
  : IWORKXMLElementContextBase(state)
  , m_geometry(&geometry)
{
}

void IWORKGeometryElement::attribute(const int name, const char *const value)
{
  switch (name)
  {
  case IWORKToken::NS_URI_SF | IWORKToken::angle :
    m_angle = deg2rad(lexical_cast<double>(value));
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::aspectRatioLocked :
    m_aspectRatioLocked = bool_cast(value);
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::horizontalFlip :
    m_horizontalFlip = bool_cast(value);
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::shearXAngle :
    m_shearXAngle = deg2rad(lexical_cast<double>(value));
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::shearYAngle :
    m_shearYAngle = deg2rad(lexical_cast<double>(value));
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::sizesLocked :
    m_sizesLocked = bool_cast(value);
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::verticalFlip :
    m_verticalFlip = bool_cast(value);
    break;
  default :
    IWORKXMLElementContextBase::attribute(name, value);
    break;
  }
}

IWORKXMLContextPtr_t IWORKGeometryElement::element(const int name)
{
  switch (name)
  {
  case IWORKToken::NS_URI_SF | IWORKToken::naturalSize :
    return makeContext<IWORKSizeElement>(getState(), m_naturalSize);
  case IWORKToken::NS_URI_SF | IWORKToken::position :
    return makeContext<IWORKPositionElement>(getState(), m_pos);
  case IWORKToken::NS_URI_SF | IWORKToken::size :
    return makeContext<IWORKSizeElement>(getState(), m_size);
  }

  return IWORKXMLContextPtr_t();
}

void IWORKGeometryElement::endOfElement()
{
  IWORKGeometryPtr_t geometry(new IWORKGeometry());
  geometry->m_naturalSize = get(m_naturalSize);
  geometry->m_size = bool(m_size) ? get(m_size) : get(m_naturalSize);
  geometry->m_position = get(m_pos);
  geometry->m_angle = m_angle;
  geometry->m_shearXAngle = m_shearXAngle;
  geometry->m_shearYAngle = m_shearYAngle;
  geometry->m_horizontalFlip = m_horizontalFlip;
  geometry->m_verticalFlip = m_verticalFlip;
  geometry->m_aspectRatioLocked = m_aspectRatioLocked;
  geometry->m_sizesLocked = m_sizesLocked;

  if (m_geometry)
    *m_geometry = geometry;
  else if (isCollector())
    getCollector().collectGeometry(geometry);
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>avoid use of empty optional<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "IWORKGeometryElement.h"

#include <boost/lexical_cast.hpp>

#include "libetonyek_xml.h"
#include "IWORKCollector.h"
#include "IWORKDictionary.h"
#include "IWORKPositionElement.h"
#include "IWORKSizeElement.h"
#include "IWORKToken.h"
#include "IWORKXMLParserState.h"

namespace libetonyek
{

using boost::lexical_cast;

IWORKGeometryElement::IWORKGeometryElement(IWORKXMLParserState &state)
  : IWORKXMLElementContextBase(state)
  , m_geometry(0)
{
}

IWORKGeometryElement::IWORKGeometryElement(IWORKXMLParserState &state, IWORKGeometryPtr_t &geometry)
  : IWORKXMLElementContextBase(state)
  , m_geometry(&geometry)
{
}

void IWORKGeometryElement::attribute(const int name, const char *const value)
{
  switch (name)
  {
  case IWORKToken::NS_URI_SF | IWORKToken::angle :
    m_angle = deg2rad(lexical_cast<double>(value));
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::aspectRatioLocked :
    m_aspectRatioLocked = bool_cast(value);
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::horizontalFlip :
    m_horizontalFlip = bool_cast(value);
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::shearXAngle :
    m_shearXAngle = deg2rad(lexical_cast<double>(value));
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::shearYAngle :
    m_shearYAngle = deg2rad(lexical_cast<double>(value));
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::sizesLocked :
    m_sizesLocked = bool_cast(value);
    break;
  case IWORKToken::NS_URI_SF | IWORKToken::verticalFlip :
    m_verticalFlip = bool_cast(value);
    break;
  default :
    IWORKXMLElementContextBase::attribute(name, value);
    break;
  }
}

IWORKXMLContextPtr_t IWORKGeometryElement::element(const int name)
{
  switch (name)
  {
  case IWORKToken::NS_URI_SF | IWORKToken::naturalSize :
    return makeContext<IWORKSizeElement>(getState(), m_naturalSize);
  case IWORKToken::NS_URI_SF | IWORKToken::position :
    return makeContext<IWORKPositionElement>(getState(), m_pos);
  case IWORKToken::NS_URI_SF | IWORKToken::size :
    return makeContext<IWORKSizeElement>(getState(), m_size);
  }

  return IWORKXMLContextPtr_t();
}

void IWORKGeometryElement::endOfElement()
{
  IWORKGeometryPtr_t geometry(new IWORKGeometry());
  if (m_naturalSize)
  {
    geometry->m_naturalSize = get(m_naturalSize);
    geometry->m_size = get(m_naturalSize);
  }
  if (m_size)
    geometry->m_size = get(m_size);
  if (m_pos)
    geometry->m_position = get(m_pos);
  geometry->m_angle = m_angle;
  geometry->m_shearXAngle = m_shearXAngle;
  geometry->m_shearYAngle = m_shearYAngle;
  geometry->m_horizontalFlip = m_horizontalFlip;
  geometry->m_verticalFlip = m_verticalFlip;
  geometry->m_aspectRatioLocked = m_aspectRatioLocked;
  geometry->m_sizesLocked = m_sizesLocked;

  if (m_geometry)
    *m_geometry = geometry;
  else if (isCollector())
    getCollector().collectGeometry(geometry);
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>// Copyright (c) 2010 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/descriptor/descriptor.h"
#include "libmv/descriptor/vector_descriptor.h"
#include "libmv/correspondence/feature.h"
#include "libmv/image/convolve.h"
#include "libmv/image/image.h"
#include "libmv/image/sample.h"
#include <cmath>

namespace libmv {
namespace descriptor {

//
// Note :
// - Angle is in radian.
// - data the output array (must be allocated to 20 values).
template <typename TImage,typename T>
void PickDipole(const TImage & image, float x, float y, float scale,
                double angle, T * data) {

  // Setup the rotation center.
  float & cx = x, & cy = y;

  double lambda1 = scale;
  double lambda2 = lambda1 / 2.0;
  double angleSubdiv = 2.0 * M_PI / 12.0;

  Vecf dipoleF1(12);
  for (int i = 0; i < 12; ++i)  {
    float xi = cx + lambda1 * cos(angle + i * angleSubdiv);
    float yi = cy + lambda1 * sin(angle + i * angleSubdiv);
    float s1 = 0.0f;
    if (image.Contains(yi,xi) ) {
      // Bilinear interpolation
      s1 = SampleLinear(image, yi, xi);
    }
    dipoleF1(i) = s1;
  }
  Matf A(8,12);
  A <<  0, 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0,
        0,-1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
        0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 1,
        0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,-1,
        0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
        1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0;

  // Add the second order F2 dipole
  Vecf dipoleF2(12);
  for (int i = 0; i < 12; ++i)  {
    double angleSample = i * angleSubdiv;
    float xi = cx + (lambda1 + lambda2) * cos(angle + angleSample);
    float yi = cy + (lambda1 + lambda2) * sin(angle + angleSample);

    float xii = cx + (lambda1 - lambda2) * cos(angle + angleSample);
    float yii = cy + (lambda1 - lambda2) * sin(angle + angleSample);

    float s1 = 0.0f;
    if (image.Contains(yi,xi) && image.Contains(yii,xii)) {
      // Bilinear interpolation
      s1 = SampleLinear(image, yi, xi) - SampleLinear(image, yii, xii);
    }
    dipoleF2(i) = s1;
  }

  (*data).template block<8,1>(0,0) = A * dipoleF1;
  (*data).template block<12,1>(8,0) = dipoleF2;
  // Normalize to be affine luminance invariant (a*I(x,y)+b).
  (*data).normalize();
}

class DipoleDescriber : public Describer {
 public:
  virtual void Describe(const vector<Feature *> &features,
                        const Image &image,
                        const detector::DetectorData *detector_data,
                        vector<Descriptor *> *descriptors) {
    (void) detector_data; // There is no matching detector for DipoleDescriptor.

    const int DIPOLE_DESC_SIZE = 20;
    descriptors->resize(features.size());
    for (int i = 0; i < features.size(); ++i) {
      PointFeature *point = dynamic_cast<PointFeature *>(features[i]);
      VecfDescriptor *descriptor = NULL;
      if (point) {
        descriptor = new VecfDescriptor(DIPOLE_DESC_SIZE);
        PickDipole( *(image.AsArray3Du()),
                  point->x(),
                  point->y(),
                  point->scale,
                  point->orientation,
                  &(descriptor->coords));
      }
      (*descriptors)[i] = descriptor;
    }
  }
};

Describer *CreateDipoleDescriber() {
  return new DipoleDescriber;
}

}  // namespace descriptor
}  // namespace libmv
<commit_msg>Fix misunderstanding about the normalization of the descriptor.<commit_after>// Copyright (c) 2010 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/descriptor/descriptor.h"
#include "libmv/descriptor/vector_descriptor.h"
#include "libmv/correspondence/feature.h"
#include "libmv/image/convolve.h"
#include "libmv/image/image.h"
#include "libmv/image/sample.h"
#include <cmath>

namespace libmv {
namespace descriptor {

//
// Note :
// - Angle is in radian.
// - data the output array (must be allocated to 20 values).
template <typename TImage,typename T>
void PickDipole(const TImage & image, float x, float y, float scale,
                double angle, T * data) {

  // Setup the rotation center.
  float & cx = x, & cy = y;

  double lambda1 = scale;
  double lambda2 = lambda1 / 2.0;
  double angleSubdiv = 2.0 * M_PI / 12.0;

  Vecf dipoleF1(12);
  for (int i = 0; i < 12; ++i)  {
    float xi = cx + lambda1 * cos(angle + i * angleSubdiv);
    float yi = cy + lambda1 * sin(angle + i * angleSubdiv);
    float s1 = 0.0f;
    if (image.Contains(yi,xi) ) {
      // Bilinear interpolation
      s1 = SampleLinear(image, yi, xi);
    }
    dipoleF1(i) = s1;
  }
  Matf A(8,12);
  A <<  0, 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0,
        0,-1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
        0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 1,
        0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,-1,
        0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
        1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0;

  // Add the second order F2 dipole
  Vecf dipoleF2(12);
  for (int i = 0; i < 12; ++i)  {
    double angleSample = i * angleSubdiv;
    float xi = cx + (lambda1 + lambda2) * cos(angle + angleSample);
    float yi = cy + (lambda1 + lambda2) * sin(angle + angleSample);

    float xii = cx + (lambda1 - lambda2) * cos(angle + angleSample);
    float yii = cy + (lambda1 - lambda2) * sin(angle + angleSample);

    float s1 = 0.0f;
    if (image.Contains(yi,xi) && image.Contains(yii,xii)) {
      // Bilinear interpolation
      s1 = SampleLinear(image, yi, xi) - SampleLinear(image, yii, xii);
    }
    dipoleF2(i) = s1;
  }

  (*data).template block<8,1>(0,0) = (A * dipoleF1).normalized();
  (*data).template block<12,1>(8,0) = dipoleF2.normalized();
  // Normalize to be affine luminance invariant (a*I(x,y)+b).
}

class DipoleDescriber : public Describer {
 public:
  virtual void Describe(const vector<Feature *> &features,
                        const Image &image,
                        const detector::DetectorData *detector_data,
                        vector<Descriptor *> *descriptors) {
    (void) detector_data; // There is no matching detector for DipoleDescriptor.

    const int DIPOLE_DESC_SIZE = 20;
    descriptors->resize(features.size());
    for (int i = 0; i < features.size(); ++i) {
      PointFeature *point = dynamic_cast<PointFeature *>(features[i]);
      VecfDescriptor *descriptor = NULL;
      if (point) {
        descriptor = new VecfDescriptor(DIPOLE_DESC_SIZE);
        PickDipole( *(image.AsArray3Du()),
                  point->x(),
                  point->y(),
                  point->scale,
                  point->orientation,
                  &(descriptor->coords));
      }
      (*descriptors)[i] = descriptor;
    }
  }
};

Describer *CreateDipoleDescriber() {
  return new DipoleDescriber;
}

}  // namespace descriptor
}  // namespace libmv
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-

#ifndef __RD_DEAD_STATE_HPP__
#define __RD_DEAD_STATE_HPP__

#include "State.hpp"
#include "Hub.hpp"
#include "InputEventListener.hpp"
#include "NetworkManager.hpp"
#include "ImageManager.hpp"
#include "InputManager.hpp"
#include "MentalMap.hpp"
#include "RobotManager.hpp"
#include "AudioManager.hpp"
#include "ScreenManager.hpp"
#include "DeadScreen.hpp"
#include "Key.hpp"
#include "WindowEvent.hpp"

namespace rd{

/**
* @ingroup GameStatesLib
*
* @brief Game Dead State
* Behavior:
*  - Waits for 10 seconds showing dead screen
*  - Then, it enables input:
*      - When user presses enter, respawns the robot and goes to game state again
*      - When user presses q, logout the game
*/
class DeadState : public State, public ManagerHub, public InputEventListener
{
public:
    DeadState(NetworkManager * networkManager, ImageManager * imageManager,
              InputManager * inputManager, MentalMap * mentalMap,
              RobotManager * robotManager, AudioManager * audioManager,
              ScreenManager * screenManager);
    virtual ~DeadState();
    virtual bool setup();
    virtual bool loop();
    virtual bool cleanup();

    //! @brief Returns the internal variable value as condition evaluation result
    virtual int evaluateConditions();

    //enum DeadStateOption {RESPAWN_SELECTED, EXIT_SELECTED};
    static const int RESPAWN_SELECTED;
    static const int EXIT_SELECTED;

    //-- InputEventListener interface:
    virtual bool onKeyDown(const Key & k);
    virtual bool onKeyUp(const Key & k);
    virtual bool onWindowEvent(const WindowEvent & event);

    static const int DEFAULT_RATE_MS;
    static const int MAX_HEALTH;

protected:
    DeadScreen screen;
    int last_transition; //-- Stores the transition that triggered the cleanup
    bool received_respawn;
    bool received_exit;
    int elapsed_time; //-- Time elapsed in ms
    int timer; //-- Countdown timer in s
};
}
#endif // __RD_DEAD_STATE_HPP__
<commit_msg>Remove unused protected member: rd::DeadState::last_transition<commit_after>// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-

#ifndef __RD_DEAD_STATE_HPP__
#define __RD_DEAD_STATE_HPP__

#include "State.hpp"
#include "Hub.hpp"
#include "InputEventListener.hpp"
#include "NetworkManager.hpp"
#include "ImageManager.hpp"
#include "InputManager.hpp"
#include "MentalMap.hpp"
#include "RobotManager.hpp"
#include "AudioManager.hpp"
#include "ScreenManager.hpp"
#include "DeadScreen.hpp"
#include "Key.hpp"
#include "WindowEvent.hpp"

namespace rd{

/**
* @ingroup GameStatesLib
*
* @brief Game Dead State
* Behavior:
*  - Waits for 10 seconds showing dead screen
*  - Then, it enables input:
*      - When user presses enter, respawns the robot and goes to game state again
*      - When user presses q, logout the game
*/
class DeadState : public State, public ManagerHub, public InputEventListener
{
public:
    DeadState(NetworkManager * networkManager, ImageManager * imageManager,
              InputManager * inputManager, MentalMap * mentalMap,
              RobotManager * robotManager, AudioManager * audioManager,
              ScreenManager * screenManager);
    virtual ~DeadState();
    virtual bool setup();
    virtual bool loop();
    virtual bool cleanup();

    //! @brief Returns the internal variable value as condition evaluation result
    virtual int evaluateConditions();

    //enum DeadStateOption {RESPAWN_SELECTED, EXIT_SELECTED};
    static const int RESPAWN_SELECTED;
    static const int EXIT_SELECTED;

    //-- InputEventListener interface:
    virtual bool onKeyDown(const Key & k);
    virtual bool onKeyUp(const Key & k);
    virtual bool onWindowEvent(const WindowEvent & event);

    static const int DEFAULT_RATE_MS;
    static const int MAX_HEALTH;

protected:
    DeadScreen screen;
    bool received_respawn;
    bool received_exit;
    int elapsed_time; //-- Time elapsed in ms
    int timer; //-- Countdown timer in s
};
}
#endif // __RD_DEAD_STATE_HPP__
<|endoftext|>