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; }
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); }