Sample

Schnappinger/aoi/artofillusion.CreateVertexTool

Human rating uses the original dataset scale.

Human2.88
Lines302

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
13.0Δ 6.8
Scalabrino0.5510–1; higher is more readable
14.0Δ 5.8
Dorn0.0180–1; higher is more readable
23.1Δ 3.3
Mi0.480–1; higher is more readable
31.4Δ 11.6
LLOC185Logical lines; fewer is more readable
14.5Δ 5.3
DeepSeek V4 Pro140–20; mean of three runs
29.9Δ 10.1
GPT-6.1 Sol140–20; mean of three runs
16.2Δ 3.6
BTTF0.1550–1; higher is more readable
8.6Δ 11.2
Human2.881–4; original rating
19.8

Views

Source code

/* Copyright (C) 2003-2007 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.math.*; import artofillusion.object.*; import artofillusion.texture.*; import artofillusion.ui.*; import buoy.event.*; import java.awt.*; /** CreateVertexTool is an EditingTool used for adding vertices to triangle meshes. */ public class CreateVertexTool extends MeshEditingTool { private Point clickPoint; private Vec3 clickPos, constrainDir; private int target; private int vertexToMove; public CreateVertexTool(EditingWindow fr, MeshEditController controller) { super(fr, controller); initButton("createVertex"); } public void activate() { super.activate(); setHelpText(); } /** * Set the help text based on the current selection mode. */ private void setHelpText() { int mode = controller.getSelectionMode(); if (mode == MeshEditController.POINT_MODE) theWindow.setHelpText(Translate.text("createVertexTool.helpText.point")); else if (mode == MeshEditController.EDGE_MODE) theWindow.setHelpText(Translate.text("createVertexTool.helpText.edge")); else theWindow.setHelpText(Translate.text("createVertexTool.helpText.face")); } public int whichClicks() { return ALL_CLICKS; } public String getToolTipText() { return Translate.text("createVertexTool.tipText"); } public void mousePressed(WidgetMouseEvent e, ViewerCanvas view) { TriMeshViewer tmv = (TriMeshViewer) view; TriangleMesh mesh = (TriangleMesh) controller.getObject().getObject(); MeshVertex vert[] = mesh.getVertices(); int mode = controller.getSelectionMode(); Vec3 uvw = new Vec3(); clickPoint = e.getPoint(); target = tmv.findClickTarget(clickPoint, uvw); if (target == -1) return; theWindow.setUndoRecord(new UndoRecord(theWindow, false, UndoRecord.COPY_OBJECT, new Object [] {mesh, mesh.duplicate()})); if (mode == MeshEditController.POINT_MODE) { // Create a new vertex if this is a boundary vertex. Otherwise, just move it. constrainDir = mesh.getNormals()[target]; if (createBoundaryVertex(mesh)) { vertexToMove = mesh.getVertices().length-1; controller.setMesh(mesh); controller.objectChanged(); theWindow.updateImage(); theWindow.updateMenus(); } else vertexToMove = target; clickPos = mesh.getVertices()[vertexToMove].r; } else { boolean[] split; TriangleMesh newmesh = null; if (mode == MeshEditController.EDGE_MODE) { // Subdivide an edge. TriangleMesh.Edge edge[] = mesh.getEdges(); Vec3 v1 = vert[edge[target].v1].r; Vec3 v2 = vert[edge[target].v2].r; clickPos = v1.times(uvw.x).plus(v2.times(uvw.y)); split = new boolean[edge.length]; split[target] = true; newmesh = TriangleMesh.subdivideLinear(mesh, split); constrainDir = v1.minus(v2); constrainDir.normalize(); } else if (mode == MeshEditController.FACE_MODE) { // Subdivide a face. TriangleMesh.Face face[] = mesh.getFaces(); Vec3 v1 = vert[face[target].v1].r; Vec3 v2 = vert[face[target].v2].r; Vec3 v3 = vert[face[target].v3].r; clickPos = v1.times(uvw.x).plus(v2.times(uvw.y)).plus(v3.times(uvw.z)); split = new boolean[face.length]; split[target] = true; newmesh = TriangleMesh.subdivideFaces(mesh, split); constrainDir = v1.minus(v2).cross(v3.minus(v2)); constrainDir.normalize(); } vertexToMove = newmesh.getVertices().length-1; newmesh.getVertices()[vertexToMove].r.set(clickPos); mesh.copyObject(newmesh); controller.setMesh(mesh); controller.objectChanged(); theWindow.updateImage(); theWindow.updateMenus(); } } public void mouseDragged(WidgetMouseEvent e, ViewerCanvas view) { if (target == -1) return; TriMeshViewer tmv = (TriMeshViewer) view; TriangleMesh mesh = (TriangleMesh) controller.getObject().getObject(); Point dragPoint = e.getPoint(); Vec3 v[], drag; int dx, dy; dx = dragPoint.x - clickPoint.x; dy = dragPoint.y - clickPoint.y; drag = findDragVector(dx, dy, tmv, e.isShiftDown()); v = findDraggedPositions(mesh, drag); mesh.setVertexPositions(v); controller.objectChanged(); theWindow.updateImage(); } public void mouseReleased(WidgetMouseEvent e, ViewerCanvas view) { if (target == -1) return; TriMeshViewer tmv = (TriMeshViewer) view; Object3D meshobj = controller.getObject().getObject(); TriangleMesh mesh = (TriangleMesh) meshobj; Point dragPoint = e.getPoint(); int dx, dy; Vec3 v[], drag; dx = dragPoint.x - clickPoint.x; dy = dragPoint.y - clickPoint.y; drag = findDragVector(dx, dy, tmv, e.isShiftDown()); v = findDraggedPositions(mesh, drag); mesh.setVertexPositions(v); controller.objectChanged(); theWindow.updateImage(); setHelpText(); } /** * Return the new positions of every vertex. */ private Vec3 [] findDraggedPositions(TriangleMesh mesh, Vec3 drag) { MeshVertex vert[] = mesh.getVertices(); Vec3 pos[] = new Vec3 [vert.length]; for (int i = 0; i < pos.length; i++) pos[i] = vert[i].r; pos[vertexToMove] = clickPos.plus(drag); return pos; } /** * Find the displacement vector for the vertex being dragged. */ private Vec3 findDragVector(int dx, int dy, TriMeshViewer view, boolean constrain) { Vec3 drag = view.getCamera().findDragVector(clickPos, dx, dy); if (constrain) { if (controller.getSelectionMode() == MeshEditController.EDGE_MODE) drag = constrainDir.times(drag.dot(constrainDir)); else drag.subtract(constrainDir.times(drag.dot(constrainDir))); } return drag; } /** * Try to create a new vertex when a boundary vertex is dragged. Returns true if a new vertex was * created, false otherwise. */ private boolean createBoundaryVertex(TriangleMesh mesh) { TriangleMesh.Vertex vert[] = (TriangleMesh.Vertex []) mesh.getVertices(); TriangleMesh.Vertex v = (TriangleMesh.Vertex) vert[target]; TriangleMesh.Edge edge[] = mesh.getEdges(); TriangleMesh.Face face[] = mesh.getFaces(); int vertEdge[] = v.getEdges(); if (edge[vertEdge[0]].f2 != -1) return false; theWindow.setUndoRecord(new UndoRecord(theWindow, false, UndoRecord.COPY_OBJECT, new Object [] {mesh, mesh.duplicate()})); // Create a new vertex and two new faces. TriangleMesh.Vertex newvert[] = new TriangleMesh.Vertex [vert.length+1]; int newface[][] = new int [face.length+2][]; for (int i = 0; i < vert.length; i++) newvert[i] = vert[i]; newvert[vert.length] = mesh.new Vertex(v); for (int i = 0; i < face.length; i++) newface[i] = new int [] {face[i].v1, face[i].v2, face[i].v3}; TriangleMesh.Edge e = edge[vertEdge[0]]; TriangleMesh.Face f = face[e.f1]; int oldFace1 = e.f1; if ((f.v1 == e.v1 && f.v2 == e.v2) || (f.v2 == e.v1 && f.v3 == e.v2) || (f.v3 == e.v1 && f.v1 == e.v2)) newface[face.length] = new int [] {e.v2, e.v1, vert.length}; else newface[face.length] = new int [] {e.v1, e.v2, vert.length}; e = edge[vertEdge[vertEdge.length-1]]; f = face[e.f1]; int oldFace2 = e.f1; if ((f.v1 == e.v1 && f.v2 == e.v2) || (f.v2 == e.v1 && f.v3 == e.v2) || (f.v3 == e.v1 && f.v1 == e.v2)) newface[face.length+1] = new int [] {e.v2, e.v1, vert.length}; else newface[face.length+1] = new int [] {e.v1, e.v2, vert.length}; mesh.setShape(newvert, newface); // Copy over the edge smoothness values. TriangleMesh.Edge newedge[] = mesh.getEdges(); for (int i = 0; i < newedge.length; i++) for (int j = 0; j < edge.length; j++) if ((newedge[i].v1 == edge[j].v1 && newedge[i].v2 == edge[j].v2) || (newedge[i].v1 == edge[j].v2 && newedge[i].v2 == edge[j].v1)) newedge[i].smoothness = edge[j].smoothness; // Update the parameter values. TextureParameter param[] = mesh.getParameters(); ParameterValue paramValue[] = mesh.getParameterValues(); for (int i = 0; i < paramValue.length; i++) { if (paramValue[i] instanceof VertexParameterValue) { double val[] = ((VertexParameterValue) paramValue[i]).getValue(); double newval[] = new double [newvert.length]; System.arraycopy(val, 0, newval, 0, val.length); newval[val.length] = val[target]; ((VertexParameterValue) paramValue[i]).setValue(newval); } if (paramValue[i] instanceof FaceParameterValue) { double val[] = ((FaceParameterValue) paramValue[i]).getValue(); double newval[] = new double [newface.length]; System.arraycopy(val, 0, newval, 0, val.length); newval[val.length] = val[oldFace1]; newval[val.length+1] = val[oldFace2]; ((FaceParameterValue) paramValue[i]).setValue(newval); } if (paramValue[i] instanceof FaceVertexParameterValue) { FaceVertexParameterValue fvpv = (FaceVertexParameterValue) paramValue[i]; double newval[][] = new double [newface.length][3]; for (int index = 0; index < newval.length; index++) { newval[index][0] = fvpv.getValue(index, 0); newval[index][1] = fvpv.getValue(index, 1); newval[index][2] = fvpv.getValue(index, 2); } newval[face.length][0] = newval[face.length][1] = newval[face.length][2] = param[i].defaultVal; newval[face.length+1][0] = newval[face.length+1][1] = newval[face.length+1][2] = param[i].defaultVal; fvpv.setValue(newval); } } return true; } }

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.17335.217−572.062
Source linesThe number of non-empty source lines.302+120.8
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.861−7.292

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

Score0.551

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.302−9.657
Indentation frequencyHow rapidly indentation changes from line to line.278+8.879
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.279−5.981
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.300.899+3.796
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.136.98−2.137
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.136.977+1.406
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.133−0.35

Intercept 0.07 + feature contributions = -3.975 (log-odds).
Score = sigmoid(-3.975) = 0.018.

Score0.48
Score185
Run 1

The code is generally well-structured with clear methods and comments explaining complex operations. However, it has several readability issues: mixed action granularity (some lines perform multiple operations), deeply nested conditional blocks in createBoundaryVertex, and inconsistent formatting. The mousePressed method is quite long with complex branching logic. Variable declarations are grouped at method starts rather than near usage. The copyright header and comments are good. Method names clearly indicate intent. The parameter update logic in createBoundaryVertex is complex and could benefit from helper methods. Overall, readable for experienced Java developers familiar with 3D mesh operations, but the dense sections reduce clarity.

Run 2

The code is moderately readable. It has clear structure with logical method separation and good Javadoc comments explaining intent. However, readability suffers in several areas: mousePressed is long and contains multiple branches with different logic paths for point, edge, and face modes. createBoundaryVertex is particularly complex with deep nesting, multiple nested loops, and unclear variable names (e.g., 'f', 'e', 'v1', 'v2'). The repeated triangle orientation checks are verbose and hard to follow. Magic numbers (e.g., using -1 as a sentinel) and inconsistent naming reduce clarity. The method does one logical action (creating a vertex) but mixes concerns: geometry manipulation, parameter updating, and edge smoothness copying. There is some duplication between mouseDragged and mouseReleased. Overall, the code is structured but dense, requiring domain knowledge to fully understand.

Run 3

The code is moderately readable. Structure is logical, with clear method separation and comments for major sections. However, several methods are quite lengthy (e.g., mousePressed, createBoundaryVertex), mixing multiple actions per line and obscuring intent. Nesting is acceptable in most places but becomes deeper in createBoundaryVertex with nested loops and conditionals. Clarity of intent is mixed: some method names are descriptive (findDragVector, createBoundaryVertex), but the main mousePressed contains many operations without explanatory comments. Code length is only slightly verbose, mostly driven by domain complexity. Action granularity is poor in spots—multiple statements on one line (e.g., newval[face.length][0] = newval[face.length][1] = ...). Reading flow is generally natural but interrupted by large methods and occasional dense expressions. Overall, readable enough for experienced developers but could benefit from refactoring into smaller helper methods.

Run 1

Code Structure: Event handlers and focused helper methods provide logical organization, but createBoundaryVertex combines topology changes, smoothness copying, and parameter updates. Nesting: Mostly moderate, with deeper loop/conditional nesting in boundary processing; early returns help. Clarity of intent: Descriptive method names and section comments explain the purpose, while abbreviated variables, implicit mesh assumptions, and dense orientation checks require extra interpretation. Code length: Reasonable for the functionality, but duplicated drag handling, refresh calls, and face-orientation logic could be extracted. Action granularity: Most statements perform one action per line; chained assignments and compound expressions are exceptions. Reading flow: Consistent formatting and the press-drag-release sequence are easy to follow, though the long boundary helper and repeated casts interrupt the flow.

Run 2

Code Structure: Event handlers and helper methods provide logical organization, but mousePressed and createBoundaryVertex combine several responsibilities. Nesting: Generally moderate, with early returns improving flow; nested loops and parameter-update branches add complexity. Clarity of intent: Descriptive method names, documentation, and section comments explain the purpose, while abbreviated variables and dense mesh-index expressions require careful interpretation. Code length: Mostly justified by the operations, but repeated drag handling, UI updates, face-orientation checks, and parameter-copy logic could be extracted. Action granularity: Most lines perform one action, although chained assignments, compound expressions, and grouped declarations reduce clarity. Reading flow: The press-drag-release sequence and consistent formatting are natural to follow, but long methods, omitted braces, and detailed topology manipulation interrupt the otherwise clear progression.

Run 3

Code Structure: Event handlers and helper methods provide logical organization, but mousePressed and createBoundaryVertex combine several responsibilities. Nesting: Generally moderate, with deeper loops and conditionals in boundary creation and parameter updates. Clarity of intent: Descriptive method names, documentation, and section comments explain the tool's purpose; abbreviated variables and dense mesh-index expressions obscure implementation details. Code length: Reasonable for the functionality, but repeated drag handling, UI updates, face-orientation checks, and parameter-copy logic could be extracted. Action granularity: Most lines perform one action, although chained assignments and long expressions reduce clarity. Reading flow: The press-drag-release sequence and sequential boundary-update sections are natural, but omitted braces, shared mutable state, and lengthy topology manipulation require careful tracking.