📄 searchengine.java
字号:
//===========================================================================//= A 3D Search Engine based on Vitral SDK toolkit platform =//=-------------------------------------------------------------------------=//= Oscar Chavarro, May 23 2007 =//=-------------------------------------------------------------------------=//= References: =//= [FUNK2003] Funkhouser, Thomas. Min, Patrick. Kazhdan, Michael. Chen, =//= Joyce. Halderman, Alex. Dobkin, David. Jacobs, David. "A Search =//= Engine for 3D Models", ACM Transactions on Graphics, Vol 22. No1. =//= January 2003. Pp. 83-105 =//= [MIN2003] Min, Patrick. Halderman, John A. Kazhdan, Michael. =//= Funkhouser, Thoimas A. "Early Experiences with a 3D Model Search =//= Engine". =//===========================================================================// Java basic classesimport java.text.DecimalFormat;import java.text.FieldPosition;import java.io.File;import java.io.FileReader;import java.io.FileOutputStream;import java.io.InputStreamReader;import java.io.BufferedReader;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.PrintWriter;import java.util.ArrayList;import java.util.HashMap;import java.util.Set;// JOGL classesimport javax.media.opengl.GL;import javax.media.opengl.GLCanvas;// VSDK Classesimport vsdk.toolkit.common.VSDK;import vsdk.toolkit.common.Matrix4x4;import vsdk.toolkit.environment.scene.SimpleBody;import vsdk.toolkit.environment.scene.SimpleBodyGroup;import vsdk.toolkit.environment.scene.SimpleScene;import vsdk.toolkit.environment.geometry.Geometry;import vsdk.toolkit.environment.geometry.VoxelVolume;import vsdk.toolkit.io.geometry.EnvironmentPersistence;import vsdk.toolkit.io.image.ImagePersistence;import vsdk.toolkit.io.metadata.ShapeDescriptorPersistence;import vsdk.toolkit.io.PersistenceElement;import vsdk.toolkit.gui.ProgressMonitorConsole;import vsdk.toolkit.media.IndexedColorImage;import vsdk.toolkit.media.RGBImage;import vsdk.toolkit.media.RGBPixel;import vsdk.toolkit.media.GeometryMetadata;import vsdk.toolkit.media.FourierShapeDescriptor;import vsdk.toolkit.media.PrimitiveCountShapeDescriptor;import vsdk.toolkit.media.ShapeDescriptor;import vsdk.toolkit.processing.ImageProcessing;import vsdk.framework.shapeMatching.ShapeDescriptor2DGenerator;import vsdk.framework.shapeMatching.ShapeDescriptor3DGenerator;import vsdk.framework.shapeMatching.JoglShapeMatchingOfflineRenderer;import vsdk.framework.shapeMatching.JoglProjectedViewRenderer;/**Class `SearchEngine` stablishes a Fachade design pattern role in which anyapplication can ask for high level functional operations of a Vitral basedsearch engine for 3D models.Vitral based search engine for 3D models follows the functional operationsideas of other systems, like the one proposed in [FUNK2003] and [MIN2003].*/public class SearchEngine{ private HashMap<String, TimeReport> timers; private int searchLastSlash(String cad) { int i; for ( i = cad.length()-1; i > 0; i-- ) { if ( cad.charAt(i) == '/' ) { return i+1; } } return 0; } /** This 3D model indexing method implements the analysis technique presented in [FUNK2003].4. */ private GeometryMetadata analyzeModel(GL gl, String filename, boolean withProjection, boolean withPreviews, int distanceFieldSide, GLCanvas canvas, JoglShapeMatchingOfflineRenderer offlineRenderer, JoglProjectedViewRenderer projectedViewRenderer) { //- Variables ----------------------------------------------------- SimpleScene scene = new SimpleScene(); ArrayList<SimpleBody> things; int i, R; VoxelVolume vv; Geometry referenceGeometry; SimpleBodyGroup bodySet; vv = new VoxelVolume(); // Spherical harmonic bandwitdh config. as defined at [FUNK2003].4.1. R = 32; // Voxel grid config. as defined at [FUNK2003].4.1. vv.init(2*R, 2*R, 2*R); GeometryMetadata metadata = new GeometryMetadata(); System.out.println("Analyzing model id [" + metadata.getId() + "], filename: " + filename); try { //- Load scene from specified size and configure its body group --- timers.get("READ_MODEL").start(); File fd = new File(filename); System.out.print(" - Reading file... "); EnvironmentPersistence.importEnvironment(fd, scene); things = scene.getSimpleBodies(); System.out.println("Ok."); bodySet = new SimpleBodyGroup(); for ( i = 0; i < things.size(); i++ ) { bodySet.getBodies().add(things.get(i)); } if ( bodySet.getBodies().size() < 1 ) { System.err.println("Warning: no geometries found inside " + filename + ", skipping shape analysis."); return null; } timers.get("READ_MODEL").stop(); System.out.println(" - Processing " + bodySet.getBodies().size() + " geometries:"); ShapeDescriptor3DGenerator component = new ShapeDescriptor3DGenerator(); //- Calculate spherical harmonics shape descriptor ---------------- System.out.print(" . Primitive count shape descriptor ... "); timers.get("PRIMITIVE_COUNT").start(); PrimitiveCountShapeDescriptor primitiveCountShapeDescriptor; primitiveCountShapeDescriptor = component.calculatePrimitiveCountShapeDescriptor(bodySet, "PRIMITIVE_COUNT"); metadata.getDescriptors().add(primitiveCountShapeDescriptor); timers.get("PRIMITIVE_COUNT").stop(); System.out.println("Ok."); //- Prepare voxelized version of scene for descriptors requiring it timers.get("VOXELIZE").start(); for ( i = 0; i < bodySet.getBodies().size(); i++ ) { referenceGeometry = bodySet.getBodies().get(i).getGeometry(); System.out.print(" . Voxelizing a " + referenceGeometry.getClass().getName() + " ... "); //- Calculate transform matrix -------------------------------- double minmax[] = referenceGeometry.getMinMax(); // Transform from voxelspace to geometry minmax space Matrix4x4 M; M = VoxelVolume.getTransformFromVoxelFrameToMinMax(minmax); //- Primitive rasterization ([FUNK2003].4.1.) ----------------- ProgressMonitorConsole reporter = new ProgressMonitorConsole(); referenceGeometry.doVoxelization(vv, M, reporter); System.out.println("Ok."); // Keep reference clean for garbage collector referenceGeometry = null; } timers.get("VOXELIZE").stop(); //- Calculate spherical harmonics shape descriptor ---------------- System.out.print(" . Spherical harmonics shape descriptor for voxelized geometry ... "); timers.get("SPHERICAL_HARMONICS").start(); FourierShapeDescriptor fourierShapeDescriptor; fourierShapeDescriptor = component.calculateSphericalHarmonicsShapeDescriptor(vv, "SPHERICAL_HARMONIC_3D"); metadata.getDescriptors().add(fourierShapeDescriptor); timers.get("SPHERICAL_HARMONICS").stop(); System.out.println("Ok."); //- Projection views image descriptor extraction [FUNK2003] --- IndexedColorImage distanceFieldsArray[]; RGBImage distanceFieldRgb; if ( withProjection ) { System.out.print(" . Projected views image descriptors (cube 13 setup) ... "); timers.get("CUBE13_PROJECTIONS").start(); distanceFieldsArray = component.calculateCube13ProjectedViewsShapeDescriptors(gl, bodySet, metadata.getDescriptors(), distanceFieldSide, projectedViewRenderer, true); //--------------------------------------------------------- String imageFilename; for ( i = 0; i < distanceFieldsArray.length; i++ ) { ImageProcessing.gammaCorrection(distanceFieldsArray[i], 2.0); distanceFieldRgb = distanceFieldsArray[i].exportToRgbImage(); int x, y; for ( x = 0; x < distanceFieldRgb.getXSize(); x++ ) { for ( y = 0; y < distanceFieldRgb.getYSize(); y++ ) { if ( distanceFieldsArray[i].getPixel(x, y) < 1 ) { distanceFieldRgb.putPixel(x, y, (byte)255, (byte)0, (byte)0); } } } //--------------------------------------------------------- DecimalFormat f1 = new DecimalFormat("0000000"); DecimalFormat f2 = new DecimalFormat("00"); String dirName = "./output/previews/" + f1.format(metadata.getId(), new StringBuffer(""), new FieldPosition(0)).toString(); if ( !PersistenceElement.checkDirectory("./output") || !PersistenceElement.checkDirectory("./output/previews") || !PersistenceElement.checkDirectory(dirName) ) { System.err.println("Unable to create / find directories for preview generation!"); System.err.println("Aborting preview generation."); continue; } imageFilename = dirName + "/df" + f2.format(i, new StringBuffer(""), new FieldPosition(0)).toString() + ".jpg"; ImagePersistence.exportJPG(new File(imageFilename), distanceFieldRgb); distanceFieldsArray[i] = null; } //--------------------------------------------------------- distanceFieldsArray = null; distanceFieldRgb = null; timers.get("CUBE13_PROJECTIONS").stop(); System.out.println("Ok."); } //- Image preview generation [MIN2003] ------------------------ JoglPreviewGenerator component2 = new JoglPreviewGenerator(); if ( withPreviews ) { System.out.print(" . Previews ... "); timers.get("PREVIEWS").start(); GLCanvas mycanvas = null; if ( !offlineRenderer.isPbufferSupported() ) { mycanvas = canvas; } component2.calculatePreviews(gl, component.calculateUnitCubePosing(bodySet), metadata.getId(), 640, 480, mycanvas); timers.get("PREVIEWS").stop(); System.out.println("Ok."); } //----------------------------------------------------------------- if ( (withProjection || withPreviews ) && !offlineRenderer.isPbufferSupported() ) { canvas.swapBuffers(); } //- Free memory (unlink references for garbage collector gathering) for ( i = 0; i < things.size(); i++ ) { things.set(i, null); } while ( things.size() > 0 ) { things.remove(0); } bodySet = null; } catch ( Exception e ) { System.err.println("ERROR: Can not analyze file " + filename); e.printStackTrace(); return null; } metadata.setFilename(filename); things = null; scene = null; return metadata; } public SearchEngine() { timers = createTimers(); } public HashMap<String, TimeReport> getTimers() { return timers; } private HashMap<String, TimeReport> createTimers() { HashMap<String, TimeReport> timers; timers = new HashMap<String, TimeReport>(); timers.put("TOTAL", new TimeReport("TOTAL")); timers.put("VOXELIZE", new TimeReport("VOXELIZE")); timers.put("READ_MODEL", new TimeReport("READ_MODEL")); timers.put("READ_DATABASE", new TimeReport("READ_DATABASE")); timers.put("WRITE_DATABASE", new TimeReport("WRITE_DATABASE")); timers.put("SEARCH_MODEL", new TimeReport("SEARCH_MODEL")); timers.put("SPHERICAL_HARMONICS", new TimeReport("SPHERICAL_HARMONICS")); timers.put("PRIMITIVE_COUNT", new TimeReport("PRIMITIVE_COUNT")); timers.put("CUBE13_PROJECTIONS", new TimeReport("CUBE13_PROJECTIONS")); timers.put("PREVIEWS", new TimeReport("PREVIEWS")); return timers; } /** This method implements the matching step as described in [FUNK2003].3.2. @todo: at a negative tolerance, this method should not use "tolerance" but return the -tolerance closest models. For example, for an equal behavior to the search engine described in [FUNK2003], this value should be -16.0. */ public ArrayList <Result> matchModelSphericalHarmonics( String filename, ShapeDatabase shapeDatabase, double tolerance, int distanceFieldSide) { timers.get("SEARCH_MODEL").start(); //-----------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -