Print

Print


Commit in GeomConverter/src/org/lcsim/geometry/compact/converter/svg on MAIN
SvgConverter.java+198-901.1 -> 1.2
current version of SVG converter

GeomConverter/src/org/lcsim/geometry/compact/converter/svg
SvgConverter.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- SvgConverter.java	26 Jan 2011 01:19:39 -0000	1.1
+++ SvgConverter.java	27 Jan 2011 00:52:48 -0000	1.2
@@ -2,13 +2,14 @@
 
 import java.text.DecimalFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
 import org.jdom.Element;
 import org.jdom.Namespace;
 import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITranslation3D;
 import org.lcsim.detector.solids.Tube;
 import org.lcsim.geometry.Calorimeter;
 import org.lcsim.geometry.Tracker;
@@ -17,7 +18,10 @@
 import org.lcsim.geometry.compact.VisAttributes;
 import org.lcsim.geometry.subdetector.DiskTracker;
 import org.lcsim.geometry.subdetector.MultiLayerTracker;
+import org.lcsim.geometry.subdetector.PolyconeSupport;
 import org.lcsim.geometry.subdetector.SiTrackerBarrel;
+import org.lcsim.geometry.subdetector.TubeSegment;
+import org.lcsim.geometry.subdetector.PolyconeSupport.ZPlane;
 
 /**
  * Convert from a compact detector description to an SVG view. This will only work correctly for full ILC physics
@@ -27,11 +31,8 @@
  */
 // TODO Fix manual scaling where possible (primarily in text and associated lines).
 // TODO Add groups for label lines so user units (from Detector) can be used instead of scaling.
-// TODO Adjust label lines so they lie exactly on detector edges.
 // TODO For Calorimeters that are large enough (Hcal, Muon) add layering instead of fill.
-// TODO Implement output for trackers.
-// TODO Implement additional types besides tracker/calorimeter (supports, etc.).
-// TODO Vertical bottom label lines?
+// TODO Add lefthand labels of Calorimeter types, Tracker types, and Coil/Solenoid.
 class SvgConverter
 {
     // Namespaces.
@@ -44,9 +45,14 @@
     // These margins are in USER not absolute units.
     private static final double xmargin = 1500;
     private static final double ymargin = 1000;
-    
+
+    // FIXME This needs to be determined dynamically from size of
+    // left margin + left labels + detector area.
     private static final double viewportX = 1200;
-    private static final double viewportY = 1200;
+
+    // FIXME This needs to be determined dynamically from size of
+    // upper margin + detector area + bottom label area.
+    private static final double viewportY = 1000;
 
     // Formatting for length measurements.
     private static final DecimalFormat df = new DecimalFormat("#.##");
@@ -54,9 +60,9 @@
     // Static access to important grouping elements.
     private static Element labelsY;
     private static Element labelsX;
-    //private static Element labelLinesX;
-    //private static Element labelLinesY;
-    private static Element subdetGroup;
+    // private static Element labelLinesX;
+    // private static Element labelLinesY;
+    // private static Element subdetGroup;
 
     // If barrel detector is less than this thick,
     // its outer radius label will not be printed.
@@ -68,7 +74,7 @@
     // Starting offset for text as bottom labels are created.
     // This incremented as Z labels are added.
     private static double zLabelOffsetY = 25;
-    
+
     // If a layer is less than this size in LCSim units (mm),
     // then it will be drawn as a line rather than a rectangle.
     private static double minTrackerLayerThickness = 50;
@@ -105,18 +111,18 @@
 
         // Subdetector group.
         Element gs = new Element("g", ns);
-        subdetGroup = gs;
+        // subdetGroup = gs;
         g.addContent(gs);
         gs.setAttribute("transform", "scale(" + scale + ") " + "translate(" + xmargin + ", " + ymargin + ")");
 
         // SVG X axis.
-        Element xaxis = line(gs, 0., zy[ 1 ], zy[ 0 ], zy[ 1 ]);
+        Element xaxis = line(gs, 0., zy[1], zy[0], zy[1]);
         xaxis.setAttribute("stroke-width", "1");
         xaxis.setAttribute("stroke", "black");
         xaxis.setAttribute("id", "xaxis");
 
         // SVG Y axis.
-        Element yaxis = line(gs, 0., 0., 0., zy[ 1 ]);
+        Element yaxis = line(gs, 0., 0., 0., zy[1]);
         yaxis.setAttribute("stroke-width", "1");
         yaxis.setAttribute("stroke", "black");
         yaxis.setAttribute("id", "yaxis");
@@ -133,10 +139,10 @@
         g.addContent(labelsX);
         labelsX.setAttribute("font-size", "12");
         labelsX.setAttribute("id", "xlabels");
-        labelsX.setAttribute("transform", "translate(" + (xmargin * scale) + ", " + ((ymargin + zy[ 1 ]) * scale) + ")");
+        labelsX.setAttribute("transform", "translate(" + (xmargin * scale) + ", " + ((ymargin + zy[1]) * scale) + ")");
 
         // Make ZY view of Detector.
-        convertSubdetectors(gs, detector, zy[ 0 ], zy[ 1 ]);
+        convertSubdetectors(gs, detector, zy[0], zy[1]);
 
         // Return the created Element to be written out by Main.
         return root;
@@ -145,7 +151,7 @@
     private static String convertColor(VisAttributes vis)
     {
         float[] rgba = vis.getRGBA();
-        return "rgb(" + rgba[ 0 ] * 100 + "%, " + rgba[ 1 ] * 100 + "%, " + rgba[ 2 ] * 100 + "%)";
+        return "rgb(" + rgba[0] * 100 + "%, " + rgba[1] * 100 + "%, " + rgba[2] * 100 + "%)";
     }
 
     public static class InnerRadiusCompare implements Comparator<Calorimeter>
@@ -169,7 +175,7 @@
         }
     }
 
