Beispiel #1
0
  bool circularEqual(const Point3dVector& points1, const Point3dVector& points2, double tol)
  {
    unsigned N = points1.size();
    if (N != points2.size()){
      return false;
    }

    if (N == 0){
      return true;
    }

    bool result = false;

    // look for a common starting point
    for (unsigned i = 0; i < N; ++i){
      if (getDistance(points1[0], points2[i]) <= tol){

        result = true;

        // check all other points
        for (unsigned j = 0; j < N; ++j){
          if (getDistance(points1[j], points2[(i + j) % N]) > tol){
            result = false;
            break;
          }
        }
      }

      if (result){
        return result;
      }
    }

    return result;
  }
Beispiel #2
0
  /// compute centroid from surface as Point3dVector
  OptionalPoint3d getCentroid(const Point3dVector& points)
  {
    OptionalPoint3d result;

    if (points.size() >= 3){
      // convert to face coordinates
      Transformation alignFace = Transformation::alignFace(points);
      Point3dVector surfacePoints = alignFace.inverse()*points;

      unsigned N = surfacePoints.size();
      double A = 0;
      double cx = 0;
      double cy = 0;
      for (unsigned i = 0; i < N; ++i){
        double x1, x2, y1, y2;
        if (i == N-1){
          x1 = surfacePoints[i].x();
          x2 = surfacePoints[0].x();
          y1 = surfacePoints[i].y();
          y2 = surfacePoints[0].y();
        }else{
          x1 = surfacePoints[i].x();
          x2 = surfacePoints[i+1].x();
          y1 = surfacePoints[i].y();
          y2 = surfacePoints[i+1].y();
        }

        double dA = (x1*y2-x2*y1);
        A += 0.5*dA;
        cx += (x1+x2)*dA;
        cy += (y1+y2)*dA;
      }

      if (A > 0){
        // centroid in face coordinates
        Point3d surfaceCentroid(cx/(6.0*A), cy/(6.0*A), 0.0);

        // centroid
        result = alignFace*surfaceCentroid;
      }
    }
    return result;
  }
