docs: public static <O extends CameraPinhole, D extends CameraPinhole>
  	Point2Transform2_F64 transformChangeModel(AdjustmentType type,
  											  O paramOriginal,
  											  D paramDesired,
  											  boolean desiredToOriginal,
  											  D paramMod)
  	{
  		LensDistortionNarrowFOV original = LensDistortionFactory.narrow(paramOriginal);
  		LensDistortionNarrowFOV desired = LensDistortionFactory.narrow(paramDesired);
  
  		Point2Transform2_F64 ori_p_to_n = original.undistort_F64(true, false);
  		Point2Transform2_F64 des_n_to_p = desired.distort_F64(false, true);
  
  		Point2Transform2_F64 ori_to_des = new SequencePoint2Transform2_F64(ori_p_to_n,des_n_to_p);
  
  		Point2D_F64 work = new Point2D_F64();
  		RectangleLength2D_F64 bound;
  		if( type == AdjustmentType.FULL_VIEW ) {
  			bound = DistortImageOps.boundBox_F64(paramOriginal.width, paramOriginal.height,
  					new PointToPixelTransform_F64(ori_to_des),work);
  		} else if( type == AdjustmentType.EXPAND) {
  			bound = LensDistortionOps_F64.boundBoxInside(paramOriginal.width, paramOriginal.height,
  					new PointToPixelTransform_F64(ori_to_des),work);
  			// ensure there are no strips of black
  			LensDistortionOps_F64.roundInside(bound);
  		} else if( type == AdjustmentType.CENTER) {
  			bound = LensDistortionOps_F64.centerBoxInside(paramOriginal.width, paramOriginal.height,
  					new PointToPixelTransform_F64(ori_to_des),work);
  		} else if( type == AdjustmentType.NONE ) {
  			bound = new RectangleLength2D_F64(0,0,paramDesired.width, paramDesired.height);
  		} else {
  			throw new IllegalArgumentException("Unsupported type "+type);
  		}
  
  		double scaleX = bound.width/paramDesired.width;
  		double scaleY = bound.height/paramDesired.height;
  
  		double scale;
  
  		if( type == AdjustmentType.FULL_VIEW ) {
  			scale = Math.max(scaleX, scaleY);
  		} else if( type == AdjustmentType.EXPAND) {
  			scale = Math.min(scaleX, scaleY);
  		} else if( type == AdjustmentType.CENTER) {
  			scale = Math.max(scaleX, scaleY);
  		} else {
  			scale = 1.0;
  		}
  
  		double deltaX = (bound.x0 + (scaleX-scale)*paramDesired.width/ 2.0 );
  		double deltaY = (bound.y0 + (scaleY-scale)*paramDesired.height/ 2.0 );
  
  		// adjustment matrix
  		DMatrixRMaj A = new DMatrixRMaj(3,3,true,scale,0,deltaX,0,scale,deltaY,0,0,1);
  		DMatrixRMaj A_inv = new DMatrixRMaj(3, 3);
  		if (!CommonOps_DDRM.invert(A, A_inv)) {
  			throw new RuntimeException("Failed to invert adjustment matrix.  Probably bad.");
  		}
  
  		if( paramMod != null ) {
  			PerspectiveOps.adjustIntrinsic(paramDesired, A_inv, paramMod);
  		}
  
  		if( desiredToOriginal ) {
  			Point2Transform2_F64 des_p_to_n = desired.undistort_F64(true, false);
  			Point2Transform2_F64 ori_n_to_p = original.distort_F64(false, true);
  			PointTransformHomography_F64 adjust = new PointTransformHomography_F64(A);
  			return new SequencePoint2Transform2_F64(adjust,des_p_to_n,ori_n_to_p);
  		} else {
  			PointTransformHomography_F64 adjust = new PointTransformHomography_F64(A_inv);
  			return new SequencePoint2Transform2_F64(ori_to_des, adjust);
  		}
  	}