-    public static class InnerZCompare implements Comparator<Calorimeter>    
+    private static class InnerZCompare implements Comparator<Calorimeter>
     {
         public int compare(Calorimeter subdet1, Calorimeter subdet2)
         {
@@ -190,10 +196,13 @@
         }
     }
 
+    // TODO Cleanup this messy method. Make and use one list of Subdetectors rather than several.
     private static void convertSubdetectors(Element parent, Detector detector, double maxZ, double maxY)
-    {
-        // Make a list of Calorimeters.
+    {        
         List<Subdetector> subdetectors = detector.getSubdetectorList();
+        
+        // Look at Calorimeters first.
+        List<Calorimeter> calorimeters = new ArrayList<Calorimeter>();
         List<Calorimeter> barrelCalorimeters = new ArrayList<Calorimeter>();
         List<Calorimeter> endcapCalorimeters = new ArrayList<Calorimeter>();
         for (Subdetector subdet : subdetectors)
@@ -209,70 +218,79 @@
                     endcapCalorimeters.add((Calorimeter)subdet);
                 }
             }
-
-        }
-
-        // HACK Manual array copy. Arrays method loses type info.
-        Calorimeter[] barrelCalorimeterArray = new Calorimeter[barrelCalorimeters.size()];
-        for (int i = 0; i < barrelCalorimeterArray.length; i++ )
-        {
-            barrelCalorimeterArray[ i ] = barrelCalorimeters.get(i);
-        }
-
+        }        
+        
         // Sort Calorimeter barrels on innerR.
-        Arrays.sort(barrelCalorimeterArray, new InnerRadiusCompare());
-       
-        // Sort Calorimeter endcaps on innerZ.
-        Calorimeter[] endcapCalorimeterArray = new Calorimeter[endcapCalorimeters.size()];
-        for (int i = 0; i < endcapCalorimeterArray.length; i++ )
-        {
-            endcapCalorimeterArray[ i ] = endcapCalorimeters.get(i);
-        }
-        Arrays.sort(endcapCalorimeterArray, new InnerZCompare());     
+        Collections.sort(barrelCalorimeters, new InnerRadiusCompare());
+        
+        // Add sorted barrel calorimeters to list.
+        calorimeters.addAll(barrelCalorimeters);        
 