TEST(Radiance, ForwardTranslator_SurfaceOnlyOnGround)
{
  Model model;
  Building building = model.getUniqueModelObject<Building>();

  Space space(model);

  Point3dVector vertices;
  vertices.push_back(Point3d(0,0,0));
  vertices.push_back(Point3d(1,0,0));
  vertices.push_back(Point3d(1,1,0));
  vertices.push_back(Point3d(0,1,0));
  Surface surface(vertices, model);

  surface.setSpace(space);

  Point3dVector polygon = ForwardTranslator::getPolygon(surface);
  EXPECT_EQ(vertices.size(), polygon.size());

  BOOST_FOREACH(const Point3d& vertex, polygon){
    LOG_FREE(::Info, "Radiance", vertex);
  }
TEST_F(ModelFixture, IlluminanceMap_SpaceSetTransformation)
{
  Model model;
  Space space(model);
  IlluminanceMap map(model);
  map.setXLength(2);
  map.setYLength(2);
  map.setNumberofXGridPoints(2);
  map.setNumberofYGridPoints(2);
  map.setOriginXCoordinate(1);
  map.setOriginYCoordinate(0);
  map.setOriginZCoordinate(2);
  map.setSpace(space);

  Point3dVector testPoints = map.referencePoints();
  ASSERT_EQ(4u, testPoints.size());
  EXPECT_DOUBLE_EQ(0, testPoints[0].x());
  EXPECT_DOUBLE_EQ(0, testPoints[0].y());
  EXPECT_DOUBLE_EQ(0, testPoints[0].z());
  EXPECT_DOUBLE_EQ(2, testPoints[3].x());
  EXPECT_DOUBLE_EQ(2, testPoints[3].y());
  EXPECT_DOUBLE_EQ(0, testPoints[3].z());

  testPoints = space.transformation()*map.transformation()*map.referencePoints();
  EXPECT_DOUBLE_EQ(1, testPoints[0].x());
  EXPECT_DOUBLE_EQ(0, testPoints[0].y());
  EXPECT_DOUBLE_EQ(2, testPoints[0].z());
  EXPECT_DOUBLE_EQ(3, testPoints[3].x());
  EXPECT_DOUBLE_EQ(2, testPoints[3].y());
  EXPECT_DOUBLE_EQ(2, testPoints[3].z());

  EXPECT_TRUE(space.setTransformation(Transformation::translation(Vector3d(1,0,0))));

  testPoints = space.transformation()*map.transformation()*map.referencePoints();
  EXPECT_DOUBLE_EQ(2, testPoints[0].x());
  EXPECT_DOUBLE_EQ(0, testPoints[0].y());
  EXPECT_DOUBLE_EQ(2, testPoints[0].z());
  EXPECT_DOUBLE_EQ(4, testPoints[3].x());
  EXPECT_DOUBLE_EQ(2, testPoints[3].y());
  EXPECT_DOUBLE_EQ(2, testPoints[3].z());

  EXPECT_TRUE(space.setTransformation(Transformation::translation(Vector3d(1,0,0))*Transformation::rotation(Vector3d(0,0,1),-openstudio::degToRad(90))));

  testPoints = space.transformation()*map.transformation()*map.referencePoints();
  EXPECT_DOUBLE_EQ(1, testPoints[0].x());
  EXPECT_DOUBLE_EQ(-1, testPoints[0].y());
  EXPECT_DOUBLE_EQ(2, testPoints[0].z());
  EXPECT_DOUBLE_EQ(3, testPoints[3].x());
  EXPECT_DOUBLE_EQ(-3, testPoints[3].y());
  EXPECT_DOUBLE_EQ(2, testPoints[3].z());
}
Beispiel #5
0
 // compute Newall vector from Point3dVector, direction is same as outward normal
 // magnitude is twice the area
 OptionalVector3d getNewallVector(const Point3dVector& points)
 {
   OptionalVector3d result;
   unsigned N = points.size();
   if (N >= 3){
     Vector3d vec;
     for (unsigned i = 1; i < N-1; ++i){
       Vector3d v1 = points[i] - points[0];
       Vector3d v2 = points[i+1] - points[0];
       vec += v1.cross(v2);
     }
    result = vec;
  }
  return result;
 }
Beispiel #6
0
  /// reorder points to upper-left-corner convention
  Point3dVector reorderULC(const Point3dVector& points)
  {
    unsigned N = points.size();
    if (N < 3){
      return Point3dVector();
    }

    // transformation to align face
    Transformation t = Transformation::alignFace(points);
    Point3dVector facePoints = t.inverse()*points;

    // find ulc index in face coordinates
    double maxY = std::numeric_limits<double>::min();
    double minX = std::numeric_limits<double>::max();
    unsigned ulcIndex = 0;
    for(unsigned i = 0; i < N; ++i){
      OS_ASSERT(std::abs(facePoints[i].z()) < 0.001);
      if ((maxY < facePoints[i].y()) || ((maxY < facePoints[i].y() + 0.00001) && (minX > facePoints[i].x()))){
        ulcIndex = i;
        maxY = facePoints[i].y();
        minX = facePoints[i].x();
      }
    }

    // no-op
    if (ulcIndex == 0){
      return points;
    }

    // create result
    Point3dVector result;
    std::copy (points.begin() + ulcIndex, points.end(), std::back_inserter(result));
    std::copy (points.begin(), points.begin() + ulcIndex, std::back_inserter(result));
    OS_ASSERT(result.size() == N);
    return result;
  }
Beispiel #7
0
  std::vector<Point3d> removeColinear(const Point3dVector& points, double tol)
  {
    unsigned N = points.size();
    if (N < 3){
      return points;
    }

    std::vector<Point3d> result;
    Point3d lastPoint = points[0];
    result.push_back(lastPoint);

    for (unsigned i = 1; i < N; ++i){
      Point3d currentPoint = points[i];
      Point3d nextPoint = points[0];
      if (i < N-1){
        nextPoint = points[i+1];
      }

      Vector3d a = (currentPoint - lastPoint);
      Vector3d b = (nextPoint - currentPoint);

      // if these fail to normalize we have zero length vectors (e.g. adjacent points)
      if (a.normalize()){
        if (b.normalize()){

          Vector3d c = a.cross(b);
          if (c.length() >= tol){
            // cross product is significant
            result.push_back(currentPoint);
            lastPoint = currentPoint;
          }else{
            // see if dot product is near -1
            double d = a.dot(b);
            if (d <= -1.0 + tol){
              // this is a line reversal
              result.push_back(currentPoint);
              lastPoint = currentPoint;
            }
          }
        }
      }
    }

    return result;
  }
Beispiel #8
0
  std::vector<std::vector<Point3d> > computeTriangulation(const Point3dVector& vertices, const std::vector<std::vector<Point3d> >& holes, double tol)
  {
    std::vector<std::vector<Point3d> > result;

    // check input
    if (vertices.size () < 3){
      return result;
    }

    boost::optional<Vector3d> normal = getOutwardNormal(vertices);
    if (!normal || normal->z() > -0.999){
      return result;
    }

    for (const auto& hole : holes){
      normal = getOutwardNormal(hole);
      if (!normal || normal->z() > -0.999){
        return result;
      }
    }

    std::vector<Point3d> allPoints;

    // PolyPartition does not support holes which intersect the polygon or share an edge
    // if any hole is not fully contained we will use boost to remove all the holes
    bool polyPartitionHoles = true;
    for (const std::vector<Point3d>& hole : holes){
      if (!within(hole, vertices, tol)){
        // PolyPartition can't handle this
        polyPartitionHoles = false;
        break;
      }
    }

    if (!polyPartitionHoles){
      // use boost to do all the intersections
      std::vector<std::vector<Point3d> > allFaces = subtract(vertices, holes, tol);
      std::vector<std::vector<Point3d> > noHoles;
      for (const std::vector<Point3d>& face : allFaces){
        std::vector<std::vector<Point3d> > temp = computeTriangulation(face, noHoles);
        result.insert(result.end(), temp.begin(), temp.end());
      }
      return result;
    }

    // convert input to vector of TPPLPoly
    std::list<TPPLPoly> polys;

    TPPLPoly outerPoly; // must be counter-clockwise, input vertices are clockwise
    outerPoly.Init(vertices.size());
    outerPoly.SetHole(false);
    unsigned n = vertices.size();
    for(unsigned i = 0; i < n; ++i){

      // should all have zero z coordinate now
      double z = vertices[n-i-1].z();
      if (abs(z) > tol){
        LOG_FREE(Error, "utilities.geometry.computeTriangulation", "All points must be on z = 0 plane for triangulation methods");
        return result;
      }

      Point3d point = getCombinedPoint(vertices[n-i-1], allPoints, tol);
      outerPoly[i].x = point.x();
      outerPoly[i].y = point.y();
    }
    outerPoly.SetOrientation(TPPL_CCW);
    polys.push_back(outerPoly);


    for (const std::vector<Point3d>& holeVertices : holes){

      if (holeVertices.size () < 3){
        LOG_FREE(Error, "utilities.geometry.computeTriangulation", "Hole has fewer than 3 points, ignoring");
        continue;
      }

      TPPLPoly innerPoly; // must be clockwise, input vertices are clockwise
      innerPoly.Init(holeVertices.size());
      innerPoly.SetHole(true);
      //std::cout << "inner :";
      for(unsigned i = 0; i < holeVertices.size(); ++i){

        // should all have zero z coordinate now
        double z = holeVertices[i].z();
        if (abs(z) > tol){
          LOG_FREE(Error, "utilities.geometry.computeTriangulation", "All points must be on z = 0 plane for triangulation methods");
          return result;
        }

        Point3d point = getCombinedPoint(holeVertices[i], allPoints, tol);
        innerPoly[i].x = point.x();
        innerPoly[i].y = point.y();
      }
      innerPoly.SetOrientation(TPPL_CW);
      polys.push_back(innerPoly);
    }

    // do partitioning
    TPPLPartition pp;
    std::list<TPPLPoly> resultPolys;
    int test = pp.Triangulate_EC(&polys,&resultPolys);
    if (test == 0){
      test = pp.Triangulate_MONO(&polys, &resultPolys);
    }
    if (test == 0){
      LOG_FREE(Error, "utilities.geometry.computeTriangulation", "Failed to partition polygon");
      return result;
    }

    // convert back to vertices
    std::list<TPPLPoly>::iterator it, itend;
    //std::cout << "Start" << std::endl;
    for(it = resultPolys.begin(), itend = resultPolys.end(); it != itend; ++it){

      it->SetOrientation(TPPL_CW);

      std::vector<Point3d> triangle;
      for (long i = 0; i < it->GetNumPoints(); ++i){
        TPPLPoint point = it->GetPoint(i);
        triangle.push_back(Point3d(point.x, point.y, 0));
      }
      //std::cout << triangle << std::endl;
      result.push_back(triangle);
    }
    //std::cout << "End" << std::endl;

    return result;
  }
TEST_F(ModelFixture, IlluminanceMap_Transformation)
{
  Model model;
  IlluminanceMap map(model);
  map.setXLength(2);
  map.setYLength(2);
  map.setNumberofXGridPoints(2);
  map.setNumberofYGridPoints(2);
  map.setOriginXCoordinate(1);
  map.setOriginYCoordinate(0);
  map.setOriginZCoordinate(2);

  Point3dVector testPoints = map.referencePoints();
  ASSERT_EQ(4u, testPoints.size());
  EXPECT_NEAR(0, testPoints[0].x(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].y(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].z(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].x(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].y(), 0.000001);
  EXPECT_NEAR(0, testPoints[3].z(), 0.000001);

  testPoints = map.transformation()*map.referencePoints();
  EXPECT_NEAR(1, testPoints[0].x(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].y(), 0.000001);
  EXPECT_NEAR(2, testPoints[0].z(), 0.000001);
  EXPECT_NEAR(3, testPoints[3].x(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].y(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].z(), 0.000001);

  Transformation transformation = Transformation::translation(Vector3d(1,0,2));
  EXPECT_TRUE(map.setTransformation(transformation));
  EXPECT_TRUE(transformation.matrix() == map.transformation().matrix());

  testPoints = map.referencePoints();
  ASSERT_EQ(4u, testPoints.size());
  EXPECT_NEAR(0, testPoints[0].x(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].y(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].z(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].x(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].y(), 0.000001);
  EXPECT_NEAR(0, testPoints[3].z(), 0.000001);

  testPoints = map.transformation()*map.referencePoints();
  EXPECT_NEAR(1, testPoints[0].x(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].y(), 0.000001);
  EXPECT_NEAR(2, testPoints[0].z(), 0.000001);
  EXPECT_NEAR(3, testPoints[3].x(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].y(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].z(), 0.000001);

  transformation = Transformation::translation(Vector3d(1,0,2))*Transformation::rotation(Vector3d(0,0,1),-openstudio::degToRad(90));
  EXPECT_TRUE(map.setTransformation(transformation));
  EXPECT_TRUE(transformation.matrix() == map.transformation().matrix()) << transformation.matrix() << std::endl << map.transformation().matrix();

  testPoints = map.referencePoints();
  ASSERT_EQ(4u, testPoints.size());
  EXPECT_NEAR(0, testPoints[0].x(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].y(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].z(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].x(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].y(), 0.000001);
  EXPECT_NEAR(0, testPoints[3].z(), 0.000001);

  testPoints = map.transformation()*map.referencePoints();
  EXPECT_NEAR(1, testPoints[0].x(), 0.000001);
  EXPECT_NEAR(0, testPoints[0].y(), 0.000001);
  EXPECT_NEAR(2, testPoints[0].z(), 0.000001);
  EXPECT_NEAR(3, testPoints[3].x(), 0.000001);
  EXPECT_NEAR(-2, testPoints[3].y(), 0.000001);
  EXPECT_NEAR(2, testPoints[3].z(), 0.000001);

}