public void testGetValue() {
    Dimension n;

    n = new Dimension(35, false);
    assertEquals(35, n.getValue(100));
    assertEquals(35, n.getValue(1000));

    n = new Dimension(35, true);
    assertEquals(35, n.getValue(100));
    assertEquals(350, n.getValue(1000));

    n = new Dimension(35, 1);
    assertEquals(35, n.getValue(100));
    assertEquals(350, n.getValue(1000));

    n = new Dimension(35, 10);
    assertEquals(3, n.getValue(100));
    assertEquals(35, n.getValue(1000));
  }
 private Dimensions validateDimensions(Dimensions dimensions, String name)
     throws CloudWatchException {
   Collection<Dimension> dimensionsCollection = null;
   if (dimensions != null) {
     dimensionsCollection = dimensions.getMember();
   }
   if (dimensions == null) {
     return dimensions;
   }
   if (dimensionsCollection.size() > 10) {
     throw new InvalidParameterValueException(
         "The collection " + name + " must not have a size greater than 10.");
   }
   int ctr = 1;
   for (Dimension dimension : dimensionsCollection) {
     validateStringLength(dimension.getName(), name + ".member." + (ctr) + ".Name", 1, 255, true);
     validateStringLength(
         dimension.getValue(), name + ".member." + (ctr) + ".Value", 1, 255, true);
     ctr++;
   }
   return dimensions;
 }
Example #3
0
  private static KDNode buildTreeSAH(
      TriangleRef[] refs, BoundingRectangle bounds, int depth, double lastCost) {
    double minCost = Double.MAX_VALUE;
    SplittingPlane minPlane = null;
    SplittingPlaneAffiliation minPlaneAffiliation = null;
    int minnleft = Integer.MAX_VALUE;
    int minnright = Integer.MAX_VALUE;

    List<TriangleEvent> events = new ArrayList<>(refs.length * 2);

    for (Dimension d : Dimension.values()) {
      for (TriangleRef ref : refs) {
        BoundingRectangle br = bounds.intersect(ref.bounds);
        if (d.getValue(br.min) == d.getValue(br.max)) {
          // The triangle is planar after clipping it to the current Voxel
          events.add(
              new TriangleEvent(
                  ref.triangle, new SplittingPlane(d.getValue(br.min), d), EventType.PLANAR));
        } else {
          events.add(
              new TriangleEvent(
                  ref.triangle, new SplittingPlane(d.getValue(br.min), d), EventType.START));
          events.add(
              new TriangleEvent(
                  ref.triangle, new SplittingPlane(d.getValue(br.max), d), EventType.END));
        }
      }

      events.sort(
          (a, b) -> {
            int i1 = (int) Math.signum(a.p.splitValue - b.p.splitValue);
            int i2 = (int) Math.signum(a.type.ord - b.type.ord);
            return i1 != 0 ? i1 : i2;
          }); // As per the order in the paper: Sort by splitValue, then by EventType: END < PLANAR
              // < START

      // Now we sweep over the event list and find the minimum cost splitting plane for this
      // dimension.
      int nleft = 0;
      int nright = refs.length;

      for (int i = 0; i < events.size(); ) {
        TriangleEvent evt = events.get(i);
        int pend = 0;
        int pplanar = 0;
        int pstart = 0;
        final SplittingPlane p = evt.p;

        // aggregate all p* for the same splitValue
        while (evt.p.splitValue == p.splitValue) {
          switch (evt.type) {
            case END:
              pend++;
              break;
            case PLANAR:
              pplanar++;
              break;
            case START:
              pstart++;
              break;
          }

          if (++i < events.size()) {
            evt = events.get(i);
          } else {
            break;
          }
        }

        // Now we got all p* values for the current splitValue.
        // Move plane *onto* p.
        nright -= pplanar;
        nright -= pend;

        Tuple2<Double, SplittingPlaneAffiliation> result =
            surfaceAreaHeuristic(bounds, p, nleft, nright, pplanar);
        if (result.v1 < minCost) {
          minCost = result.v1;
          minPlane = p;
          minPlaneAffiliation = result.v2;
          minnleft = nleft;
          minnright = nright;
          switch (minPlaneAffiliation) {
            case LEFT:
              minnleft += pplanar;
              break;
            case RIGHT:
              minnright += pplanar;
              break;
          }
        }

        // Move plane *beyond* p
        nleft += pstart;
        nleft += pplanar;

        assert nleft + nright >= refs.length;
        assert minnleft + minnright >= refs.length;
      }

      events.clear();
    }

    if (INTERSECTION_COST * refs.length < minCost || depth > 30 || lastCost <= minCost) {
      return KDNode.leaf(bounds, refs);
    }

    assert refs.length > 1;

    // We found the best splitting plane and the associated costs, all that is left to do is split.
    TriangleRef[] left = new TriangleRef[minnleft];
    TriangleRef[] right = new TriangleRef[minnright];
    int l = 0;
    int r = 0;
    BoundingRectangle lv = BoundingRectangle.EMPTY;
    BoundingRectangle rv = BoundingRectangle.EMPTY;
    for (TriangleRef ref : refs) {
      if (minPlane.dimension.getValue(ref.bounds.min) == minPlane.splitValue
          && minPlane.dimension.getValue(ref.bounds.max) == minPlane.splitValue) {
        if (minPlaneAffiliation == SplittingPlaneAffiliation.RIGHT) {
          right[r++] = ref;
          rv = rv.merge(ref.bounds);
        } else {
          left[l++] = ref;
          lv = lv.merge(ref.bounds);
        }
      } else {
        if (minPlane.dimension.getValue(ref.bounds.min) < minPlane.splitValue) {
          left[l++] = ref;
          lv = lv.merge(ref.bounds);
        }
        if (minPlane.dimension.getValue(ref.bounds.max) > minPlane.splitValue) {
          right[r++] = ref;
          rv = rv.merge(ref.bounds);
        }
        // In the remaining case where min == max == splitValue, the triangle
        // is planar (extent == 0) and will we dealt with in the other if branch
        // according to minPlaneAffiliation.
      }
    }

    lv =
        splitBoundingRect(lv.intersect(bounds), minPlane)
            .v1; // I hope this is accurate enough. don't want clip all triangles
    rv = splitBoundingRect(rv.intersect(bounds), minPlane).v2;

    assert l == left.length;
    assert r == right.length;

    KDNode leftChild = buildTreeSAH(left, lv, depth + 1, minCost);
    KDNode rightChild = buildTreeSAH(right, rv, depth + 1, minCost);

    return KDNode.inner(bounds, leftChild, rightChild, minPlane);
  }