public MeshViewer(String title, ArrayList<Triangle> triangles, boolean culling) { super(title); enableCullling = culling; this.setSize(640, 480); ArrayList<PointND> edgePoints = new ArrayList<PointND>(); for (Triangle t : triangles) { edgePoints.add(t.getA()); edgePoints.add(t.getB()); edgePoints.add(t.getC()); } PointND center = DoublePrecisionPointUtil.getGeometricCenter(edgePoints); Translation translation = new Translation(center.getAbstractVector().negated()); double max = 0; for (PointND p : edgePoints) { p.applyTransform(translation); for (int i = 0; i < 3; i++) { if (Math.abs(p.get(i)) > max) { max = Math.abs(p.get(i)); } } } AffineTransform affineTransform = new AffineTransform(SimpleMatrix.I_3.dividedBy(max / 1.0), new SimpleVector(0, 0, 0)); for (Triangle t : triangles) { t.applyTransform(translation); t.applyTransform(affineTransform); } this.triangles = triangles; }
public Grid2D raytraceScene(PrioritizableScene phantomScene, Projection projection) { Trajectory geom = Configuration.getGlobalConfiguration().getGeometry(); // Grid2D slice = new Grid2D(geom.getDetectorWidth(), geom.getDetectorHeight()); Grid2D slice = detector.createDetectorGrid(geom.getDetectorWidth(), geom.getDetectorHeight(), projection); rayTracer.setScene(phantomScene); // Second rule of optimization is: Optimize later. PointND raySource = new PointND(0, 0, 0); raySource.setCoordinates(projection.computeCameraCenter()); StraightLine castLine = new StraightLine(raySource, new SimpleVector(0, 0, 0)); SimpleVector centerPixDir = null; if (accurate) { centerPixDir = projection.computePrincipalAxis(); } // SimpleVector prinpoint = trajectory.getProjectionMatrix(sliceNumber).getPrincipalPoint(); double xcorr = 0; // trajectory.getDetectorWidth()/2 - prinpoint.getElement(0); double ycorr = 0; // trajectory.getDetectorHeight()/2 - prinpoint.getElement(1); double length = trajectory.getSourceToDetectorDistance(); Edge environmentEdge = new Edge(new PointND(0), new PointND(length)); ArrayList<PhysicalObject> fallBackBackground = new ArrayList<PhysicalObject>(1); SimpleVector pixel = new SimpleVector(0, 0); boolean negate = false; for (int y = 0; y < trajectory.getDetectorHeight(); y++) { for (int x = 0; x < trajectory.getDetectorWidth(); x++) { pixel.setElementValue(0, x - xcorr); pixel.setElementValue(1, y - ycorr); SimpleVector dir = projection.computeRayDirection(pixel); if ((y == 0) && (x == 0)) { // Check that ray direction is towards origin. double max = 0; int index = 0; for (int i = 0; i < 3; i++) { if (Math.abs(dir.getElement(i)) > max) { max = Math.abs(dir.getElement(i)); index = i; } } double t = -raySource.get(index) / dir.getElement(index); if (t < 0) negate = true; } if (negate) dir.negate(); castLine.setDirection(dir); ArrayList<PhysicalObject> segments = rayTracer.castRay(castLine); if (accurate) { double dirCosine = SimpleOperators.multiplyInnerProd(centerPixDir, dir); length = trajectory.getSourceToDetectorDistance() / dirCosine; } if (segments == null) { fallBackBackground.clear(); segments = fallBackBackground; } else { if (accurate) { environmentEdge = new Edge(new PointND(0), new PointND(length - getTotalSegmentsLength(segments))); } } environment.setShape(environmentEdge); segments.add(environment); /* old code: double integral = absorptionModel.evaluateLineIntegral(segments); slice.putPixelValue(x, y, integral); */ detector.writeToDetector(slice, x, y, segments); } } return slice; }
public Grid2D createSinogramm(Grid2D phantom, boolean filter) { // Bouding Box Box imageBox = new Box( phantom.getWidth() * phantom.getSpacing()[0], phantom.getHeight() * phantom.getSpacing()[1], 2.0d); imageBox.setLowerCorner(new PointND(phantom.getOrigin()[0], phantom.getOrigin()[1], -1.0)); imageBox.setUpperCorner(new PointND(-phantom.getOrigin()[0], -phantom.getOrigin()[1], 1.0)); // walk over each projection for (int indexProjections = 0; indexProjections < projections; indexProjections++) { // walk along the detector for (int indexDetektor = 0; indexDetektor < numberPixel; indexDetektor++) { // define the parallel lines of the detector double[] indexWorld = this.indexToPhysical(indexDetektor, indexProjections); double angle = angleWidthR * indexProjections; double s = indexWorld[0]; double cos = Math.cos(angle); double sin = Math.sin(angle); PointND p1 = new PointND(cos * s, sin * s, 0.0d); PointND p2 = new PointND(cos * s - sin, sin * s + cos, 0.0d); StraightLine line = new StraightLine(p1, p2); // intersection of the box and the line ArrayList<PointND> crossingPoints = imageBox.intersect(line); // if there is no intersection -> change direction of the line and look again if (crossingPoints.size() == 0) { p2 = new PointND(cos * s + sin, sin * s - cos, 0.0d); line = new StraightLine(p1, p2); crossingPoints = imageBox.intersect(line); } if (crossingPoints.size() == 2) { PointND c1 = crossingPoints.get(0); PointND c2 = crossingPoints.get(1); // compute distance between intersectoin points double distance = c1.euclideanDistance(c2); // define the direction of the line double deltax = (c2.get(0) - c1.get(0)) / (distance); double deltay = (c2.get(1) - c1.get(1)) / (distance); double deltaz = (c2.get(2) - c1.get(2)) / (distance); PointND richtung = new PointND(deltax, deltay, deltaz); // result value at the current position in the sinogramm float val = 0.f; // stepsize of the integral double delta = 0.5; // in mm // line integral for (double k = 0; k < (distance); k = k + delta) { double indexX = c1.get(0) + k * (richtung.get(0)); double indexY = c1.get(1) + k * (richtung.get(1)); double[] indexImage = phantom.physicalToIndex(indexX, indexY); val += InterpolationOperators.interpolateLinear(phantom, indexImage[0], indexImage[1]); } this.setAtIndex(indexDetektor, indexProjections, (float) (val * delta)); } } } if (filter == true) { filtering(this); } Grid2D result = new Grid2D(this); return result; }
public void setTrajectory( int numProjectionMatrices, double sourceToAxisDistance, double averageAngularIncrement, double detectorOffsetX, double detectorOffsetY, CameraAxisDirection uDirection, CameraAxisDirection vDirection, SimpleVector rotationAxis, PointND rotationCenter, double angleFirstProjection) { this.projectionMatrices = new Projection[numProjectionMatrices]; this.primaryAngles = new double[numProjectionMatrices]; this.numProjectionMatrices = numProjectionMatrices; this.sourceToAxisDistance = sourceToAxisDistance; this.averageAngularIncrement = averageAngularIncrement; this.detectorOffsetU = detectorOffsetX; this.detectorOffsetV = detectorOffsetY; double cosPhi = Math.cos(General.toRadians(angleFirstProjection)); double sinPhi = Math.sin(General.toRadians(angleFirstProjection)); SimpleMatrix rotMat = new SimpleMatrix(3, 3); rotMat.setElementValue(0, 0, cosPhi); rotMat.setElementValue(0, 1, sinPhi); rotMat.setElementValue(1, 0, -sinPhi); rotMat.setElementValue(1, 1, cosPhi); rotMat.setElementValue(2, 2, 1); SimpleVector centerToCameraIdealAtInitialAngle = SimpleOperators.multiply(rotMat, new SimpleVector(sourceToAxisDistance, 0, 0)); Plane3D trajPlane = new Plane3D( rotationAxis, SimpleOperators.multiplyInnerProd(rotationAxis, rotationCenter.getAbstractVector())); double distToPlane = trajPlane.computeDistance(new PointND(centerToCameraIdealAtInitialAngle)); SimpleVector centerToCameraDir = SimpleOperators.subtract( SimpleOperators.add( rotationAxis.multipliedBy(-1 * distToPlane), centerToCameraIdealAtInitialAngle), rotationCenter.getAbstractVector()); centerToCameraDir.divideBy(centerToCameraDir.normL2()); SimpleVector centerToCameraInitialInPlane = centerToCameraDir.multipliedBy(sourceToAxisDistance); for (int i = 0; i < numProjectionMatrices; i++) { primaryAngles[i] = i * averageAngularIncrement + angleFirstProjection; // System.out.println(primaryAngles[i] + " " + averageAngularIncrement + " " + // this.reconDimensions[0] + " " + this.reconDimensions[1]); projectionMatrices[i] = new Projection(); double rotationAngle = General.toRadians(primaryAngles[i]); projectionMatrices[i].setRtFromCircularTrajectory( rotationCenter.getAbstractVector(), rotationAxis, sourceToAxisDistance, centerToCameraInitialInPlane, uDirection, vDirection, rotationAngle); SimpleVector spacingUV = new SimpleVector(pixelDimensionX, pixelDimensionY); SimpleVector sizeUV = new SimpleVector(detectorWidth, detectorHeight); SimpleVector offset = new SimpleVector(detectorOffsetX, detectorOffsetY); projectionMatrices[i].setKFromDistancesSpacingsSizeOffset( sourceToDetectorDistance, spacingUV, sizeUV, offset, 1.0, 0); } this.projectionStackSize = numProjectionMatrices; // System.out.println("Defined geometry with SDD " +sourceToDetectorDistance); }