Package ca.eandb.jmist.framework.loader.dxf

Source Code of ca.eandb.jmist.framework.loader.dxf.DxfSceneBuilder$GroupHandler_VERTEX

/**
* Java Modular Image Synthesis Toolkit (JMIST)
* Copyright (C) 2008-2013 Bradley W. Kimmel
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package ca.eandb.jmist.framework.loader.dxf;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;

import ca.eandb.jmist.framework.SceneElement;
import ca.eandb.jmist.framework.accel.BoundingIntervalHierarchy;
import ca.eandb.jmist.framework.color.ColorModel;
import ca.eandb.jmist.framework.color.rgb.RGBColorModel;
import ca.eandb.jmist.framework.geometry.primitive.PolyhedronGeometry;
import ca.eandb.jmist.framework.material.LambertianMaterial;
import ca.eandb.jmist.framework.scene.CollapseSceneElement;
import ca.eandb.jmist.framework.scene.MaterialSceneElement;
import ca.eandb.jmist.framework.scene.MergeSceneElement;
import ca.eandb.jmist.framework.scene.TransformableSceneElement;
import ca.eandb.jmist.math.AffineMatrix3;
import ca.eandb.jmist.math.Basis3;
import ca.eandb.jmist.math.MathUtil;
import ca.eandb.jmist.math.Point3;
import ca.eandb.jmist.math.Vector3;

/**
* @author Brad
*
*/
public final class DxfSceneBuilder {

  private static final int ACCEL_THRESHOLD = Integer.MAX_VALUE;

  private static final class Block {
    public Point3 base;
    public MergeSceneElement geometry;
    public SceneElement root;
    public PolyhedronGeometry _3dfaces = null;
  }

  private static final class State {
    public String currentSection;

    public Map<String, Block> blocks = new HashMap<String, Block>();

    public Block currentBlock = null;
    public PolyhedronGeometry currentMesh = null;
    public MergeSceneElement root = new MergeSceneElement();
    public PolyhedronGeometry _3dfaces = null;
  }

  private static interface GroupHandler {

    void parse(State state, DxfReader dxf);

  }

  @SuppressWarnings("unused")
  static final class GroupHandler_BLOCK implements GroupHandler {

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.loader.dxf.SceneBuilder.GroupHandler#parse(ca.eandb.jmist.framework.loader.dxf.SceneBuilder.State, ca.eandb.jmist.framework.loader.dxf.DxfReader)
     */
    @Override
    public void parse(State state, DxfReader dxf) {
      int flags = 0;
      String name = null;
      String xref = null;
      double[] p = { 0.0, 0.0, 0.0 };

      DxfElement elem;
      int gc;

      do {
        dxf.advance();
        elem = dxf.getCurrentElement();
        gc = elem.getGroupCode();

        switch (gc) {

        case 1:
          xref = elem.getStringValue();
          break;

        case 2:
        case 3:
          name = elem.getStringValue();
          break;

        case 10:
        case 20:
        case 30:
          p[(gc - 10) / 10] = elem.getFloatValue();
          break;

        }
      } while (gc != 0);

      if (xref != null && !xref.isEmpty()) {
        System.err.println("Warning, Xrefs in blocks not supported");
        System.err.printf("Block xref: %s", xref);
        System.err.println();
      }

      state.currentBlock = new Block();
      state.currentBlock.base = new Point3(p[0], p[1], p[2]);
      state.currentBlock.geometry = new MergeSceneElement();

      if (state.currentBlock.base.squaredDistanceToOrigin() > MathUtil.EPSILON) {
        System.out.println("Block with non-origin base.");
      }

      state.blocks.put(name, state.currentBlock);

    }

  }

  static final class GroupHandler_ENDBLK implements GroupHandler {

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.loader.dxf.SceneBuilder.GroupHandler#parse(ca.eandb.jmist.framework.loader.dxf.SceneBuilder.State, ca.eandb.jmist.framework.loader.dxf.DxfReader)
     */
    @Override
    public void parse(State state, DxfReader dxf) {
      state.currentMesh = null;
      state.currentBlock = null;
      dxf.advance();
    }

  }