-        // Draw barrel calorimeters from inner radius to outer radius.        
-        for (Calorimeter subdet : barrelCalorimeterArray)
-        {
-            SvgConverter.convertSubdetector(parent, (Subdetector)subdet, maxZ, maxY);
-        }
+        // Sort Calorimeter endcaps on innerZ.
+        Collections.sort(endcapCalorimeters, new InnerZCompare());
+        
+        // Add sorted endcap calorimeters to list.
+        calorimeters.addAll(endcapCalorimeters);
 
-        // Draw endcap calorimeters from inner Z to outer Z.
-        for (Calorimeter subdet : endcapCalorimeterArray)
+        // Make the SVG for ordered Calorimeters.
+        for (Calorimeter cal : calorimeters)
         {
-            SvgConverter.convertSubdetector(parent, (Subdetector)subdet, maxZ, maxY);
+            SvgConverter.convertSubdetector(parent, (Subdetector)cal, maxZ, maxY);
         }
         
-        // Now draw the Trackers.
+        // Now draw the Trackers, supports, and dead material.
         for (org.lcsim.geometry.Subdetector subdet : detector.getSubdetectors().values())
         {
-            // TODO Remove if statement here when all types are handled.
-            if (subdet instanceof SiTrackerBarrel || 
-                    subdet instanceof MultiLayerTracker || 
-                    subdet instanceof DiskTracker)
+            // TODO Remove if statement here when all types are handled above.
+            //if (subdet instanceof SiTrackerBarrel || subdet instanceof MultiLayerTracker
+            //        || subdet instanceof DiskTracker || subdet instanceof PolyconeSupport
+            //        || subdet instanceof TubeSegment)
+            if (!(subdet instanceof Calorimeter))
             {
                 SvgConverter.convertSubdetector(parent, (Subdetector)subdet, maxZ, maxY);
             }
         }
-        
-        // process Trackers and others here
+    }
+
+    /**
+     * Order a List of ZPlanes by Z value.
+     * 
+     * @author jeremym
+     * 
+     */
+    private static class ZPlaneCompare implements Comparator<ZPlane>
+    {
+        public int compare(ZPlane zp1, ZPlane zp2)
+        {
+            double z1 = zp1.getZ();
+            double z2 = zp2.getZ();
+            if (z1 > z2)
+                return 1;
+            else if (z1 < z2)
+                return -1;
+            else
+                return 0;
+        }
     }
 
     private static void convertSubdetector(Element parent, Subdetector subdet, double maxZ, double maxY)
     {
+        // Debug print.
         System.out.println(">> " + subdet.getName());
 
         // visualization
         VisAttributes vis = subdet.getVisAttributes();
-        
-        // If not visible then immediately return. 
+
+        // If not visible then immediately return.
         if (!vis.getVisible())
         {
-            System.out.println("not visible");
+            System.out.println("    *not visible* ... skipping");
             return;
         }
-        
+
+        // Convert color parameters to SVG format.
         String color = convertColor(vis);
-        float alpha = vis.getRGBA()[ 3 ];
+        float alpha = vis.getRGBA()[3];
 
         // Make a group for this Subdetector.
         Element g = new Element("g", ns);
@@ -280,7 +298,7 @@
         parent.addContent(g);
 
         // Set Subdetector's line and fill colors.
-        g.setAttribute("stroke", color);        
+        g.setAttribute("stroke", color);
         g.setAttribute("fill", color);
         g.setAttribute("stroke-width", "3"); // Default stroke-width.
         g.setAttribute("opacity", Float.toString(alpha));
@@ -290,12 +308,9 @@
 
         if (subdet instanceof Calorimeter)
         {
-            // Use a black outline.
-            //g.setAttribute("stroke", "black"); 
-            
-            // Turn off rectangle outline.
+            // Turn off shape outline.
             g.setAttribute("stroke-width", "0");
-            
+
             // Get Calorimeter generic parameters.
             Calorimeter cal = (Calorimeter)subdet;
             double innerR = cal.getInnerRadius();
@@ -313,7 +328,8 @@
                 rect(g, 0., maxY - outerR, outerR - innerR, halfZ);
 
                 // Line at inner radius of barrel calorimeter.
-                Element lineInner = line(labelGroup, 75., ((maxY - innerR) * scale), xmargin * scale, (maxY - innerR) * scale);
+                Element lineInner =
+                        line(labelGroup, 75., ((maxY - innerR) * scale), xmargin * scale, (maxY - innerR) * scale);
                 lineInner.setAttribute("stroke-dasharray", "6,3");
                 lineInner.setAttribute("stroke", "gray");
                 lineInner.setAttribute("stroke-width", "1");
@@ -325,7 +341,8 @@
                 if (outerR - innerR > yLabelTolerance)
                 {
                     // Line at outer radius of barrel calorimeter.
-                    Element lineOuter = line(labelGroup, 75., ((maxY - outerR) * scale), xmargin * scale, (maxY - outerR) * scale);
+                    Element lineOuter =
+                            line(labelGroup, 75., ((maxY - outerR) * scale), xmargin * scale, (maxY - outerR) * scale);
                     lineOuter.setAttribute("stroke-dasharray", "6,3");
                     lineOuter.setAttribute("stroke", "gray");
                     lineOuter.setAttribute("stroke-width", "1");
@@ -383,7 +400,7 @@
         {
             // Draw barrel trackers.
             if (subdet instanceof SiTrackerBarrel || subdet instanceof MultiLayerTracker)
-            {                
+            {
                 // Loop over SiTrackerBarrel layers.
                 IDetectorElement de = subdet.getDetectorElement();
                 for (IDetectorElement layer : de.getChildren())
@@ -394,7 +411,7 @@
                     double r = tube.getInnerRadius() + thickness / 2;
                     double halfZ = tube.getZHalfLength();
                     double outerR = tube.getOuterRadius();
-                    double innerR = tube.getInnerRadius();                    
+                    double innerR = tube.getInnerRadius();
 
                     // Draw a line for this tracker layer.
                     if (thickness < minTrackerLayerThickness)
@@ -407,26 +424,26 @@
                     {
                         // Use a black outline to separate nearby layers.
                         g.setAttribute("stroke", "black");
-                        
+
                         // Make a rectangle for the layer.
                         rect(g, 0., maxY - outerR, outerR - innerR, halfZ);
                     }
                 }
             }
             // TODO Replace compact based code with IDetectorElement, but DiskTracker
-            //      layers need their own DetectorElements.
+            // layers need their own DetectorElements.
             else if (subdet instanceof DiskTracker)
-            {                                
+            {
                 DiskTracker diskTracker = (DiskTracker)subdet;
                 int nlayers = diskTracker.getInnerR().length;
-                for (int i=0, n=nlayers; i<n; i++)
+                for (int i = 0, n = nlayers; i < n; i++ )
                 {
                     double innerR = diskTracker.getInnerR()[i];
                     double outerR = diskTracker.getOuterR()[i];
                     double z = diskTracker.getThickness()[i];
                     double innerZ = diskTracker.getInnerZ()[i];
-                    double midZ = innerZ + z / 2; 
-                                        
+                    double midZ = innerZ + z / 2;
+
                     // Draw a line for this tracker layer.
                     if (z < minTrackerLayerThickness)
                     {
@@ -438,18 +455,111 @@
                     {
                         // Use a black outline to separate nearby layers.
                         g.setAttribute("stroke", "black");
-                        
+
                         // Make a rectangle for the layer.
                         rect(g, innerZ, maxY - outerR, outerR - innerR, z);
-                    }    
+                    }
+                }
+            }
+        }
+        else if (subdet instanceof PolyconeSupport)
+        {
+            PolyconeSupport support = (PolyconeSupport)subdet;
+
+            // Sort zplanes by z, from negative to positive.
+            List<ZPlane> zplanes = new ArrayList<ZPlane>(support.getZPlanes());
+            Collections.sort(zplanes, new ZPlaneCompare());
+
+            // Make a list of usable ZPlanes.
+            List<ZPlane> zplanesUse = new ArrayList<ZPlane>();
+            for (int i = 0, n = zplanes.size(); i < n; i++ )
+            {
+                ZPlane zplane = zplanes.get(i);
+
+                // Only use ZPlanes in positive Z.
+                if (zplane.getZ() > 0)
+                {
+                    // Make a modified ZPlane for components that cross the xaxis.
+                    if (i > 0 && zplanesUse.size() == 0)
+                    {
+                        ZPlane lastNegZPlane = zplanes.get(i - 1);
+
+                        // Check if last point had same radius values, so that
+                        // drawing across the X axis can be done simply by starting
+                        // from x==0.
+                        if (lastNegZPlane.getRMin() == zplane.getRMin() && lastNegZPlane.getRMax() == zplane.getRMax())
+                        {
+                            ZPlane borderZPlane = new ZPlane(lastNegZPlane.getRMin(), lastNegZPlane.getRMax(), 0);
+                            zplanesUse.add(borderZPlane);
+                        }
+                        // FIXME Handle ZPlanes crossing xaxis that have different radii from the next ZPlane.
+                    }
+                    // Add positive ZPlane to usable list.
+                    else
+                    {
+                        zplanesUse.add(zplane);
+                    }
+                }
+            }
+
+            if (zplanesUse.size() > 0)
+            {
+                StringBuffer buff = new StringBuffer();
+
+                // Start by making outer radii points in positive X direction.
+                for (ZPlane zplane : zplanesUse)
+                {
+                    double outerR = zplane.getRMax();
+                    double z = zplane.getZ();
+                    buff.append(z + "," + (maxY - outerR) + " ");
+                }
+
+                // Make a reverse list.
+                List<ZPlane> reverseZPlanes = new ArrayList<ZPlane>(zplanesUse);
+                Collections.reverse(reverseZPlanes);
+
+                // Now make inner radius points going in the negative X direction.
+                for (ZPlane zplane : reverseZPlanes)
+                {
+                    double innerR = zplane.getRMin();
+                    double z = zplane.getZ();
+                    buff.append(z + "," + (maxY - innerR) + " ");
                 }
+                String points = buff.toString();
+                points.trim();
+
+                // System.out.println(points);
+
+                // Make the polygon using the list of points.
+                Element polygon = new Element("polygon", ns);
+                polygon.setAttribute("points", points);
+                g.addContent(polygon);
             }
         }
-        // TODO Handle additional types here...       
-        // PolyconeSupport
-        // SiTrackerEndcap 
-        // SiTrackerEndcap2 (difficult...no mother vols for layers)
-        // TubeSegment
+        else if (subdet instanceof TubeSegment)
+        {            
+            TubeSegment tube = (TubeSegment)subdet;
+                        
+            if (tube.getTransform().getTranslation().z() > 0)
+            {
+                double innerR = tube.getInnerRadius();
+                double outerR = tube.getOuterRadius();
+                double halfZ = tube.getZHalfLength();
+                double zmin = tube.getTransform().getTranslation().z() - halfZ;
+                           
+                // Only draw components with a positive z position.
+                if (zmin > 0)
+                {
+                    rect(g, zmin, maxY - outerR, outerR - innerR, halfZ);
+                }
+                
+                // FIXME: Rotation is ignored.
+                // FIXME: TubeSegments going across Y axis are ignored.
+            }
+        }
+        // TODO Handle these additional types...
+        // SiTrackerEndcap
+        // SiTrackerEndcap2
     }
 
     private static Element line(Element parent, double x1, double y1, double x2, double y2)
@@ -512,16 +622,14 @@
             throw new RuntimeException("Could not find ZY extent of this Detector!");
         }
 
-        zy[ 0 ] = z;
-        zy[ 1 ] = y;
+        zy[0] = z;
+        zy[1] = y;
 
         return zy;
     }
-    
+
     /*
-    interface SubdetectorConverter
-    {
-       void convert(Element parent, Detector detector, double maxZ, double maxY);
-    }
-    */
+     * This would be nice. interface SubdetectorConverter { void convert(Element parent, Detector detector, double maxZ,
+     * double maxY); }
+     */
 }
\ No newline at end of file
CVSspam 0.2.8