public void updateSpringPosition() { if (mPrev != null && mSimulate) { mWorldPosition.set(mPrev.mWorldEndPosition); mWorldRotation.set(mRotation.getQuaternion()); mWorldRotation.multiply(mPrev.mWorldRotation); MathUtil.setVectorToSumOf( mWorldEndPosition, mPrev.mWorldEndPosition, MathUtil.setVectorToProductOf(mTempVec1, mWorldRotation, mDirection)); mWorldSpringRotation.set(mOriginalRotation); mWorldSpringRotation.multiply(mPrev.mWorldRotation); /* Method using only existing ngin3d (requires allocations/garbage) * mWorldSpringPosition.set(mPrev.mWorldEndPosition); * mWorldSpringPosition = mWorldSpringPosition.add(mWorldSpringRotation.applyTo(mDirection)); * */ // Method using new functions. MathUtil.setVectorToSumOf( mWorldSpringPosition, mPrev.mWorldEndPosition, MathUtil.setVectorToProductOf(mTempVec1, mWorldSpringRotation, mDirection)); } }
/** * Change the parent of a game object. * * <p>TODO: add code so that the object does not change its global position, rotation or scale * when it is reparented. * * @param newParent */ public void setParent(GameObject newParent) { GameObject oldParent = this.myParent; double oldLocalRotation = this.getRotation(); double newLocalRotation = MathUtil.normaliseAngle( oldParent.getGlobalRotation() - newParent.getGlobalRotation() + oldLocalRotation); double oldLocalScale = this.getScale(); double newLocalScale = oldParent.getGlobalScale() * oldLocalScale / newParent.getGlobalScale(); double[] globalPosition = this.getGlobalPosition(); double[] globalPositionPoint = new double[3]; globalPositionPoint[0] = globalPosition[0]; globalPositionPoint[1] = globalPosition[1]; globalPositionPoint[2] = 1; double[] newLocalPositionPoint = MathUtil.multiply(newParent.getInverseGlobalMatrix(), globalPositionPoint); double[] newLocalPosition = new double[2]; newLocalPosition[0] = newLocalPositionPoint[0]; newLocalPosition[1] = newLocalPositionPoint[1]; myParent.myChildren.remove(this); myParent = newParent; myParent.myChildren.add(this); this.myTranslation = newLocalPosition; this.myRotation = newLocalRotation; this.myScale = newLocalScale; }
public void projectBy(ProjectionParameters projectionParameters) { this.setWeeklyRent( MathUtil.increaseBy(this.getWeeklyRent(), projectionParameters.getRentIncreaseRate())); this.setMarketValue( MathUtil.increaseBy(this.getMarketValue(), projectionParameters.getCapitalGrowthRate())); this.ongoingCosts.projectBy(projectionParameters.getCpi()); for (Owner owner : getOwnerList()) { owner.setAnnualIncome( MathUtil.increaseBy( owner.getAnnualIncome(), projectionParameters.getSalaryIncreaseRate())); } }
@Test public void testCubicRealRoots() { assertCollection(AlgebraUtil.cubicRealRoots(0, 0, 0), 0, 0, 0); assertCollection(AlgebraUtil.cubicRealRoots(0, 0, 1), -1); assertCollection( AlgebraUtil.cubicRealRoots(0, 0, -1000000000000000000000000000000000.0), 100000000000.0); assertCollection(AlgebraUtil.cubicRealRoots(-3, 3, -1), 1, 1, 1); assertCollection(AlgebraUtil.cubicRealRoots(1, -1, -1), 1, -1, -1); assertCollection(MathUtil.simpleRound(10, AlgebraUtil.cubicRealRoots(-14, 56, -64)), 2, 4, 8); assertCollection( MathUtil.simpleRound(10, AlgebraUtil.cubicRealRoots(-0.875, 0.21875, -0.015625)), 0.5, 0.25, 0.125); }
public static Map<String, String> getEntityPropertiesToStringMap( Object entity, Map<String, String> fieldClassMapping, String... entityIdentifier) { Map<String, String> propertiesMap = new HashMap<String, String>(); StringBuffer sb = new StringBuffer(); if (entityIdentifier.length > 0) { for (String ei : entityIdentifier) { sb.append(ei + "."); } } String prefixStr = sb.toString(); PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(entity.getClass()); for (PropertyDescriptor pd : pds) { Method readMethod = pd.getReadMethod(); if (null == readMethod) continue; Class<?> returnType = readMethod.getReturnType(); Object returnValue = null; try { returnValue = readMethod.invoke(entity); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } if (null != returnValue) { String value = ""; if (returnType.isAssignableFrom(Set.class)) { continue; } else if (isTenwaEntity(returnType)) { String fieldName = null; if (null != fieldClassMapping) { fieldName = fieldClassMapping.get(returnType.getSimpleName()); } if (StringUtils.isBlank(fieldName)) { fieldName = "id"; } Method method = BeanUtils.getPropertyDescriptor(returnType, fieldName).getReadMethod(); // System.out.println("####:"+method.getName()+","+returnValue); try { value = StringUtil.nullToString(method.invoke(returnValue)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } else { if (returnType.getSimpleName().equalsIgnoreCase("double")) { value = MathUtil.decimal((Double) returnValue, 8); } else { value = returnValue.toString(); } } propertiesMap.put(prefixStr + pd.getName().toLowerCase(), value); } } return propertiesMap; }
/** * http://ogre.sourcearchive.com/documentation/1.4.5/classOgre_1_1Vector3_eeef4472ad0c4d5f34a038a9f2faa819.html#eeef4472ad0c4d5f34a038a9f2faa819 * * @param direction * @return */ public Quaternion getRotationTo(Number3D direction) { // Based on Stan Melax's article in Game Programming Gems Quaternion q = new Quaternion(); // Copy, since cannot modify local Number3D v0 = this; Number3D v1 = direction; v0.normalize(); v1.normalize(); float d = Number3D.dot(v0, v1); // If dot == 1, vectors are the same if (d >= 1.0f) { q.setIdentity(); } if (d < 0.000001f - 1.0f) { // Generate an axis Number3D axis = Number3D.cross(Number3D.getAxisVector(Axis.X), this); if (axis.length() == 0) // pick another if colinear axis = Number3D.cross(Number3D.getAxisVector(Axis.Y), this); axis.normalize(); q.fromAngleAxis(MathUtil.radiansToDegrees(MathUtil.PI), axis); } else { float s = FloatMath.sqrt((1 + d) * 2); float invs = 1f / s; Number3D c = Number3D.cross(v0, v1); q.x = c.x * invs; q.y = c.y * invs; q.z = c.z * invs; q.w = s * 0.5f; q.normalize(); } return q; }
@Override public boolean compare(Number actual, Number expected) { checkTolerance(tolerance); double actualDouble = checkNotNull(actual).doubleValue(); double expectedDouble = checkNotNull(expected).doubleValue(); return MathUtil.equalWithinTolerance(actualDouble, expectedDouble, tolerance); }
public void updateNodeRotation() { if (mPrev != null && mSimulate) { Quaternion qRot = mRotation.getQuaternion(); mTempQuat.set( mPrev.mWorldRotation.getQ0(), -mPrev.mWorldRotation.getQ1(), -mPrev.mWorldRotation.getQ2(), -mPrev.mWorldRotation.getQ3()); qRot.set(mWorldRotation); qRot.multiply(mTempQuat); qRot.nor(); /* After pointing, the rotation will have an arbitrary "roll" around * the "to" z-axis. We must find the new position of the "up" vector * after rotation. */ // Vec3 dir = qRot.applyTo(BONE_DIR); // Vec3 rolledUp = qRot.applyTo(BONE_ORTH); MathUtil.setVectorToProductOf(mTempVec1, qRot, BONE_DIR); MathUtil.setVectorToProductOf(mTempVec2, qRot, BONE_ORTH); /* We now project this vector and the original "up" vector onto a plane * perpendicular to the "to" vector so that we can find the extra * rotation needed to rotate the rolled "up" vector onto the given * "up" vector. Note that these vectors won't have unit length. */ // Vec3 upProjected = mOrthogonalTarget.subtract(Vec3.dotProduct(mTempVec1, // mOrthogonalTarget), mTempVec1); float dot = Vec3.dotProduct(mTempVec1, mOrthogonalTarget); mTempVec3.set(dot * mTempVec1.x, dot * mTempVec1.y, dot * mTempVec1.z); MathUtil.setVectorToDifferenceOf(mTempVec4, mOrthogonalTarget, mTempVec3); /* Calculate the rotation bring rolledUpProjected onto upProjected. * Note that this rotation will be around the "to" vector (because both * vectors are parallel to the "to" vector after projection). */ // Rotation rollRotation = Rotation.fromTo(mTempVec2, upProjected); // qRot.multiply(rollRotation.getQuaternion()); MathUtil.setQuaternionFromTo(mTempQuat, mTempVec2, mTempVec4); qRot.multiply(mTempQuat); mTempRot.getQuaternion().set(qRot); mTempRot.getQuaternion().multiply(mPhysics.mFold); mActorNode.setRotation(mTempRot); } }
/** * Compute the object's rotation in the global coordinate frame * * <p>TODO: Write this method * * @return the global rotation of the object (in degrees) */ public double getGlobalRotation() { double rotation; if (myParent == null) { rotation = myRotation; } else { rotation = MathUtil.normaliseAngle(myParent.getGlobalRotation() + myRotation); } return rotation; }
public static Number variance(Collection<? extends Number> col) { double mean = mean(col).doubleValue(); double accumSum = 0; for (Number n : col) { accumSum += MathUtil.sq(n.doubleValue() - mean); } accumSum /= col.size(); return accumSum; }
public void updateNodePosition() { if (mPrev != null && mSimulate) { // Vec3 oldPos = new Vec3(mWorldEndPosition); mTempVec1.set(mWorldEndPosition); float damping = mPhysics.mDamping * mGlobalPhysics.mExtraDamping; float springStrength = mPhysics.mSpringStrength; for (int i = 0; i != 4; ++i) { mVelocity.x += mGlobalPhysics.mGravity.x; mVelocity.y += mGlobalPhysics.mGravity.y; mVelocity.z += mGlobalPhysics.mGravity.z; float strength = springStrength * ((1f / mRootiness) + 0.5f); mVelocity.x += (mWorldSpringPosition.x - mWorldEndPosition.x) * strength; mVelocity.y += (mWorldSpringPosition.y - mWorldEndPosition.y) * strength; mVelocity.z += (mWorldSpringPosition.z - mWorldEndPosition.z) * strength; mVelocity.x *= damping; mVelocity.y *= damping; mVelocity.z *= damping; mWorldEndPosition.x += 0.01f * mVelocity.x; mWorldEndPosition.y += 0.01f * mVelocity.y; mWorldEndPosition.z += 0.01f * mVelocity.z; if (mWorldEndPosition.z < -0.2f) { mWorldEndPosition.z = -0.2f; mVelocity.z = 0f; } } // Vec3 from = oldPos.subtract(mPrev.mWorldEndPosition); // Vec3 to = mWorldEndPosition.subtract(mPrev.mWorldEndPosition); // mWorldRotation.multiply(Rotation.fromTo(from, to).getQuaternion()); // from = old_world_position - parent_end MathUtil.setVectorToDifferenceOf(mTempVec2, mTempVec1, mPrev.mWorldEndPosition); // to = new_world_position - parent_end MathUtil.setVectorToDifferenceOf(mTempVec3, mWorldEndPosition, mPrev.mWorldEndPosition); mWorldRotation.multiply(MathUtil.setQuaternionFromTo(mTempQuat, mTempVec2, mTempVec3)); } }
public static <T> T getRandomElement(final Set<T> collection) { if (collection == null || collection.size() == 0) { return null; } final int elemIndex = MathUtil.randomInteger(collection.size()); int i = -1; for (final T elem : collection) { if (++i == elemIndex) { return elem; } } return collection.iterator().next(); }
// incorporates exponential model of probability of motion, weight less likely motions less private double[] constructW(double[] Uxyzrpy) { assert (Uxyzrpy.length == Vxyzrpy.length) : "Warning expected 6 velocity"; double[] W = new double[6]; // weighting matrix for (int i = 0; i < Uxyzrpy.length; i++) { double u = Uxyzrpy[i]; double v = Vxyzrpy[i]; double Dv = Math.abs(u - v); if (i <= 2) { // handle velocities close to 0 if ((Math.abs(u) <= LV_THRESH) && (Math.abs(v) <= LV_THRESH)) { // use exponential model to come up with weights W[i] = MathUtil.exp(-ALPHA * Dv); } // if our change in velocity was within acceptable bounds else if ((Dv / u) <= DELTAV_THRESH) { // use exponential model to come up with weights W[i] = MathUtil.exp(-ALPHA * Dv); } else { W[i] = 0; // throw out bad changes } } else { // handle angular velocities close to 0 if ((Math.abs(u) <= LR_THRESH) && (Math.abs(v) <= LR_THRESH)) { // use exponential model to come up with weights W[i] = MathUtil.exp(-BETA * Dv); } // if our change in velocity was within acceptable bounds else if ((Dv / u) <= DELTAR_THRESH) { // use exponential model to come up with weights W[i] = MathUtil.exp(-BETA * Dv); } else { W[i] = 0; // throw out bad changes } } } return W; }
/** * Compute the object's position in world coordinates * * <p>TODO: Write this method * * @return a point in world coordinats in [x,y] form */ public double[] getGlobalPosition() { double[] globalPosition = new double[2]; if (myParent == null) { globalPosition[0] = myTranslation[0]; globalPosition[1] = myTranslation[1]; } else { double[][] parentsGlobalMatrix = myParent.getGlobalMatrix(); double[] positionPoint = new double[3]; positionPoint[0] = myTranslation[0]; positionPoint[1] = myTranslation[1]; positionPoint[2] = 1; double[] globalPositionPoint = MathUtil.multiply(parentsGlobalMatrix, positionPoint); globalPosition[0] = globalPositionPoint[0]; globalPosition[1] = globalPositionPoint[1]; } return globalPosition; }
public double[][] getGlobalMatrix() { double[] myGlobalPosition = this.getGlobalPosition(); double[][] myGlobalTranslationMatrix = MathUtil.translationMatrix(myGlobalPosition); double myGlobalRotation = this.getGlobalRotation(); double[][] myGlobalRotationMatrix = MathUtil.rotationMatrix(myGlobalRotation); double myGlobalScale = this.getGlobalScale(); double[][] myGlobalScaleMatrix = MathUtil.scaleMatrix(myGlobalScale); double[][] m = MathUtil.getIdentity(); m = MathUtil.multiply(m, myGlobalTranslationMatrix); m = MathUtil.multiply(m, myGlobalRotationMatrix); m = MathUtil.multiply(m, myGlobalScaleMatrix); return m; }
public double[][] getInverseGlobalMatrix() { double[] globalPosition = this.getGlobalPosition(); double[] inverseTranslation = new double[2]; inverseTranslation[0] = -globalPosition[0]; inverseTranslation[1] = -globalPosition[1]; double[][] myInverseGlobalTranslationMatrix = MathUtil.translationMatrix(inverseTranslation); double myInverseRotation = -this.getGlobalRotation(); double[][] myInverseGlobalRotationMatrix = MathUtil.rotationMatrix(myInverseRotation); double myInverseScale = 1d / this.getGlobalScale(); double[][] myInverseGlobalScaleMatrix = MathUtil.scaleMatrix(myInverseScale); double[][] m = MathUtil.getIdentity(); m = MathUtil.multiply(m, myInverseGlobalScaleMatrix); m = MathUtil.multiply(m, myInverseGlobalRotationMatrix); m = MathUtil.multiply(m, myInverseGlobalTranslationMatrix); return m; }
/** * Initialises subbands fields, such as number of code-blocks and code-blocks dimension, in the * subband tree. The nominal code-block width/height depends on the precincts dimensions if used. * * @param t The tile index of the subband * @param c The component index * @param sb The subband tree to be initialised. */ private void initSubbandsFields(int t, int c, Subband sb) { int cbw = cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t, c); int cbh = cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t, c); if (!sb.isNode) { // Code-blocks dimension int ppx, ppy; int ppxExp, ppyExp, cbwExp, cbhExp; ppx = pss.getPPX(t, c, sb.resLvl); ppy = pss.getPPY(t, c, sb.resLvl); if (ppx != Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != Markers.PRECINCT_PARTITION_DEF_SIZE) { ppxExp = MathUtil.log2(ppx); ppyExp = MathUtil.log2(ppy); cbwExp = MathUtil.log2(cbw); cbhExp = MathUtil.log2(cbh); // Precinct partition is used switch (sb.resLvl) { case 0: sb.nomCBlkW = (cbwExp < ppxExp ? (1 << cbwExp) : (1 << ppxExp)); sb.nomCBlkH = (cbhExp < ppyExp ? (1 << cbhExp) : (1 << ppyExp)); break; default: sb.nomCBlkW = (cbwExp < ppxExp - 1 ? (1 << cbwExp) : (1 << (ppxExp - 1))); sb.nomCBlkH = (cbhExp < ppyExp - 1 ? (1 << cbhExp) : (1 << (ppyExp - 1))); break; } } else { sb.nomCBlkW = cbw; sb.nomCBlkH = cbh; } // Number of code-blocks if (sb.numCb == null) sb.numCb = new Point(); if (sb.w != 0 && sb.h != 0) { int acb0x = cb0x; int acb0y = cb0y; int tmp; // Project code-block partition origin to subband. Since the // origin is always 0 or 1, it projects to the low-pass side // (throught the ceil operator) as itself (i.e. no change) and // to the high-pass side (through the floor operator) as 0, // always. switch (sb.sbandIdx) { case Subband.WT_ORIENT_LL: // No need to project since all low-pass => nothing to do break; case Subband.WT_ORIENT_HL: acb0x = 0; break; case Subband.WT_ORIENT_LH: acb0y = 0; break; case Subband.WT_ORIENT_HH: acb0x = 0; acb0y = 0; break; default: throw new Error("Internal JJ2000 error"); } if (sb.ulcx - acb0x < 0 || sb.ulcy - acb0y < 0) { throw new IllegalArgumentException( "Invalid code-blocks " + "partition origin or " + "image offset in the " + "reference grid."); } // NOTE: when calculating "floor()" by integer division the // dividend and divisor must be positive, we ensure that by // adding the divisor to the dividend and then substracting 1 // to the result of the division tmp = sb.ulcx - acb0x + sb.nomCBlkW; sb.numCb.x = (tmp + sb.w - 1) / sb.nomCBlkW - (tmp / sb.nomCBlkW - 1); tmp = sb.ulcy - acb0y + sb.nomCBlkH; sb.numCb.y = (tmp + sb.h - 1) / sb.nomCBlkH - (tmp / sb.nomCBlkH - 1); } else { sb.numCb.x = sb.numCb.y = 0; } } else { initSubbandsFields(t, c, sb.getLL()); initSubbandsFields(t, c, sb.getHL()); initSubbandsFields(t, c, sb.getLH()); initSubbandsFields(t, c, sb.getHH()); } }
public static <T> T getRandomElement(final T[] collection) { if (collection == null || collection.length == 0) { return null; } return collection[MathUtil.randomInteger(collection.length)]; }
public static <T> T getRandomElement(final List<T> collection) { if (collection == null || collection.size() == 0) { return null; } return collection.get(MathUtil.randomInteger(collection.size())); }
public static boolean isLoaded(final org.bukkit.World world, double x, double y, double z) { return isLoaded(world, MathUtil.locToChunk(x), MathUtil.locToChunk(z)); }
public static void loadChunks( org.bukkit.World world, double xmid, double zmid, final int radius) { loadChunks(world, MathUtil.locToChunk(xmid), MathUtil.locToChunk(zmid), radius); }
/** * 1=30度 2=45度 4=60度 * * @return */ public static float switchDegrees(float x, float y) { return (float) MathUtil.pointTotoDegrees(x, y); }
/** * Evaluate the logit probability of {@link #sumOfProducts(Map)} of values. Probability = * exp(logit)/(1+exp(logit)) where logit = sumOfProducts(values) + gamma. * * @param values set of values with same names as this model. These values are multiplied with the * model's effect estimates (coefficients). * @param gamma gamma to add to the sum of products * @return logit probability */ public double evaluateLogitProb(Map<String, ? extends Number> values, double gamma) { double logit = sumOfProducts(values) + gamma; double prob = MathUtil.probFromLogit(logit); return prob; }
/** * Get the local rotation (in degrees) * * @return */ public double getRotation() { return MathUtil.normaliseAngle(myRotation); }
/** * Encodes a packet and returns the buffer containing the encoded packet header. The code-blocks * appear in a 3D array of CBlkRateDistStats, 'cbs'. The first index is the tile index in * lexicographical order, the second index is the subband index (as defined in the Subband class), * and the third index is the code-block index (whithin the subband tile) in lexicographical order * as well. The indexes of the new truncation points for each code-block are specified by the 3D * array of int 'tIndx'. The indices of this array are the same as for cbs. The truncation point * indices in 'tIndx' are the indices of the elements of the 'truncIdxs' array, of the * CBlkRateDistStats class, that give the real truncation points. If a truncation point index is * negative it means that the code-block has not been included in any layer yet. If the truncation * point is less than or equal to the highest truncation point used in previous layers then the * code-block is not included in the packet. Otherwise, if larger, the code-block is included in * the packet. The body of the packet can be obtained with the getLastBodyBuf() and * getLastBodyLen() methods. * * <p>Layers must be coded in increasing order, in consecutive manner, for each tile, component * and resolution level (e.g., layer 1, then layer 2, etc.). For different tile, component and/or * resolution level no particular order must be followed. * * @param ly The layer index (starts at 1). * @param c The component index. * @param r The resolution level * @param t Index of the current tile * @param cbs The 3D array of coded code-blocks. * @param tIndx The truncation point indices for each code-block. * @param hbuf The header buffer. If null a new BitOutputBuffer is created and returned. This * buffer is reset before anything is written to it. * @param bbuf The body buffer. If null a new one is created. If not large enough a new one is * created. * @param pIdx The precinct index. * @return The buffer containing the packet header. */ public BitOutputBuffer encodePacket( int ly, int c, int r, int t, CBlkRateDistStats cbs[][], int tIndx[][], BitOutputBuffer hbuf, byte bbuf[], int pIdx) { int b, i, maxi; int ncb; int thmax; int newtp; int cblen; int prednbits, nbits, deltabits; TagTreeEncoder cur_ttIncl, cur_ttMaxBP; // inclusion and bit-depth tag // trees int cur_prevtIdxs[]; // last encoded truncation points CBlkRateDistStats cur_cbs[]; int cur_tIndx[]; // truncation points to encode int minsb = (r == 0) ? 0 : 1; int maxsb = (r == 0) ? 1 : 4; Point cbCoord = null; SubbandAn root = infoSrc.getAnSubbandTree(t, c); SubbandAn sb; roiInPkt = false; roiLen = 0; int mend, nend; // Checks if a precinct with such an index exists in this resolution // level if (pIdx >= ppinfo[t][c][r].length) { packetWritable = false; return hbuf; } PrecInfo prec = ppinfo[t][c][r][pIdx]; // First, we check if packet is empty (i.e precinct 'pIdx' has no // code-block in any of the subbands) boolean isPrecVoid = true; for (int s = minsb; s < maxsb; s++) { if (prec.nblk[s] == 0) { // The precinct has no code-block in this subband. continue; } else { // The precinct is not empty in at least one subband -> // stop isPrecVoid = false; break; } } if (isPrecVoid) { packetWritable = true; if (hbuf == null) { hbuf = new BitOutputBuffer(); } else { hbuf.reset(); } if (bbuf == null) { lbbuf = bbuf = new byte[1]; } hbuf.writeBit(0); lblen = 0; return hbuf; } if (hbuf == null) { hbuf = new BitOutputBuffer(); } else { hbuf.reset(); } // Invalidate last body buffer lbbuf = null; lblen = 0; // Signal that packet is present hbuf.writeBit(1); for (int s = minsb; s < maxsb; s++) { // Loop on subbands sb = (SubbandAn) root.getSubbandByIdx(r, s); // Go directly to next subband if the precinct has no code-block // in the current one. if (prec.nblk[s] == 0) { continue; } cur_ttIncl = ttIncl[t][c][r][pIdx][s]; cur_ttMaxBP = ttMaxBP[t][c][r][pIdx][s]; cur_prevtIdxs = prevtIdxs[t][c][r][s]; cur_cbs = cbs[s]; cur_tIndx = tIndx[s]; // Set tag tree values for code-blocks in this precinct mend = (prec.cblk[s] == null) ? 0 : prec.cblk[s].length; for (int m = 0; m < mend; m++) { nend = (prec.cblk[s][m] == null) ? 0 : prec.cblk[s][m].length; for (int n = 0; n < nend; n++) { cbCoord = prec.cblk[s][m][n].idx; b = cbCoord.x + cbCoord.y * sb.numCb.x; if (cur_tIndx[b] > cur_prevtIdxs[b] && cur_prevtIdxs[b] < 0) { // First inclusion cur_ttIncl.setValue(m, n, ly - 1); } if (ly == 1) { // First layer, need to set the skip of MSBP cur_ttMaxBP.setValue(m, n, cur_cbs[b].skipMSBP); } } } // Now encode the information for (int m = 0; m < prec.cblk[s].length; m++) { // Vertical code-blocks for (int n = 0; n < prec.cblk[s][m].length; n++) { // Horiz. cblks cbCoord = prec.cblk[s][m][n].idx; b = cbCoord.x + cbCoord.y * sb.numCb.x; // 1) Inclusion information if (cur_tIndx[b] > cur_prevtIdxs[b]) { // Code-block included in this layer if (cur_prevtIdxs[b] < 0) { // First inclusion // Encode layer info cur_ttIncl.encode(m, n, ly, hbuf); // 2) Max bitdepth info. Encode value thmax = cur_cbs[b].skipMSBP + 1; for (i = 1; i <= thmax; i++) { cur_ttMaxBP.encode(m, n, i, hbuf); } // Count body size for packet lblen += cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]; } else { // Already in previous layer // Send "1" bit hbuf.writeBit(1); // Count body size for packet lblen += cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]] - cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]]; } // 3) Truncation point information if (cur_prevtIdxs[b] < 0) { newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]]; } else { newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]] - cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] - 1; } // Mix of switch and if is faster switch (newtp) { case 0: hbuf.writeBit(0); // Send one "0" bit break; case 1: hbuf.writeBits(2, 2); // Send one "1" and one "0" break; case 2: case 3: case 4: // Send two "1" bits followed by 2 bits // representation of newtp-2 hbuf.writeBits((3 << 2) | (newtp - 2), 4); break; default: if (newtp <= 35) { // Send four "1" bits followed by a five bits // representation of newtp-5 hbuf.writeBits((15 << 5) | (newtp - 5), 9); } else if (newtp <= 163) { // Send nine "1" bits followed by a seven bits // representation of newtp-36 hbuf.writeBits((511 << 7) | (newtp - 36), 16); } else { throw new ArithmeticException( "Maximum number " + "of truncation " + "points exceeded"); } } } else { // Block not included in this layer if (cur_prevtIdxs[b] >= 0) { // Already in previous layer. Send "0" bit hbuf.writeBit(0); } else { // Not in any previous layers cur_ttIncl.encode(m, n, ly, hbuf); } // Go to the next one. continue; } // Code-block length // We need to compute the maximum number of bits needed to // signal the length of each terminated segment and the // final truncation point. newtp = 1; maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]]; cblen = (cur_prevtIdxs[b] < 0) ? 0 : cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]]; // Loop on truncation points i = (cur_prevtIdxs[b] < 0) ? 0 : cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] + 1; int minbits = 0; for (; i < maxi; i++, newtp++) { // If terminated truncation point calculate length if (cur_cbs[b].isTermPass != null && cur_cbs[b].isTermPass[i]) { // Calculate length cblen = cur_cbs[b].truncRates[i] - cblen; // Calculate number of needed bits prednbits = lblock[t][c][r][s][b] + MathUtil.log2(newtp); minbits = ((cblen > 0) ? MathUtil.log2(cblen) : 0) + 1; // Update Lblock increment if needed for (int j = prednbits; j < minbits; j++) { lblock[t][c][r][s][b]++; hbuf.writeBit(1); } // Initialize for next length newtp = 0; cblen = cur_cbs[b].truncRates[i]; } } // Last truncation point length always sent // Calculate length cblen = cur_cbs[b].truncRates[i] - cblen; // Calculate number of bits prednbits = lblock[t][c][r][s][b] + MathUtil.log2(newtp); minbits = ((cblen > 0) ? MathUtil.log2(cblen) : 0) + 1; // Update Lblock increment if needed for (int j = prednbits; j < minbits; j++) { lblock[t][c][r][s][b]++; hbuf.writeBit(1); } // End of comma-code increment hbuf.writeBit(0); // There can be terminated several segments, send length // info for all terminated truncation points in addition // to final one newtp = 1; maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]]; cblen = (cur_prevtIdxs[b] < 0) ? 0 : cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]]; // Loop on truncation points and count the groups i = (cur_prevtIdxs[b] < 0) ? 0 : cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] + 1; for (; i < maxi; i++, newtp++) { // If terminated truncation point, send length if (cur_cbs[b].isTermPass != null && cur_cbs[b].isTermPass[i]) { cblen = cur_cbs[b].truncRates[i] - cblen; nbits = MathUtil.log2(newtp) + lblock[t][c][r][s][b]; hbuf.writeBits(cblen, nbits); // Initialize for next length newtp = 0; cblen = cur_cbs[b].truncRates[i]; } } // Last truncation point length is always signalled // First calculate number of bits needed to signal // Calculate length cblen = cur_cbs[b].truncRates[i] - cblen; nbits = MathUtil.log2(newtp) + lblock[t][c][r][s][b]; hbuf.writeBits(cblen, nbits); } // End loop on horizontal code-blocks } // End loop on vertical code-blocks } // End loop on subband // -> Copy the data to the body buffer // Ensure size for body data if (bbuf == null || bbuf.length < lblen) { bbuf = new byte[lblen]; } lbbuf = bbuf; lblen = 0; for (int s = minsb; s < maxsb; s++) { // Loop on subbands sb = (SubbandAn) root.getSubbandByIdx(r, s); cur_prevtIdxs = prevtIdxs[t][c][r][s]; cur_cbs = cbs[s]; cur_tIndx = tIndx[s]; ncb = cur_prevtIdxs.length; mend = (prec.cblk[s] == null) ? 0 : prec.cblk[s].length; for (int m = 0; m < mend; m++) { // Vertical code-blocks nend = (prec.cblk[s][m] == null) ? 0 : prec.cblk[s][m].length; for (int n = 0; n < nend; n++) { // Horiz. cblks cbCoord = prec.cblk[s][m][n].idx; b = cbCoord.x + cbCoord.y * sb.numCb.x; if (cur_tIndx[b] > cur_prevtIdxs[b]) { // Block included in this precinct -> Copy data to // body buffer and get code-size if (cur_prevtIdxs[b] < 0) { cblen = cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]; System.arraycopy(cur_cbs[b].data, 0, lbbuf, lblen, cblen); } else { cblen = cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]] - cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]]; System.arraycopy( cur_cbs[b].data, cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]], lbbuf, lblen, cblen); } lblen += cblen; // Verifies if this code-block contains new ROI // information if (cur_cbs[b].nROIcoeff != 0 && (cur_prevtIdxs[b] == -1 || cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] <= cur_cbs[b].nROIcp - 1)) { roiInPkt = true; roiLen = lblen; } // Update truncation point cur_prevtIdxs[b] = cur_tIndx[b]; } } // End loop on horizontal code-blocks } // End loop on vertical code-blocks } // End loop on subbands packetWritable = true; // Must never happen if (hbuf.getLength() == 0) { throw new Error("You have found a bug in PktEncoder, method:" + " encodePacket"); } return hbuf; }