예제 #1
1
 private void calculateGridTranslation() {
   if (transformCells.getScaleX() >= SHOW_GRID_MIN_SCALE) {
     @SuppressWarnings("SuspiciousNameCombination")
     double modX = Math.floorMod(round(transformCells.getTranslateX()), cellWidth);
     double modY = Math.floorMod(round(transformCells.getTranslateY()), cellHeight);
     transformGrid.setToTranslation(-cellWidth + modX - 1, -cellHeight + modY - 1);
   }
 }
예제 #2
0
 public void tree(Graphics2D g2d, double size, int phase) {
   g2d.setColor(colors[phase % 3]);
   new TextLayout(theT.toString(), theFont, g2d.getFontRenderContext()).draw(g2d, 0.0f, 0.0f);
   if (size > 10.0) {
     AffineTransform at = new AffineTransform();
     at.setToTranslation(Twidth, -0.1);
     at.scale(0.6, 0.6);
     g2d.transform(at);
     size *= 0.6;
     new TextLayout(theR.toString(), theFont, g2d.getFontRenderContext()).draw(g2d, 0.0f, 0.0f);
     at.setToTranslation(Rwidth + 0.75, 0);
     g2d.transform(at);
     Graphics2D g2dt = (Graphics2D) g2d.create();
     at.setToRotation(-Math.PI / 2.0);
     g2dt.transform(at);
     tree(g2dt, size, phase + 1);
     g2dt.dispose();
     at.setToTranslation(.75, 0);
     at.rotate(-Math.PI / 2.0);
     at.scale(-1.0, 1.0);
     at.translate(-Twidth, 0);
     g2d.transform(at);
     tree(g2d, size, phase);
   }
   g2d.setTransform(new AffineTransform());
 }