  static final class xGroupHandler_3DFACE implements GroupHandler {

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.loader.dxf.SceneBuilder.GroupHandler#parse(ca.eandb.jmist.framework.loader.dxf.SceneBuilder.State, ca.eandb.jmist.framework.loader.dxf.DxfReader)
     */
    @Override
    public void parse(State state, DxfReader dxf) {

      double[] v = {
          0.0, 0.0, 0.0,
          0.0, 0.0, 0.0,
          0.0, 0.0, 0.0,
          0.0, 0.0, 0.0
      };

      DxfElement elem;
      int gc;

      do {
        dxf.advance();
        elem = dxf.getCurrentElement();
        gc = elem.getGroupCode();

        switch (gc) {

        case 10:
        case 11:
        case 12:
        case 13:
        case 20:
        case 21:
        case 22:
        case 23:
        case 30:
        case 31:
        case 32:
        case 33:
          int vi = gc % 10;
          int ci = (gc - 10) / 10;
          v[3 * vi + ci] = elem.getFloatValue();
          break;

        }
      } while (gc != 0);

      PolyhedronGeometry mesh = null;

      if (state.currentSection.equals("ENTITIES")) {
        if (state._3dfaces == null) {
          state._3dfaces = new PolyhedronGeometry();
          state.root.addChild(state._3dfaces);
        }
        mesh = state._3dfaces;
      } else if (state.currentBlock != null) {
        if (state.currentBlock._3dfaces == null) {
          state.currentBlock._3dfaces = new PolyhedronGeometry();
          state.currentBlock.geometry.addChild(state.currentBlock._3dfaces);
        }
        mesh = state.currentBlock._3dfaces;
      } else {
        return;
      }

      Point3[] vertices = new Point3[4];
      for (int i = 0; i < 4; i++) {
        vertices[i] = new Point3(v[3 * i + 0], v[3 * i + 1], v[3 * i + 2]);
      }

      int nv = vertices[3].squaredDistanceTo(vertices[2]) < MathUtil.EPSILON ? 3 : 4;
      int offset = mesh.getNumVertices();

      for (int i = 0; i < nv; i++) {
        mesh.addVertex(vertices[i]);
      }

      mesh.addFace(new int[]{ offset + 0, offset + 1, offset + 2 });
      if (nv > 3) { // quad
        mesh.addFace(new int[]{ offset + 2, offset + 3, offset + 0 });
      }

    }

  }

  @SuppressWarnings("unused")
  static final class GroupHandler_POLYLINE implements GroupHandler {

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.loader.dxf.SceneBuilder.GroupHandler#parse(ca.eandb.jmist.framework.loader.dxf.SceneBuilder.State, ca.eandb.jmist.framework.loader.dxf.DxfReader)
     */
    @Override
    public void parse(State state, DxfReader dxf) {
      int flags = 0;
      int surfaceType = 0;

      DxfElement elem;

      do {
        dxf.advance();
        elem = dxf.getCurrentElement();

        switch (elem.getGroupCode()) {

        case 70: // flags
          flags = elem.getIntegerValue();
          break;

        case 75: // surface type
          surfaceType = elem.getIntegerValue();
          break;
        }
      } while (elem.getGroupCode() != 0);

      if ((flags & 64) != 0) {
        state.currentMesh = new PolyhedronGeometry();
        if (state.currentBlock != null) {
          state.currentBlock.geometry.addChild(state.currentMesh);
        }
        if (state.currentSection.equals("ENTITIES")) {
          state.root.addChild(state.currentMesh);
        }
      }
    }

  }

