Sample

Schnappinger/aoi/artofillusion.ObjectViewer

Human rating uses the original dataset scale.

Human2.61
Lines481

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
11.0Δ 4.1
Scalabrino0.7490–1; higher is more readable
48.6Δ 33.4
Dorn0.0060–1; higher is more readable
16.5Δ 1.3
Mi0.2650–1; higher is more readable
17.8Δ 2.6
LLOC250Logical lines; fewer is more readable
10.2Δ 5.0
DeepSeek V4 Pro13.670–20; mean of three runs
26.9Δ 11.7
GPT-6.1 Sol150–20; mean of three runs
25.7Δ 10.6
BTTF0.210–1; higher is more readable
11.6Δ 3.6
Human2.611–4; original rating
15.2

Views

Source code

/* Copyright (C) 1999-2008 by Peter Eastman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package artofillusion; import artofillusion.image.*; import artofillusion.math.*; import artofillusion.object.*; import artofillusion.ui.*; import buoy.event.*; import buoy.widget.*; import java.awt.*; import java.awt.geom.*; import java.util.*; /** The ObjectViewer class is the abstract superclass of components which display a single object and allow the user to edit it. */ public abstract class ObjectViewer extends ViewerCanvas { protected MeshEditController controller; protected boolean showScene, useWorldCoords, freehandSelection, draggingBox, squareBox, sentClick; protected Point clickPoint, dragPoint; protected Vector<Point> selectBoundsPoints; protected Shape selectBounds; protected ObjectInfo thisObjectInScene; protected Scene theScene; public ObjectViewer(MeshEditController controller, RowContainer p) { super(ArtOfIllusion.getPreferences().getUseOpenGL() && isOpenGLAvailable()); this.controller = controller; buildChoices(p); } /** Get the controller which maintains the state for this viewer. */ public MeshEditController getController() { return controller; } /** Estimate the range of depth values that the camera will need to render. This need not be exact, but should err on the side of returning bounds that are slightly too large. @return the two element array {minDepth, maxDepth} */ public double[] estimateDepthRange() { Mat4 toView = theCamera.getWorldToView(); // Find the depth range for the object being edited. ObjectInfo info = getController().getObject(); BoundingBox bounds = info.getBounds(); double dx = bounds.maxx-bounds.minx; double dy = bounds.maxy-bounds.miny; double dz = bounds.maxz-bounds.minz; double size = 0.5*Math.sqrt(dx*dx+dy*dy+dz*dz); Vec3 origin = getDisplayCoordinates().fromLocal().times(bounds.getCenter()); double depth = toView.times(origin).z; double min = depth-size, max = depth+size; // Now check the rest of the scene. if (showScene) { for (int i = 0; i < theScene.getNumObjects(); i++) { info = theScene.getObject(i); if (info == thisObjectInScene) continue; bounds = info.getBounds(); dx = bounds.maxx-bounds.minx; dy = bounds.maxy-bounds.miny; dz = bounds.maxz-bounds.minz; size = 0.5*Math.sqrt(dx*dx+dy*dy+dz*dz); origin = info.getCoords().fromLocal().times(bounds.getCenter()); if (!useWorldCoords) origin = thisObjectInScene.getCoords().toLocal().times(origin); depth = toView.times(origin).z; if (depth-size < min) min = depth-size; if (depth+size > max) max = depth+size; } } return new double [] {min, max}; } @Override public void viewChanged(boolean selectionOnly) { super.viewChanged(selectionOnly); if (renderMode == RENDER_RENDERED && !selectionOnly) { // Re-render the image. Renderer rend = ArtOfIllusion.getPreferences().getObjectPreviewRenderer(); if (rend == null) return; adjustCamera(true); Scene sc; Camera cam = theCamera.duplicate(); if (showScene && theScene != null) { sc = new Scene(); sc.setEnvironmentColor(theScene.getEnvironmentColor()); sc.setEnvironmentTexture(theScene.getEnvironmentTexture()); sc.setEnvironmentMapping(theScene.getEnvironmentMapping()); sc.setEnvironmentParameterValues(theScene.getEnvironmentParameterValues()); sc.setEnvironmentMode(theScene.getEnvironmentMode()); sc.setAmbientColor(theScene.getAmbientColor()); Object3D thisObject = (thisObjectInScene == null ? null : thisObjectInScene.getObject()); for (int i = 0; i < theScene.getNumObjects(); i++) { ObjectInfo obj = theScene.getObject(i); if (obj.getObject() == thisObject) sc.addObject(obj.duplicate(controller.getObject().getObject()), null); else sc.addObject(obj, null); } if (!useWorldCoords && thisObjectInScene != null) { CoordinateSystem newCoords = cam.getCameraCoordinates(); newCoords.transformCoordinates(thisObjectInScene.getCoords().fromLocal()); cam.setCameraCoordinates(newCoords); } } else { sc = new Scene(); RGBColor background = new RGBColor(); background.setARGB(backgroundColor.getRGB()); sc.setEnvironmentColor(background); sc.addObject(new DirectionalLight(new RGBColor(1.0f, 1.0f, 1.0f), 0.8f), cam.getCameraCoordinates(), "", null); ObjectInfo obj = getController().getObject(); obj = obj.duplicate(obj.getObject().duplicate()); obj.getCoords().transformCoordinates(getDisplayCoordinates().fromLocal()); sc.addObject(obj, null); } rend.configurePreview(); Rectangle bounds = getBounds(); SceneCamera sceneCamera = new SceneCamera(); sceneCamera.setFieldOfView(Math.atan(0.5*bounds.height/(cam.getDistToScreen()*getScale()))*360.0/Math.PI); adjustCamera(isPerspective()); RenderListener listener = new RenderListener() { public void imageUpdated(Image image) { renderedImage = image; getCanvasDrawer().imageChanged(renderedImage); repaint(); } public void statusChanged(String status) { } public void imageComplete(ComplexImage image) { renderedImage = image.getImage(); getCanvasDrawer().imageChanged(renderedImage); repaint(); } public void renderingCanceled() { } }; rend.renderScene(sc, cam, listener, sceneCamera); } } public synchronized void updateImage() { if (renderMode == RENDER_RENDERED) { if (renderedImage != null && renderedImage.getWidth(null) > 0) drawImage(renderedImage, 0, 0); else viewChanged(false); drawBorder(); if (showAxes) drawCoordinateAxes(); return; } super.updateImage(); if (controller.getObject() == null) return; // Draw the rest of the objects in the scene. if (showScene && theScene != null) { Vec3 viewdir = getDisplayCoordinates().toLocal().timesDirection(theCamera.getViewToWorld().timesDirection(Vec3.vz())); for (int i = 0; i < theScene.getNumObjects(); i++) { ObjectInfo obj = theScene.getObject(i); if (!obj.isVisible() || obj == thisObjectInScene) continue; Mat4 objectTransform = obj.getCoords().fromLocal(); if (!useWorldCoords && thisObjectInScene != null) objectTransform = thisObjectInScene.getCoords().toLocal().times(objectTransform); theCamera.setObjectTransform(objectTransform); obj.getObject().renderObject(obj, this, thisObjectInScene.getCoords().fromLocal().timesDirection(viewdir)); } } // Draw the object being edited. theCamera.setObjectTransform(getDisplayCoordinates().fromLocal()); drawObject(); // Finish up. drawBorder(); if (showAxes) drawCoordinateAxes(); } protected abstract void drawObject(); /** Get the coordinate system in which the object is displayed. This will vary depending on whether the user has selected Local or Scene coordinates. */ public CoordinateSystem getDisplayCoordinates() { if (useWorldCoords && thisObjectInScene != null) return thisObjectInScene.getCoords(); else return controller.getObject().getCoords(); } /** Get whether freehand selection mode is currently in use. */ public boolean getFreehandSelection() { return freehandSelection; } /** Set whether to use freehand selection mode. */ public void setFreehandSelection(boolean freehand) { freehandSelection = freehand; } /** Get the scene this object is part of, or null if there is none. */ public Scene getScene() { return theScene; } /** Set the scene this object is part of. */ public void setScene(Scene sc, ObjectInfo thisObject) { theScene = sc; thisObjectInScene = thisObject; } /** Get whether the entire scene is visible. */ public boolean getSceneVisible() { return showScene; } /** Set whether the entire scene is visible. */ public void setSceneVisible(boolean visible) { showScene = visible; viewChanged(false); } /** Get whether to use world coordinates. */ public boolean getUseWorldCoords() { return useWorldCoords; } /** Set whether to use world coordinates. */ public void setUseWorldCoords(boolean use) { useWorldCoords = use; viewChanged(false); } /** Begin dragging a selection region. The variable square determines whether the region should be constrained to be square. */ public void beginDraggingSelection(Point p, boolean square) { draggingBox = true; clickPoint = p; squareBox = square; dragPoint = null; if (freehandSelection) selectBoundsPoints = new Vector<Point>(); } /** Finish dragging a selection region. */ public void endDraggingSelection() { if (!draggingBox || dragPoint == null) { selectBounds = null; return; } repaint(); // Construct the selection region. if (freehandSelection) selectBounds = createPolygonFromSelection(); else selectBounds = new Rectangle(Math.min(clickPoint.x, dragPoint.x), Math.min(clickPoint.y, dragPoint.y), Math.abs(dragPoint.x-clickPoint.x), Math.abs(dragPoint.y-clickPoint.y)); } /** Create a Polygon from the selection bounds. */ private Polygon createPolygonFromSelection() { int n = selectBoundsPoints.size(), x[] = new int [n], y[] = new int [n]; for (int i = 0; i < n; i++) { Point p = selectBoundsPoints.elementAt(i); x[i] = p.x; y[i] = p.y; } return new Polygon(x, y, n); } /** Determine whether the selection region contains the specified point. */ public boolean selectionRegionContains(Point p) { if (selectBounds instanceof Rectangle) return ((Rectangle) selectBounds).contains(p); if (selectBounds instanceof Polygon) return ((Polygon) selectBounds).contains(p); return false; } /** * Determine whether the selection region intersects the segment specified by the 2 points. * <p> The selection intersects the line if either:<ul> * <li> one of the points is inside the selection; * <li> both points are outside and the line formed by them intersects * any of the boundaries of the selection. * </ul> */ public boolean selectionRegionIntersects(Point p1, Point p2) { if (selectionRegionContains(p1) || selectionRegionContains(p2)) return true; if (selectBounds instanceof Rectangle) return ((Rectangle) selectBounds).intersectsLine(p1.x, p1.y, p2.x, p2.y); if (selectBounds instanceof Polygon) { // if any of the edges of the polygon intersect, return true final Polygon polygon = ((Polygon) selectBounds); final int[] xpoints = polygon.xpoints; final int[] ypoints = polygon.ypoints; final int npoints = polygon.npoints; int lastx = xpoints[npoints - 1]; int lasty = ypoints[npoints - 1]; int curx, cury; for (int i = 0; i < npoints; i++) { curx = xpoints[i]; cury = ypoints[i]; final boolean intersect = Line2D.linesIntersect( lastx, lasty, curx, cury, // polygon selection line p1.x, p1.y, p2.x, p2.y // tested line ); if (intersect) return true; lastx = curx; lasty = cury; } return false; } return false; } protected void mouseDragged(WidgetMouseEvent e) { moveToGrid(e); if (draggingBox && freehandSelection) { // Add this point to the region boundary and draw a line. dragPoint = e.getPoint(); selectBoundsPoints.addElement(dragPoint); drawDraggedShape(createPolygonFromSelection()); } else if (draggingBox) { // We are dragging a box, so erase and redraw it. if (dragPoint != null) drawDraggedShape(new Rectangle(Math.min(clickPoint.x, dragPoint.x), Math.min(clickPoint.y, dragPoint.y), Math.abs(dragPoint.x-clickPoint.x), Math.abs(dragPoint.y-clickPoint.y))); dragPoint = e.getPoint(); if (squareBox) { if (Math.abs(dragPoint.x-clickPoint.x) > Math.abs(dragPoint.y-clickPoint.y)) { if (dragPoint.y < clickPoint.y) dragPoint.y = clickPoint.y - Math.abs(dragPoint.x-clickPoint.x); else dragPoint.y = clickPoint.y + Math.abs(dragPoint.x-clickPoint.x); } else { if (dragPoint.x < clickPoint.x) dragPoint.x = clickPoint.x - Math.abs(dragPoint.y-clickPoint.y); else dragPoint.x = clickPoint.x + Math.abs(dragPoint.y-clickPoint.y); } } drawDraggedShape(new Rectangle(Math.min(clickPoint.x, dragPoint.x), Math.min(clickPoint.y, dragPoint.y), Math.abs(dragPoint.x-clickPoint.x), Math.abs(dragPoint.y-clickPoint.y))); } // Send the event to the current tool, if appropriate. if (sentClick) activeTool.mouseDragged(e, this); } public void previewObject() { Renderer rend = ArtOfIllusion.getPreferences().getObjectPreviewRenderer(); if (rend == null) return; adjustCamera(true); Scene sc; CoordinateSystem cameraCoords = theCamera.getCameraCoordinates(); if (showScene) { sc = theScene; if (!useWorldCoords && thisObjectInScene != null) { CoordinateSystem newCoords = cameraCoords.duplicate(); newCoords.transformCoordinates(thisObjectInScene.getCoords().fromLocal()); theCamera.setCameraCoordinates(newCoords); } } else { sc = new Scene(); sc.addObject(new DirectionalLight(new RGBColor(1.0f, 1.0f, 1.0f), 0.8f), theCamera.getCameraCoordinates(), "", null); ObjectInfo obj = getController().getObject(); obj = obj.duplicate(obj.getObject().duplicate()); obj.getCoords().transformCoordinates(getDisplayCoordinates().fromLocal()); sc.addObject(obj, null); } rend.configurePreview(); SceneCamera sceneCamera = new SceneCamera(); sceneCamera.setFieldOfView(Math.atan(0.5*getBounds().height/(theCamera.getDistToScreen()*getScale()))*360.0/Math.PI); ObjectInfo cameraInfo = new ObjectInfo(sceneCamera, theCamera.getCameraCoordinates(), ""); new RenderingDialog(UIUtilities.findFrame(this), rend, sc, theCamera, cameraInfo); theCamera.setCameraCoordinates(cameraCoords); adjustCamera(isPerspective()); } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.20996.03−692.869
Source linesThe number of non-empty source lines.481+192.4
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.759−7.138

Intercept 8.87 + feature contributions = -498.737 (log-odds).
Score = sigmoid(-498.737) = 0.

Score0.749

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.481−15.994
Indentation frequencyHow rapidly indentation changes from line to line.447+14.724
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.447−9.836
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.479.808+6.297
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.123.975−1.586
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.123.988+1.196
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.1−0.027

Intercept 0.07 + feature contributions = -5.156 (log-odds).
Score = sigmoid(-5.156) = 0.006.

Score0.265
Score250
Run 1

The code demonstrates reasonable organization with clear method separation and Javadoc comments, but has several readability issues. The class structure is logical with related methods grouped together, and most methods follow single-responsibility principles. However, methods like viewChanged and mouseDragged contain deeply nested conditional logic, particularly in the showScene rendering paths with multiple if statements and duplicated code blocks. The code is quite verbose and repetitive—the scene-building logic in viewChanged and previewObject is largely duplicated with minor variations, hindering maintainability. Many lines exceed comfortable reading length, especially in mouseDragged with long Rectangle constructor calls. Action granularity is inconsistent, with multiple operations occasionally condensed into single lines (e.g., variable declarations and calculations). The reading flow is generally natural but gets interrupted by complex nested conditions and repeated patterns. Naming is mostly clear, though abbreviations like 'sc' and 'rend' reduce clarity. Overall, the code is functional but would benefit from extraction of repeated logic into helper methods and reducing nesting depth for better readability.

Run 2

The code has clear structure with logical method organization and good Javadoc comments explaining intent. However, several methods like viewChanged() and previewObject() are quite long and contain complex nested logic (especially the scene setup sections). The estimateDepthRange() method shows good readability with clear variable names and sequential logic. Action granularity is generally one action per line, but some lines are long and densely packed with operations. The mouseDragged() method has readable structure but complex conditional logic for square box constraints. Overall the code is functional and somewhat maintainable but suffers from verbose methods and inconsistent formatting that impact readability.

Run 3

The code has clear method separation and Javadoc comments, but suffers from several readability issues. The viewChanged() method is excessively long (over 100 lines) with deeply nested conditionals (up to 4 levels), making it hard to follow. Complex mathematical expressions like `0.5*Math.sqrt(dx*dx+dy*dy+dz*dz)` lack explanatory variables. Methods like estimateDepthRange() have good structure with logical sections, but dense calculations reduce clarity. The event handler mouseDragged() contains multiple nested if/else blocks handling different selection modes, creating tangled logic. Variable names are generally meaningful, and the class structure follows logical organization. Some methods like selectionRegionIntersects() demonstrate good action granularity with one operation per line, but others combine multiple operations. The code would benefit from extracting helper methods for render setup and coordinate transformations.

Run 1

Code Structure: Clearly separated methods organize rendering, scene configuration, and selection handling, although viewChanged mixes several responsibilities. Nesting: Generally moderate, but mouseDragged has deeply nested square-selection logic and rendering paths contain multiple conditional levels. Clarity of intent: Descriptive method names, Javadoc, and useful section comments explain most behavior; abbreviated variables and dense coordinate transformations require extra effort. Code length: Mostly justified, but duplicated scene setup, depth calculations, and rectangle construction could be extracted into helpers. Action granularity: Most lines perform one action, though grouped field declarations, combined local declarations, and an inline conditional return reduce consistency. Reading flow: Consistent indentation, whitespace, and early returns support natural reading; long expressions, occasional formatting inconsistencies, and large methods interrupt it. Overall, readable and well documented, with complexity concentrated in rendering and drag handling.

Run 2

Code Structure: Methods separate rendering, scene configuration, and selection handling logically, although the class combines several responsibilities. Nesting: Generally moderate, but viewChanged and square-selection dragging contain several nested branches. Clarity of intent: Descriptive method names, documentation, and section comments explain most operations; abbreviated variables and dense coordinate transformations require extra interpretation. Code length: Mostly justified, though repeated scene setup, depth calculations, and rectangle construction could be extracted into helpers. Action granularity: Most lines perform one action, but grouped declarations, complex expressions, and an inline conditional return reduce consistency. Reading flow: Consistent formatting and clear method boundaries support navigation, while long rendering methods, repeated logic, and occasional inconsistent indentation interrupt the flow.

Run 3

Code Structure: Methods separate rendering, scene configuration, and selection handling logically, but larger methods combine several responsibilities and duplicate scene setup and rectangle calculations. Nesting: Most methods are shallow, though mouseDragged and viewChanged contain moderately deep branching. Clarity of intent: Descriptive method names, JavaDoc, and section comments explain behavior well; abbreviated variables and dense coordinate transformations require extra effort. Code length: Accessors are concise, but repeated rendering setup and selection geometry could be extracted into helpers. Action granularity: Most statements perform one action per line, with occasional combined declarations and inline conditionals reducing consistency. Reading flow: Consistent indentation, whitespace, and comments support a natural progression, while long expressions, inconsistent brace usage, and interleaved camera and scene mutations occasionally interrupt it.