예제 #3
0
  @Override
  protected void paintComponent(Graphics graphics) {
    // Fill in the background:
    Graphics2D g = (Graphics2D) graphics;
    Shape clip = g.getClip();
    g.setColor(LightZoneSkin.Colors.NeutralGray);
    g.fill(clip);

    if (preview == null) {
      PlanarImage image = currentImage.get();
      if (image == null) {
        engine.update(null, false);
      } else if (visibleRect != null && getHeight() > 1 && getWidth() > 1) {
        preview = cropScaleGrayscale(visibleRect, image);
      }
    }
    if (preview != null) {
      int dx, dy;
      AffineTransform transform = new AffineTransform();
      if (getSize().width > preview.getWidth()) dx = (getSize().width - preview.getWidth()) / 2;
      else dx = 0;
      if (getSize().height > preview.getHeight()) dy = (getSize().height - preview.getHeight()) / 2;
      else dy = 0;
      transform.setToTranslation(dx, dy);
      try {
        g.drawRenderedImage(preview, transform);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
예제 #4
0
 public void update() {
   x += Math.cos(heading) * speed;
   y += Math.sin(heading) * speed;
   rect.setLocation((int) Math.round(x), (int) Math.round(y));
   affineTransform.setToTranslation(x, y);
   affineTransform.rotate(heading + (Math.PI / 2));
 }
예제 #5
0
  /**
   * Gets the mark for the specified panel.
   *
   * @param trackerPanel the tracker panel
   * @return the mark
   */
  protected Mark getMark(TrackerPanel trackerPanel) {
    Mark mark = marks.get(trackerPanel);
    TPoint selection = null;
    if (mark == null) {
      selection = trackerPanel.getSelectedPoint();
      Point p = null;
      valid = true; // assume true
      for (int n = 0; n < points.length; n++) {
        if (!valid) continue;
        // determine if point is valid (ie not NaN)
        valid = valid && !Double.isNaN(points[n].getX()) && !Double.isNaN(points[n].getY());
        screenPoints[n] = points[n].getScreenPosition(trackerPanel);
        if (valid && selection == points[n]) p = screenPoints[n];
      }
      mark = footprint.getMark(screenPoints);
      if (p != null) { // point is selected, so draw selection shape
        transform.setToTranslation(p.x, p.y);
        int scale = FontSizer.getIntegerFactor();
        if (scale > 1) {
          transform.scale(scale, scale);
        }
        final Color color = footprint.getColor();
        final Mark stepMark = mark;
        final Shape selectedShape = transform.createTransformedShape(selectionShape);
        mark =
            new Mark() {
              public void draw(Graphics2D g, boolean highlighted) {
                stepMark.draw(g, false);
                Paint gpaint = g.getPaint();
                g.setPaint(color);
                g.fill(selectedShape);
                g.setPaint(gpaint);
              }

              public Rectangle getBounds(boolean highlighted) {
                Rectangle bounds = selectedShape.getBounds();
                bounds.add(stepMark.getBounds(false));
                return bounds;
              }
            };
      }
      final Mark theMark = mark;
      mark =
          new Mark() {
            public void draw(Graphics2D g, boolean highlighted) {
              if (!valid) return;
              theMark.draw(g, false);
            }

            public Rectangle getBounds(boolean highlighted) {
              return theMark.getBounds(highlighted);
            }
          };
      marks.put(trackerPanel, mark);
    }
    return mark;
  }
예제 #6
0
 protected AffineTransform getArrowTrans(
     double sx, double sy, double ex, double ey, double width, double theta) {
   m_arrowTrans.setToTranslation(ex, ey);
   m_arrowTrans.rotate(-HALF_PI + theta + Math.atan2(ey - sy, ex - sx));
   if (width > m_width) {
     double scalar = width / 3;
     m_arrowTrans.scale(scalar, scalar);
   }
   return m_arrowTrans;
 }
예제 #7
0
  @Override
  public Transition2DInstruction[] getInstructions(float progress, Dimension size) {
    if (type == OUT) {
      progress = 1 - progress;
    }
    progress = (float) Math.pow(progress, .5);

    float ySize = (size.height) * .05f;
    float xSize = (size.width) * .05f;
    Vector<RectangularShape> v = new Vector<RectangularShape>();
    float angleProgress = (float) Math.pow(1 - Math.min(progress, 1), .5);
    // pop it over 1:
    float progressZ = 1.3f * progress;
    double w = xSize * progressZ;
    double h = ySize * progressZ;
    float min = (float) (Math.min(w, h));
    for (float y = 0; y < size.height; y += ySize) {
      for (float x = 0; x < size.width; x += xSize) {
        v.add(
            new RoundRectangle2D.Double(
                x + xSize / 2 - w / 2,
                y + ySize / 2 - h / 2,
                w * progress + (1 - progress) * min,
                h * progress + (1 - progress) * min,
                w * angleProgress * progress + (1 - progress) * min * angleProgress,
                h * angleProgress * progress + (1 - progress) * min * angleProgress));
      }
    }
    ImageInstruction[] instr = new ImageInstruction[v.size() + 1];
    instr[0] = new ImageInstruction(false);
    for (int a = 0; a < v.size(); a++) {
      float progress2 = progress; // (float)Math.pow(progress, .9+.2*random.nextFloat());
      RectangularShape r = v.get(a);
      Point2D p1 = new Point2D.Double(r.getCenterX(), r.getCenterY());
      Point2D p2 = new Point2D.Double(r.getCenterX(), r.getCenterY());
      AffineTransform transform = new AffineTransform();
      transform.translate(r.getCenterX(), r.getCenterY());
      transform.scale(30 * (1 - progress) + 1, 30 * (1 - progress) + 1);
      transform.translate(-r.getCenterX(), -r.getCenterY());

      transform.rotate(.3 * (1 - progress2), size.width / 3, size.height / 2);

      transform.transform(p1, p2);
      transform.setToTranslation(p1.getX() - p2.getX(), p1.getY() - p2.getY());
      Shape shape = transform.createTransformedShape(r);
      instr[a + 1] = new ImageInstruction(true, transform, shape);
    }
    if (type == IN) {
      for (int a = 0; a < instr.length; a++) {
        instr[a].isFirstFrame = !instr[a].isFirstFrame;
      }
    }

    return instr;
  }
예제 #8
0
  /**
   * Rotate an image using an AffineTransform.
   *
   * @param timg The image you want to rotate
   * @param degrees Degrees to rotate
   * @return The rotated image
   */
  public BufferedImage rotate(BufferedImage timg, double degrees) {
    AffineTransform xform = new AffineTransform();

    xform.setToTranslation(0.5 * timg.getWidth(), 0.5 * timg.getHeight());
    xform.rotate(degrees);
    xform.translate(-0.5 * timg.getHeight(), -0.5 * timg.getWidth());

    AffineTransformOp op = new AffineTransformOp(xform, AffineTransformOp.TYPE_BILINEAR);

    return op.filter(timg, null);
  }
예제 #9
0
 private void adjustEndingPoint(Point2D start, Point2D end, VisualItem source, VisualItem target) {
   Rectangle2D sourceBounds = source.getBounds();
   Rectangle2D targetBounds = target.getBounds();
   if (source.getShape() == Constants.SHAPE_ELLIPSE) {
     m_edgeTrans.setToTranslation(start.getX(), start.getY());
     m_edgeTrans.rotate(
         -HALF_PI + Math.atan2(start.getY() - end.getY(), start.getX() - end.getX()));
     start.setLocation(0, -sourceBounds.getWidth() / 2.0D);
     m_edgeTrans.transform(start, start);
   } else if (GraphicsLib.intersectLineRectangle(start, end, sourceBounds, m_isctPoints) > 0) {
     start.setLocation(m_isctPoints[0]);
   }
   if (target.getShape() == Constants.SHAPE_ELLIPSE) {
     m_edgeTrans.setToTranslation(end.getX(), end.getY());
     m_edgeTrans.rotate(
         -HALF_PI + Math.atan2(end.getY() - start.getY(), end.getX() - start.getX()));
     end.setLocation(0, -targetBounds.getWidth() / 2.0D);
     m_edgeTrans.transform(end, end);
   } else if (GraphicsLib.intersectLineRectangle(start, end, targetBounds, m_isctPoints) > 0) {
     end.setLocation(m_isctPoints[0]);
   }
 }
예제 #10
0
  /**
   * Determines the control points to use for cubic (Bezier) curve edges. Override this method to
   * provide custom curve specifications. To reduce object initialization, the entries of the
   * Point2D array are already initialized, so use the <tt>Point2D.setLocation()</tt> method rather
   * than <tt>new Point2D.Double()</tt> to more efficiently set custom control points.
   *
   * @param eitem the EdgeItem we are determining the control points for
   * @param cp array of Point2D's (length >= 2) in which to return the control points
   * @param x1 the x co-ordinate of the first node this edge connects to
   * @param y1 the y co-ordinate of the first node this edge connects to
   * @param x2 the x co-ordinate of the second node this edge connects to
   * @param y2 the y co-ordinate of the second node this edge connects to
   */
  protected void getCurveControlPoints(
      EdgeItem eitem, Point2D[] cp, double x1, double y1, double x2, double y2) {
    //        double dx = x2 - x1, dy = y2 - y1;
    //        cp[0].setLocation(x1 + 2 * dx / 3, y1);
    //        cp[1].setLocation(x2 - dx / 8, y2 - dy / 8);

    double d = Point2D.distance(x1, y1, x2, y2);
    cp[0].setLocation(d / 10, -d / 2);
    //        cp[0].setLocation(-d / 10, -d / 2);
    m_edgeTrans.setToTranslation(x2, y2);
    m_edgeTrans.rotate(-HALF_PI + Math.atan2(y2 - y1, x2 - x1));
    m_edgeTrans.transform(cp[0], cp[0]);
    //        cp[1].setLocation(x2, y2);
  }
예제 #11
0
  /* Draws the ball at its current position */
  public void draw(Graphics2D g) {
    double imageWidth = img.getWidth(parent);
    double imageHeight = img.getHeight(parent);

    // translate image such that its centred on its actual position
    objectTransform.setToTranslation(
        (double) pos_x - imageWidth / 2, (double) pos_y - imageHeight / 2);

    // 	// this rotates the planet!
    // 	objectTransform.rotate(Math.PI/800,50.0,51.0);

    g.setTransform(new AffineTransform());
    g.drawImage(img, objectTransform, parent);
  }
예제 #12
0
 protected int adjustEndingPointByMultipleEdge(EdgeItem e, Point2D start, Point2D end) {
   int edgeIndex = getEdgeIndex(e);
   if (edgeIndex < 0) {
     return edgeIndex;
   }
   m_edgeTrans.setToTranslation(end.getX(), end.getY());
   m_edgeTrans.rotate(-HALF_PI + Math.atan2(end.getY() - start.getY(), end.getX() - start.getX()));
   if (edgeIndex % 2 == 1) {
     end.setLocation(4 + edgeIndex, 0);
   } else {
     end.setLocation(-4 - (edgeIndex - 1), 0);
   }
   m_edgeTrans.transform(end, end);
   return edgeIndex;
 }
예제 #13
0
  protected void getCurveControlPoints(
      int edgeIndex, Point2D[] cp, double x1, double y1, double x2, double y2) {
    if (edgeIndex < 0) {
      // draw the line straight if we found one edge
      //            cp[0].setLocation(x2, y2);
      //            cp[1].setLocation(x1, y1);
      return;
    }

    double d = Point2D.distance(x1, y1, x2, y2);
    if (edgeIndex % 2 == 1) {
      cp[0].setLocation(d / 10 * edgeIndex, -d / 2);
    } else {
      cp[0].setLocation(-d / 10 * (edgeIndex - 1), -d / 2);
    }
    m_edgeTrans.setToTranslation(x2, y2);
    m_edgeTrans.rotate(-HALF_PI + Math.atan2(y2 - y1, x2 - x1));
    m_edgeTrans.transform(cp[0], cp[0]);
    //        cp[1].setLocation(x2, y2);
  }
예제 #14
0
  public static void drawService(Graphics2D g2, int x, int y) {
    g2.setPaint(Color.BLACK);
    g2.setStroke(BPMNUtils.extraThinStroke);

    Path2D path = new Path2D.Double();

    path.moveTo(-0.7, 5.0);

    path.lineTo(0.7, 5.0);
    path.lineTo(0.7, 3.6);
    path.lineTo(2.0, 3.0);
    path.lineTo(3.0, 4.0);
    path.lineTo(4.0, 3.0);
    path.lineTo(3.0, 2.0);
    path.lineTo(3.6, 0.7);
    path.lineTo(5.0, 0.7);

    path.lineTo(5.0, -0.7);
    path.lineTo(3.6, -0.7);
    path.lineTo(3.0, -2.0);
    path.lineTo(4.0, -3.0);
    path.lineTo(3.0, -4.0);
    path.lineTo(2.0, -3.0);
    path.lineTo(0.7, -3.6);
    path.lineTo(0.7, -5.0);

    path.lineTo(-0.7, -5.0);
    path.lineTo(-0.7, -3.6);
    path.lineTo(-2.0, -3.0);
    path.lineTo(-3.0, -4.0);
    path.lineTo(-4.0, -3.0);
    path.lineTo(-3.0, -2.0);
    path.lineTo(-3.6, -0.7);
    path.lineTo(-5.0, -0.7);

    path.lineTo(-5.0, 0.7);
    path.lineTo(-3.6, 0.7);
    path.lineTo(-3.0, 2.0);
    path.lineTo(-4.0, 3.0);
    path.lineTo(-3.0, 4.0);
    path.lineTo(-2.0, 3.0);
    path.lineTo(-0.7, 3.6);

    path.closePath();

    // Tranform and scale to target
    AffineTransform at = new AffineTransform();

    // Draw outer shape
    at.scale(Activity.STEREOTYPE_ICON_SIZE * 0.07, Activity.STEREOTYPE_ICON_SIZE * 0.07);
    Shape shape = at.createTransformedShape(path);
    at.setToTranslation(x, y);
    shape = at.createTransformedShape(shape);
    g2.setColor(Color.WHITE);
    g2.fill(shape);
    g2.setColor(Color.BLACK);
    g2.draw(shape);

    // Draw inner shape
    at = new AffineTransform();
    at.scale(Activity.STEREOTYPE_ICON_SIZE * 0.035, Activity.STEREOTYPE_ICON_SIZE * 0.035);
    shape = at.createTransformedShape(path);
    at.setToTranslation(x, y);
    shape = at.createTransformedShape(shape);
    g2.setColor(Color.WHITE);
    g2.fill(shape);
    g2.setColor(Color.BLACK);
    g2.draw(shape);

    // Draw second outer shape
    at = new AffineTransform();
    at.scale(Activity.STEREOTYPE_ICON_SIZE * 0.07, Activity.STEREOTYPE_ICON_SIZE * 0.07);
    shape = at.createTransformedShape(path);
    at.setToTranslation(x + STEREOTYPE_ICON_SIZE / 6, y + STEREOTYPE_ICON_SIZE / 6);
    shape = at.createTransformedShape(shape);
    g2.setColor(Color.WHITE);
    g2.fill(shape);
    g2.setColor(Color.BLACK);
    g2.draw(shape);

    // Draw second inner shape
    at = new AffineTransform();
    at.scale(Activity.STEREOTYPE_ICON_SIZE * 0.035, Activity.STEREOTYPE_ICON_SIZE * 0.035);
    shape = at.createTransformedShape(path);
    at.setToTranslation(x + STEREOTYPE_ICON_SIZE / 6, y + STEREOTYPE_ICON_SIZE / 6);
    shape = at.createTransformedShape(shape);
    g2.setColor(Color.WHITE);
    g2.fill(shape);
    g2.setColor(Color.BLACK);
    g2.draw(shape);
  }
예제 #15
0
  @Override
  public void draw(Graphics2D g2d, MapContent map, MapViewport viewport) {
    if (map != null && this.map == null) {
      this.map = map;
    }

    if (viewport == null) {
      viewport = map.getViewport(); // use the map viewport if one has not been provided
    }
    if (viewport == null || viewport.getScreenArea() == null) {
      return; // renderer is not set up for use yet
    }
    if (collection != null && signsdb == null) {
      signsdb = new Hashtable();
      for (Iterator it1 = collection.iterator(); it1.hasNext(); ) {
        SimpleFeature feature = (SimpleFeature) it1.next();
        StructOffset offset = new StructOffset(0, 0, -1);
        signsdb.put(feature, offset);
      }
    }
    // 消除线条锯齿
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    DefaultFeatureCollection collection = this.getCollection();
    // 遍历得到每个SimpleFeature

    for (Iterator it1 = collection.iterator(); it1.hasNext(); ) {
      SimpleFeature feature = (SimpleFeature) it1.next();
      String id = feature.getID();

      DirectPosition2D geoCoords = null;
      DirectPosition2D signCoords = null;

      Point point = (Point) feature.getAttribute("the_geom");
      if (point != null) {
        // 保存前一次刷新所处的位置
        double x = point.getX();
        double y = point.getY();
        geoCoords = new DirectPosition2D(x, y);
      }

      // 经纬度坐标转换为屏幕坐标
      MathTransform transform_math;
      try {
        transform_math =
            CRS.findMathTransform(
                DefaultGeographicCRS.WGS84, viewport.getCoordinateReferenceSystem(), true);
        transform_math.transform(geoCoords, geoCoords);
        AffineTransform transform_affine = viewport.getWorldToScreen();
        transform_affine.transform(geoCoords, geoCoords);

        g2d.setColor(Color.CYAN);
        g2d.drawOval((int) geoCoords.x, (int) geoCoords.y, 10, 10);

        // 如果被选中,填充空心成实体
        if (id.equals(selectedId)) g2d.fillOval((int) geoCoords.x, (int) geoCoords.y, 10, 10);

        if (signsdb.get(feature) != null) {
          StructOffset offset = (StructOffset) (signsdb.get(feature));
          double offsetX = offset.getX();
          double offsetY = offset.getY();
          signCoords = new DirectPosition2D(geoCoords.x + offsetX, geoCoords.y + offsetY);
        }

        if (signCoords != null) {
          // 坐标默认偏移量<-25,-60>
          int width = 60, height = 40;
          g2d.setColor(Color.CYAN);
          g2d.drawLine(
              (int) geoCoords.x + 5,
              (int) geoCoords.y + 5,
              (int) signCoords.x + offsetX + width / 2,
              (int) signCoords.y + offsetY + height / 2);
          g2d.setColor(Color.BLACK);
          g2d.drawRect((int) signCoords.x + offsetX, (int) signCoords.y + offsetY, width, height);
          g2d.setColor(Color.ORANGE);
          g2d.fillRect((int) signCoords.x + offsetX, (int) signCoords.y + offsetY, width, height);
          g2d.setColor(Color.RED);
          String signsText = (String) feature.getAttribute("name");
          g2d.drawString(
              signsText, (int) signCoords.x + offsetX + 2, (int) signCoords.y + offsetY + 12);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    // 绘制指南针
    //		int x[] = {20,10,20,30};
    //		int y[] = {10,20,30,20};
    //		int nPoint = 4;
    //		g2d.drawPolygon(x, y, nPoint);
    String APP_PATH = "";
    Bundle bundle = Platform.getBundle("MapControl");
    try {
      APP_PATH =
          FileLocator.resolve(bundle.getEntry("")).getPath().substring(1) + "icons/map/compass.png";
    } catch (Exception e) {
      System.out.println(e.getMessage());
      System.exit(1);
    }
    Image src = Toolkit.getDefaultToolkit().getImage(APP_PATH);
    double dx = 0.72, dy = 0.72;
    double x = 10, y = 10; // 指南针左上角
    g2d.rotate(
        -MainMapViewPart.rotateAngle + (Math.PI / 360) * 40,
        x + dx * src.getWidth(null) / 2,
        y + dy * src.getHeight(null) / 2);
    AffineTransform affine = new AffineTransform();
    affine.setToTranslation(x, y);
    affine.scale(dx, dy); // 缩放图片
    g2d.drawImage(src, affine, null);
  }
예제 #16
0
파일: SVGUtil.java 프로젝트: chikoski/sqs
 /**
  * Formats a transformation matrix in millipoints with values as points.
  *
  * @param transform the transformation matrix in millipoints
  * @return the formatted matrix in points
  */
 public static String formatAffineTransformMptToPt(AffineTransform transform) {
   AffineTransform scaled = new AffineTransform(transform);
   scaled.setToTranslation(transform.getTranslateX() / 1000, transform.getTranslateY() / 1000);
   return IFUtil.toString(scaled);
 }
예제 #17
0
  public static void main(String args[]) {
    XComponent xDrawDoc = null;
    try {
      // get the remote office context of a running office (a new office
      // instance is started if necessary)
      com.sun.star.uno.XComponentContext xOfficeContext = Helper.connect();

      // suppress Presentation Autopilot when opening the document
      // properties are the same as described for
      // com.sun.star.document.MediaDescriptor
      PropertyValue[] pPropValues = new PropertyValue[1];
      pPropValues[0] = new PropertyValue();
      pPropValues[0].Name = "Silent";
      pPropValues[0].Value = Boolean.TRUE;

      xDrawDoc =
          Helper.createDocument(
              xOfficeContext, "private:factory/simpress", "_blank", 0, pPropValues);

      XDrawPage xPage = PageHelper.getDrawPageByIndex(xDrawDoc, 0);
      XPropertySet xPagePropSet = UnoRuntime.queryInterface(XPropertySet.class, xPage);

      XShapes xShapes = UnoRuntime.queryInterface(XShapes.class, xPage);

      XShape xShape =
          ShapeHelper.createShape(
              xDrawDoc,
              new Point(0, 0),
              new Size(10000, 2500),
              "com.sun.star.drawing.RectangleShape");
      xShapes.add(xShape);

      XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, xShape);

      HomogenMatrix3 aHomogenMatrix3 = (HomogenMatrix3) xPropSet.getPropertyValue("Transformation");

      java.awt.geom.AffineTransform aOriginalMatrix =
          new java.awt.geom.AffineTransform(
              aHomogenMatrix3.Line1.Column1, aHomogenMatrix3.Line2.Column1,
              aHomogenMatrix3.Line1.Column2, aHomogenMatrix3.Line2.Column2,
              aHomogenMatrix3.Line1.Column3, aHomogenMatrix3.Line2.Column3);

      AffineTransform aNewMatrix1 = new AffineTransform();
      aNewMatrix1.setToRotation(Math.PI / 180 * 15);
      aNewMatrix1.concatenate(aOriginalMatrix);

      AffineTransform aNewMatrix2 = new AffineTransform();
      aNewMatrix2.setToTranslation(2000, 2000);
      aNewMatrix2.concatenate(aNewMatrix1);

      double aFlatMatrix[] = new double[6];
      aNewMatrix2.getMatrix(aFlatMatrix);
      aHomogenMatrix3.Line1.Column1 = aFlatMatrix[0];
      aHomogenMatrix3.Line2.Column1 = aFlatMatrix[1];
      aHomogenMatrix3.Line1.Column2 = aFlatMatrix[2];
      aHomogenMatrix3.Line2.Column2 = aFlatMatrix[3];
      aHomogenMatrix3.Line1.Column3 = aFlatMatrix[4];
      aHomogenMatrix3.Line2.Column3 = aFlatMatrix[5];
      xPropSet.setPropertyValue("Transformation", aHomogenMatrix3);

    } catch (Exception ex) {
      System.out.println(ex);
    }
    System.exit(0);
  }
예제 #18
0
  // Triangulate glyph with 'unicode' if not already done.
  GeometryArrayRetained triangulateGlyphs(GlyphVector gv, char c) {
    Character ch = new Character(c);
    GeometryArrayRetained geo = geomHash.get(ch);

    if (geo == null) {
      // Font Y-axis is downwards, so send affine transform to flip it.
      Rectangle2D bnd = gv.getVisualBounds();
      AffineTransform aTran = new AffineTransform();
      double tx = bnd.getX() + 0.5 * bnd.getWidth();
      double ty = bnd.getY() + 0.5 * bnd.getHeight();
      aTran.setToTranslation(-tx, -ty);
      aTran.scale(1.0, -1.0);
      aTran.translate(tx, -ty);
      Shape shape = gv.getOutline();
      PathIterator pIt = shape.getPathIterator(aTran, tessellationTolerance);
      int flag = -1, numContours = 0, numPoints = 0, i, j, k, num = 0, vertCnt;
      UnorderList coords = new UnorderList(100, Point3f.class);
      float tmpCoords[] = new float[6];
      float lastX = .0f, lastY = .0f;
      float firstPntx = Float.MAX_VALUE, firstPnty = Float.MAX_VALUE;
      GeometryInfo gi = null;
      NormalGenerator ng = new NormalGenerator();
      FastVector contours = new FastVector(10);
      float maxY = -Float.MAX_VALUE;
      int maxYIndex = 0, beginIdx = 0, endIdx = 0, start = 0;

      boolean setMaxY = false;

      while (!pIt.isDone()) {
        Point3f vertex = new Point3f();
        flag = pIt.currentSegment(tmpCoords);
        if (flag == PathIterator.SEG_CLOSE) {
          if (num > 0) {
            if (setMaxY) {
              // Get Previous point
              beginIdx = start;
              endIdx = numPoints - 1;
            }
            contours.addElement(num);
            num = 0;
            numContours++;
          }
        } else if (flag == PathIterator.SEG_MOVETO) {
          vertex.x = tmpCoords[0];
          vertex.y = tmpCoords[1];
          lastX = vertex.x;
          lastY = vertex.y;

          if ((lastX == firstPntx) && (lastY == firstPnty)) {
            pIt.next();
            continue;
          }
          setMaxY = false;
          coords.add(vertex);
          firstPntx = lastX;
          firstPnty = lastY;
          if (num > 0) {
            contours.addElement(num);
            num = 0;
            numContours++;
          }
          num++;
          numPoints++;
          // skip checking of first point,
          // since the last point will repeat this.
          start = numPoints;
        } else if (flag == PathIterator.SEG_LINETO) {
          vertex.x = tmpCoords[0];
          vertex.y = tmpCoords[1];
          // Check here for duplicate points. Code
          // later in this function can not handle
          // duplicate points.

          if ((vertex.x == lastX) && (vertex.y == lastY)) {
            pIt.next();
            continue;
          }
          if (vertex.y > maxY) {
            maxY = vertex.y;
            maxYIndex = numPoints;
            setMaxY = true;
          }
          lastX = vertex.x;
          lastY = vertex.y;
          coords.add(vertex);
          num++;
          numPoints++;
        }
        pIt.next();
      }

      // No data(e.g space, control characters)
      // Two point can't form a valid contour
      if (numPoints == 0) {
        return null;
      }

      // Determine font winding order use for side triangles
      Point3f p1 = new Point3f(), p2 = new Point3f(), p3 = new Point3f();
      boolean flip_side_orient = true;
      Point3f vertices[] = (Point3f[]) coords.toArray(false);

      if (endIdx - beginIdx > 0) {
        // must be true unless it is a single line
        // define as "MoveTo p1 LineTo p2 Close" which is
        // not a valid font definition.

        if (maxYIndex == beginIdx) {
          p1.set(vertices[endIdx]);
        } else {
          p1.set(vertices[maxYIndex - 1]);
        }
        p2.set(vertices[maxYIndex]);
        if (maxYIndex == endIdx) {
          p3.set(vertices[beginIdx]);
        } else {
          p3.set(vertices[maxYIndex + 1]);
        }

        if (p3.x != p2.x) {
          if (p1.x != p2.x) {
            // Use the one with smallest slope
            if (Math.abs((p2.y - p1.y) / (p2.x - p1.x)) > Math.abs((p3.y - p2.y) / (p3.x - p2.x))) {
              flip_side_orient = (p3.x > p2.x);
            } else {
              flip_side_orient = (p2.x > p1.x);
            }
          } else {
            flip_side_orient = (p3.x > p2.x);
          }
        } else {
          // p1.x != p2.x, otherwise all three
          // point form a straight vertical line with
          // the middle point the highest. This is not a
          // valid font definition.
          flip_side_orient = (p2.x > p1.x);
        }
      }

      // Build a Tree of Islands
      int startIdx = 0;
      IslandsNode islandsTree = new IslandsNode(-1, -1);
      int contourCounts[] = contours.getData();

      for (i = 0; i < contours.getSize(); i++) {
        endIdx = startIdx + contourCounts[i];
        islandsTree.insert(new IslandsNode(startIdx, endIdx), vertices);
        startIdx = endIdx;
      }

      coords = null; // Free memory
      contours = null;
      contourCounts = null;

      // Compute islandCounts[][] and outVerts[][]
      UnorderList islandsList = new UnorderList(10, IslandsNode.class);
      islandsTree.collectOddLevelNode(islandsList, 0);
      IslandsNode nodes[] = (IslandsNode[]) islandsList.toArray(false);
      int islandCounts[][] = new int[islandsList.arraySize()][];
      Point3f outVerts[][] = new Point3f[islandCounts.length][];
      int nchild, sum;
      IslandsNode node;

      for (i = 0; i < islandCounts.length; i++) {
        node = nodes[i];
        nchild = node.numChild();
        islandCounts[i] = new int[nchild + 1];
        islandCounts[i][0] = node.numVertices();
        sum = 0;
        sum += islandCounts[i][0];
        for (j = 0; j < nchild; j++) {
          islandCounts[i][j + 1] = node.getChild(j).numVertices();
          sum += islandCounts[i][j + 1];
        }
        outVerts[i] = new Point3f[sum];
        startIdx = 0;
        for (k = node.startIdx; k < node.endIdx; k++) {
          outVerts[i][startIdx++] = vertices[k];
        }

        for (j = 0; j < nchild; j++) {
          endIdx = node.getChild(j).endIdx;
          for (k = node.getChild(j).startIdx; k < endIdx; k++) {
            outVerts[i][startIdx++] = vertices[k];
          }
        }
      }

      islandsTree = null; // Free memory
      islandsList = null;
      vertices = null;

      contourCounts = new int[1];
      int currCoordIndex = 0, vertOffset = 0;
      ArrayList<GeometryArray> triangData = new ArrayList<GeometryArray>();

      Point3f q1 = new Point3f(), q2 = new Point3f(), q3 = new Point3f();
      Vector3f n1 = new Vector3f(), n2 = new Vector3f();
      numPoints = 0;
      // Now loop thru each island, calling triangulator once per island.
      // Combine triangle data for all islands together in one object.
      for (i = 0; i < islandCounts.length; i++) {
        contourCounts[0] = islandCounts[i].length;
        numPoints += outVerts[i].length;
        gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
        gi.setCoordinates(outVerts[i]);
        gi.setStripCounts(islandCounts[i]);
        gi.setContourCounts(contourCounts);
        ng.generateNormals(gi);

        GeometryArray ga = gi.getGeometryArray(false, false, false);
        vertOffset += ga.getVertexCount();

        triangData.add(ga);
      }
      // Multiply by 2 since we create 2 faces of the font
      // Second term is for side-faces along depth of the font
      if (fontExtrusion == null) vertCnt = vertOffset;
      else {
        if (fontExtrusion.shape == null) vertCnt = vertOffset * 2 + numPoints * 6;
        else {
          vertCnt = vertOffset * 2 + numPoints * 6 * (fontExtrusion.pnts.length - 1);
        }
      }

      // XXXX: Should use IndexedTriangleArray to avoid
      // duplication of vertices. To create triangles for
      // side faces, every vertex is duplicated currently.
      TriangleArray triAry =
          new TriangleArray(vertCnt, GeometryArray.COORDINATES | GeometryArray.NORMALS);

      boolean flip_orient[] = new boolean[islandCounts.length];
      boolean findOrient;
      // last known non-degenerate normal
      Vector3f goodNormal = new Vector3f();

      for (j = 0; j < islandCounts.length; j++) {
        GeometryArray ga = triangData.get(j);
        vertOffset = ga.getVertexCount();

        findOrient = false;

        // Create the triangle array
        for (i = 0; i < vertOffset; i += 3, currCoordIndex += 3) {
          // Get 3 points. Since triangle is known to be flat, normal
          // must be same for all 3 points.
          ga.getCoordinate(i, p1);
          ga.getNormal(i, n1);
          ga.getCoordinate(i + 1, p2);
          ga.getCoordinate(i + 2, p3);

          if (!findOrient) {
            // Check here if triangles are wound incorrectly and need
            // to be flipped.
            if (!getNormal(p1, p2, p3, n2)) {
              continue;
            }

            if (n2.z >= EPS) {
              flip_orient[j] = false;
            } else if (n2.z <= -EPS) {
              flip_orient[j] = true;
            } else {
              continue;
            }
            findOrient = true;
          }
          if (flip_orient[j]) {
            // New Triangulator preserves contour orientation. If contour
            // input is wound incorrectly, swap 2nd and 3rd points to
            // sure all triangles are wound correctly for j3d.
            q1.x = p2.x;
            q1.y = p2.y;
            q1.z = p2.z;
            p2.x = p3.x;
            p2.y = p3.y;
            p2.z = p3.z;
            p3.x = q1.x;
            p3.y = q1.y;
            p3.z = q1.z;
            n1.x = -n1.x;
            n1.y = -n1.y;
            n1.z = -n1.z;
          }

          if (fontExtrusion != null) {
            n2.x = -n1.x;
            n2.y = -n1.y;
            n2.z = -n1.z;

            triAry.setCoordinate(currCoordIndex, p1);
            triAry.setNormal(currCoordIndex, n2);
            triAry.setCoordinate(currCoordIndex + 1, p3);
            triAry.setNormal(currCoordIndex + 1, n2);
            triAry.setCoordinate(currCoordIndex + 2, p2);
            triAry.setNormal(currCoordIndex + 2, n2);

            q1.x = p1.x;
            q1.y = p1.y;
            q1.z = p1.z + fontExtrusion.length;
            q2.x = p2.x;
            q2.y = p2.y;
            q2.z = p2.z + fontExtrusion.length;
            q3.x = p3.x;
            q3.y = p3.y;
            q3.z = p3.z + fontExtrusion.length;

            triAry.setCoordinate(currCoordIndex + vertOffset, q1);
            triAry.setNormal(currCoordIndex + vertOffset, n1);
            triAry.setCoordinate(currCoordIndex + 1 + vertOffset, q2);
            triAry.setNormal(currCoordIndex + 1 + vertOffset, n1);
            triAry.setCoordinate(currCoordIndex + 2 + vertOffset, q3);
            triAry.setNormal(currCoordIndex + 2 + vertOffset, n1);
          } else {
            triAry.setCoordinate(currCoordIndex, p1);
            triAry.setNormal(currCoordIndex, n1);
            triAry.setCoordinate(currCoordIndex + 1, p2);
            triAry.setNormal(currCoordIndex + 1, n1);
            triAry.setCoordinate(currCoordIndex + 2, p3);
            triAry.setNormal(currCoordIndex + 2, n1);
          }
        }
        if (fontExtrusion != null) {
          currCoordIndex += vertOffset;
        }
      }

      // Now add side triangles in both cases.

      // Since we duplicated triangles with different Z, make sure
      // currCoordIndex points to correct location.
      if (fontExtrusion != null) {
        if (fontExtrusion.shape == null) {
          boolean smooth;
          // we'll put a crease if the angle between the normals is
          // greater than 44 degrees
          float threshold = (float) Math.cos(44.0 * Math.PI / 180.0);
          float cosine;
          // need the previous normals to check for smoothing
          Vector3f pn1 = null, pn2 = null;
          // need the next normals to check for smoothing
          Vector3f n3 = new Vector3f(), n4 = new Vector3f();
          //  store the normals for each point because they are
          // the same for both triangles
          Vector3f p1Normal = new Vector3f();
          Vector3f p2Normal = new Vector3f();
          Vector3f p3Normal = new Vector3f();
          Vector3f q1Normal = new Vector3f();
          Vector3f q2Normal = new Vector3f();
          Vector3f q3Normal = new Vector3f();

          for (i = 0; i < islandCounts.length; i++) {
            for (j = 0, k = 0, num = 0; j < islandCounts[i].length; j++) {
              num += islandCounts[i][j];
              p1.x = outVerts[i][num - 1].x;
              p1.y = outVerts[i][num - 1].y;
              p1.z = 0.0f;
              q1.x = p1.x;
              q1.y = p1.y;
              q1.z = p1.z + fontExtrusion.length;
              p2.z = 0.0f;
              q2.z = p2.z + fontExtrusion.length;
              for (int m = 0; m < num; m++) {
                p2.x = outVerts[i][m].x;
                p2.y = outVerts[i][m].y;
                q2.x = p2.x;
                q2.y = p2.y;
                if (getNormal(p1, q1, p2, n1)) {

                  if (!flip_side_orient) {
                    n1.negate();
                  }
                  goodNormal.set(n1);
                  break;
                }
              }

              for (; k < num; k++) {
                p2.x = outVerts[i][k].x;
                p2.y = outVerts[i][k].y;
                p2.z = 0.0f;
                q2.x = p2.x;
                q2.y = p2.y;
                q2.z = p2.z + fontExtrusion.length;

                if (!getNormal(p1, q1, p2, n1)) {
                  n1.set(goodNormal);
                } else {
                  if (!flip_side_orient) {
                    n1.negate();
                  }
                  goodNormal.set(n1);
                }

                if (!getNormal(p2, q1, q2, n2)) {
                  n2.set(goodNormal);
                } else {
                  if (!flip_side_orient) {
                    n2.negate();
                  }
                  goodNormal.set(n2);
                }
                // if there is a previous normal, see if we need to smooth
                // this normal or make a crease

                if (pn1 != null) {
                  cosine = n1.dot(pn2);
                  smooth = cosine > threshold;
                  if (smooth) {
                    p1Normal.x = (pn1.x + pn2.x + n1.x);
                    p1Normal.y = (pn1.y + pn2.y + n1.y);
                    p1Normal.z = (pn1.z + pn2.z + n1.z);
                    normalize(p1Normal);

                    q1Normal.x = (pn2.x + n1.x + n2.x);
                    q1Normal.y = (pn2.y + n1.y + n2.y);
                    q1Normal.z = (pn2.z + n1.z + n2.z);
                    normalize(q1Normal);
                  } // if smooth
                  else {
                    p1Normal.x = n1.x;
                    p1Normal.y = n1.y;
                    p1Normal.z = n1.z;
                    q1Normal.x = n1.x + n2.x;
                    q1Normal.y = n1.y + n2.y;
                    q1Normal.z = n1.z + n2.z;
                    normalize(q1Normal);
                  } // else
                } // if pn1 != null
                else {
                  pn1 = new Vector3f();
                  pn2 = new Vector3f();
                  p1Normal.x = n1.x;
                  p1Normal.y = n1.y;
                  p1Normal.z = n1.z;

                  q1Normal.x = (n1.x + n2.x);
                  q1Normal.y = (n1.y + n2.y);
                  q1Normal.z = (n1.z + n2.z);
                  normalize(q1Normal);
                } // else

                // if there is a next, check if we should smooth normal

                if (k + 1 < num) {
                  p3.x = outVerts[i][k + 1].x;
                  p3.y = outVerts[i][k + 1].y;
                  p3.z = 0.0f;
                  q3.x = p3.x;
                  q3.y = p3.y;
                  q3.z = p3.z + fontExtrusion.length;

                  if (!getNormal(p2, q2, p3, n3)) {
                    n3.set(goodNormal);
                  } else {
                    if (!flip_side_orient) {
                      n3.negate();
                    }
                    goodNormal.set(n3);
                  }

                  if (!getNormal(p3, q2, q3, n4)) {
                    n4.set(goodNormal);
                  } else {
                    if (!flip_side_orient) {
                      n4.negate();
                    }
                    goodNormal.set(n4);
                  }

                  cosine = n2.dot(n3);
                  smooth = cosine > threshold;

                  if (smooth) {
                    p2Normal.x = (n1.x + n2.x + n3.x);
                    p2Normal.y = (n1.y + n2.y + n3.y);
                    p2Normal.z = (n1.z + n2.z + n3.z);
                    normalize(p2Normal);

                    q2Normal.x = (n2.x + n3.x + n4.x);
                    q2Normal.y = (n2.y + n3.y + n4.y);
                    q2Normal.z = (n2.z + n3.z + n4.z);
                    normalize(q2Normal);
                  } else { // if smooth
                    p2Normal.x = n1.x + n2.x;
                    p2Normal.y = n1.y + n2.y;
                    p2Normal.z = n1.z + n2.z;
                    normalize(p2Normal);
                    q2Normal.x = n2.x;
                    q2Normal.y = n2.y;
                    q2Normal.z = n2.z;
                  } // else
                } else { // if k+1 < num
                  p2Normal.x = (n1.x + n2.x);
                  p2Normal.y = (n1.y + n2.y);
                  p2Normal.z = (n1.z + n2.z);
                  normalize(p2Normal);

                  q2Normal.x = n2.x;
                  q2Normal.y = n2.y;
                  q2Normal.z = n2.z;
                } // else

                // add pts for the 2 tris
                // p1, q1, p2 and p2, q1, q2

                if (flip_side_orient) {
                  triAry.setCoordinate(currCoordIndex, p1);
                  triAry.setNormal(currCoordIndex, p1Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, q1);
                  triAry.setNormal(currCoordIndex, q1Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, p2);
                  triAry.setNormal(currCoordIndex, p2Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, p2);
                  triAry.setNormal(currCoordIndex, p2Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, q1);
                  triAry.setNormal(currCoordIndex, q1Normal);
                  currCoordIndex++;
                } else {
                  triAry.setCoordinate(currCoordIndex, q1);
                  triAry.setNormal(currCoordIndex, q1Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, p1);
                  triAry.setNormal(currCoordIndex, p1Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, p2);
                  triAry.setNormal(currCoordIndex, p2Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, q1);
                  triAry.setNormal(currCoordIndex, q1Normal);
                  currCoordIndex++;

                  triAry.setCoordinate(currCoordIndex, p2);
                  triAry.setNormal(currCoordIndex, p2Normal);
                  currCoordIndex++;
                }
                triAry.setCoordinate(currCoordIndex, q2);
                triAry.setNormal(currCoordIndex, q2Normal);
                currCoordIndex++;
                pn1.x = n1.x;
                pn1.y = n1.y;
                pn1.z = n1.z;
                pn2.x = n2.x;
                pn2.y = n2.y;
                pn2.z = n2.z;
                p1.x = p2.x;
                p1.y = p2.y;
                p1.z = p2.z;
                q1.x = q2.x;
                q1.y = q2.y;
                q1.z = q2.z;
              } // for k

              // set the previous normals to null when we are done
              pn1 = null;
              pn2 = null;
            } // for j
          } // for i
        } else { // if shape
          int m, offset = 0;
          Point3f P2 = new Point3f(), Q2 = new Point3f(), P1 = new Point3f();
          Vector3f nn = new Vector3f(),
              nn1 = new Vector3f(),
              nn2 = new Vector3f(),
              nn3 = new Vector3f();
          Vector3f nna = new Vector3f(), nnb = new Vector3f();
          float length;
          boolean validNormal = false;

          // fontExtrusion.shape is specified, and is NOT straight line
          for (i = 0; i < islandCounts.length; i++) {
            for (j = 0, k = 0, offset = num = 0; j < islandCounts[i].length; j++) {
              num += islandCounts[i][j];

              p1.x = outVerts[i][num - 1].x;
              p1.y = outVerts[i][num - 1].y;
              p1.z = 0.0f;
              q1.x = p1.x;
              q1.y = p1.y;
              q1.z = p1.z + fontExtrusion.length;
              p3.z = 0.0f;
              for (m = num - 2; m >= 0; m--) {
                p3.x = outVerts[i][m].x;
                p3.y = outVerts[i][m].y;

                if (getNormal(p3, q1, p1, nn1)) {
                  if (!flip_side_orient) {
                    nn1.negate();
                  }
                  goodNormal.set(nn1);
                  break;
                }
              }
              for (; k < num; k++) {
                p2.x = outVerts[i][k].x;
                p2.y = outVerts[i][k].y;
                p2.z = 0.0f;
                q2.x = p2.x;
                q2.y = p2.y;
                q2.z = p2.z + fontExtrusion.length;
                getNormal(p1, q1, p2, nn2);

                p3.x = outVerts[i][(k + 1) == num ? offset : (k + 1)].x;
                p3.y = outVerts[i][(k + 1) == num ? offset : (k + 1)].y;
                p3.z = 0.0f;
                if (!getNormal(p3, p2, q2, nn3)) {
                  nn3.set(goodNormal);
                } else {
                  if (!flip_side_orient) {
                    nn3.negate();
                  }
                  goodNormal.set(nn3);
                }

                // Calculate normals at the point by averaging normals
                // of two faces on each side of the point.
                nna.x = (nn1.x + nn2.x);
                nna.y = (nn1.y + nn2.y);
                nna.z = (nn1.z + nn2.z);
                normalize(nna);

                nnb.x = (nn3.x + nn2.x);
                nnb.y = (nn3.y + nn2.y);
                nnb.z = (nn3.z + nn2.z);
                normalize(nnb);

                P1.x = p1.x;
                P1.y = p1.y;
                P1.z = p1.z;
                P2.x = p2.x;
                P2.y = p2.y;
                P2.z = p2.z;
                Q2.x = q2.x;
                Q2.y = q2.y;
                Q2.z = q2.z;
                for (m = 1; m < fontExtrusion.pnts.length; m++) {
                  q1.z = q2.z = fontExtrusion.pnts[m].x;
                  q1.x = P1.x + nna.x * fontExtrusion.pnts[m].y;
                  q1.y = P1.y + nna.y * fontExtrusion.pnts[m].y;
                  q2.x = P2.x + nnb.x * fontExtrusion.pnts[m].y;
                  q2.y = P2.y + nnb.y * fontExtrusion.pnts[m].y;

                  if (!getNormal(p1, q1, p2, n1)) {
                    n1.set(goodNormal);
                  } else {
                    if (!flip_side_orient) {
                      n1.negate();
                    }
                    goodNormal.set(n1);
                  }

                  if (flip_side_orient) {
                    triAry.setCoordinate(currCoordIndex, p1);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;

                    triAry.setCoordinate(currCoordIndex, q1);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;
                  } else {
                    triAry.setCoordinate(currCoordIndex, q1);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;

                    triAry.setCoordinate(currCoordIndex, p1);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;
                  }
                  triAry.setCoordinate(currCoordIndex, p2);
                  triAry.setNormal(currCoordIndex, n1);
                  currCoordIndex++;

                  if (!getNormal(p2, q1, q2, n1)) {
                    n1.set(goodNormal);
                  } else {
                    if (!flip_side_orient) {
                      n1.negate();
                    }
                    goodNormal.set(n1);
                  }

                  if (flip_side_orient) {
                    triAry.setCoordinate(currCoordIndex, p2);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;

                    triAry.setCoordinate(currCoordIndex, q1);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;
                  } else {
                    triAry.setCoordinate(currCoordIndex, q1);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;

                    triAry.setCoordinate(currCoordIndex, p2);
                    triAry.setNormal(currCoordIndex, n1);
                    currCoordIndex++;
                  }
                  triAry.setCoordinate(currCoordIndex, q2);
                  triAry.setNormal(currCoordIndex, n1);
                  currCoordIndex++;

                  p1.x = q1.x;
                  p1.y = q1.y;
                  p1.z = q1.z;
                  p2.x = q2.x;
                  p2.y = q2.y;
                  p2.z = q2.z;
                } // for m
                p1.x = P2.x;
                p1.y = P2.y;
                p1.z = P2.z;
                q1.x = Q2.x;
                q1.y = Q2.y;
                q1.z = Q2.z;
                nn1.x = nn2.x;
                nn1.y = nn2.y;
                nn1.z = nn2.z;
              } // for k
              offset = num;
            } // for j
          } // for i
        } // if shape
      } // if fontExtrusion
      geo = (GeometryArrayRetained) triAry.retained;
      geomHash.put(ch, geo);
    }

    return geo;
  }