  static final class GroupHandler_VERTEX implements GroupHandler {

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.loader.dxf.SceneBuilder.GroupHandler#parse(ca.eandb.jmist.framework.loader.dxf.SceneBuilder.State, ca.eandb.jmist.framework.loader.dxf.DxfReader)
     */
    @Override
    public void parse(State state, DxfReader dxf) {

      DxfElement elem;
      int flags = 0;
      double[] v = { 0.0, 0.0, 0.0 };
      int[] f = { 0, 0, 0, 0 };
      int gc;

      do {
        dxf.advance();
        elem = dxf.getCurrentElement();
        gc = elem.getGroupCode();

        switch (gc) {

        case 10:
        case 20:
        case 30:
          v[(gc - 10) / 10] = elem.getFloatValue();
          break;

        case 70: // flags
          flags = elem.getIntegerValue();

          /* all polyface vertices have 128-bit set.  If it is not
           * set, we are not interested in this vertex.
           */
          if ((flags & 128) == 0) {
            return;
          }
          break;

        case 71:
        case 72:
        case 73:
        case 74:
          f[gc - 71] = elem.getIntegerValue();
          break;

        }
      } while (gc != 0);

      if ((flags & 64) != 0) { // mesh vertex
        state.currentMesh.addVertex(new Point3(v[0], v[1], v[2]));
      } else { // mesh face
        if (f[2] > 0) { // we require at least 3 vertices
          state.currentMesh.addFace(new int[]{ f[0] - 1, f[1] - 1, f[2] - 1 });
          if (f[3] > 0) { // quad
            state.currentMesh.addFace(new int[]{ f[2] - 1, f[3] - 1, f[0] - 1 });
          }
        }
      }

    }

  }

  static final class GroupHandler_SECTION implements GroupHandler {

    public void parse(State state, DxfReader dxf) {
      DxfUtil.advanceToGroupCode(2, dxf);
      state.currentSection = dxf.getCurrentElement().getStringValue();
      dxf.advance();
    }

  }

  static final class GroupHandler_ENDSEC implements GroupHandler {
    public void parse(State state, DxfReader dxf) {
      state.currentSection = null;
      dxf.advance();
    }
  }

  static final class GroupHandler_INSERT implements GroupHandler {

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.loader.dxf.SceneBuilder.GroupHandler#parse(ca.eandb.jmist.framework.loader.dxf.SceneBuilder.State, ca.eandb.jmist.framework.loader.dxf.DxfReader)
     */
    @Override
    public void parse(State state, DxfReader dxf) {

      DxfElement elem;
      double[] p = { 0.0, 0.0, 0.0 };
      double[] scale = { 1.0, 1.0, 1.0 };
      double[] ext = { 0.0, 0.0, 1.0 };
      int gc;

      String ref = null;
      double angle = 0.0;

      do {
        dxf.advance();
        elem = dxf.getCurrentElement();
        gc = elem.getGroupCode();

        switch (gc) {

        case 2:
          ref = elem.getStringValue();
          break;

        case 10:
        case 20:
        case 30:
          p[(gc - 10) / 10] = elem.getFloatValue();
          break;

        case 41:
        case 42:
        case 43:
          scale[gc - 41] = elem.getFloatValue();
          break;

        case 50:
          angle = elem.getFloatValue();
          break;

        case 210:
        case 220:
        case 230:
          ext[(gc - 210) / 10] = elem.getFloatValue();
          break;

        }
      } while (gc != 0);

      Block block = state.blocks.get(ref);
      if (block.geometry.getNumPrimitives() == 0) {
        return;
      }
//      double tol = 1.0;
//      if (!MathUtil.equal(angle, 0.0, tol) && !MathUtil.equal(angle, 180.0, tol) && !MathUtil.equal(angle, 360.0, tol)) {// && !MathUtil.equal(angle, 90.0, tol) && !MathUtil.equal(angle, 270.0, tol)) {
//        System.err.printf("Non-standard angle: %f degrees", angle);
//        System.err.println();
//        return;
//      }

      Point3 insertionPoint = new Point3(p[0], p[1], p[2]);
      Vector3 extrusionDir = new Vector3(ext[0], ext[1], ext[2]);

//      if (extrusionDir.minus(Vector3.K).squaredLength() > MathUtil.EPSILON) { System.err.printf("%f %f %f", extrusionDir.x(), extrusionDir.y(), extrusionDir.z()); System.err.println(); return; }
//      if (!MathUtil.areEqual(scale)) {
//        System.err.println("Non-uniform scaling");
//      }

      if (block.root == null) {
        int np = block.geometry.getNumPrimitives();
        if (np >= ACCEL_THRESHOLD) {
          block.root = new BoundingIntervalHierarchy(block.geometry);
        } else {
          block.root = block.geometry;
        }
      }

      TransformableSceneElement e = new TransformableSceneElement(block.root);
      e.translate(block.base.vectorFromOrigin());
      e.stretch(scale[0], scale[1], scale[2]);
      e.rotateZ(Math.toRadians(angle));

      e.translate(insertionPoint.vectorFromOrigin());
      Basis3 basis = DxfUtil.getBasisFromArbitraryAxis(extrusionDir);
      AffineMatrix3 T = AffineMatrix3.fromColumns(basis.u(), basis.v(), basis.w());
      e.transform(T);


      if (state.currentSection.equals("ENTITIES")) {
        state.root.addChild(block.root instanceof BoundingIntervalHierarchy ? new CollapseSceneElement(e) : e);
      }
      if (state.currentBlock != null) {
        state.currentBlock.geometry.addChild(block.root instanceof BoundingIntervalHierarchy ? new CollapseSceneElement(e) : e);
      }
    }

  }

  private static final Map<String, GroupHandler> handlers = new HashMap<String, GroupHandler>();
  {
    Class<?>[] classes = DxfSceneBuilder.class.getDeclaredClasses();
    for (Class<?> clazz : classes) {
      String name = clazz.getSimpleName();
      if (name.startsWith("GroupHandler_")) {
        String type = name.substring(13);
        try {
          GroupHandler handler = (GroupHandler) clazz.newInstance();
          handlers.put(type, handler);
        } catch (Exception e) {
          System.err.printf("Failed to instantiate %s", name);
          System.err.println();
          e.printStackTrace();
        }
      }
    }
  }

  private static final GroupHandler rootGroupHandler = new GroupHandler() {

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.loader.dxf.SceneBuilder.GroupHandler#parse(ca.eandb.jmist.framework.loader.dxf.SceneBuilder.State, ca.eandb.jmist.framework.loader.dxf.DxfReader)
     */
    @Override
    public void parse(State state, DxfReader dxf) {
      String key = dxf.getCurrentElement().getStringValue();
      GroupHandler handler = handlers.get(key);
      if (handler != null) {
        handler.parse(state, dxf);
      } else {
        dxf.advance();
      }
    }

  };

  public SceneElement createScene(ColorModel cm, DxfReader dxf) {
    State state = new State();
    do {
      DxfUtil.advanceToGroupCode(0, dxf);
      if (dxf.getCurrentElement().getStringValue().equals("EOF")) {
        break;
      }
      rootGroupHandler.parse(state, dxf);
    } while (true);
    return new MaterialSceneElement(new LambertianMaterial(cm.getGray(0.5)), new BoundingIntervalHierarchy(state.root));
  }

  public static void main(String[] args) {
    String fn = "C:\\Users\\Brad\\Documents\\11-01-22 Sun Life Atria Q2.dxf";
    FileReader fr;
    try {
      fr = new FileReader(fn);
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      return;
    }
    DxfReader dxf = new AsciiDxfReader(fr);
    DxfSceneBuilder builder = new DxfSceneBuilder();
    ColorModel cm = RGBColorModel.getInstance();
    SceneElement elem = builder.createScene(cm, dxf);
    System.out.println(elem.toString());
  }

}
TOP

Related Classes of ca.eandb.jmist.framework.loader.dxf.DxfSceneBuilder$GroupHandler_VERTEX

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.