diff --git a/backend/src/main/java/com/nestapp/RestController.kt b/backend/src/main/java/com/nestapp/RestController.kt index 5d3cfb8..08909db 100644 --- a/backend/src/main/java/com/nestapp/RestController.kt +++ b/backend/src/main/java/com/nestapp/RestController.kt @@ -7,6 +7,7 @@ import com.nestapp.nest.nestRestApi import com.nestapp.project.ProjectMaker import com.nestapp.project.projectsRestController import io.ktor.client.HttpClient +import io.ktor.client.plugins.HttpTimeout import io.ktor.http.HttpMethod import io.ktor.http.HttpStatusCode import io.ktor.serialization.kotlinx.json.json @@ -24,6 +25,7 @@ import io.ktor.server.routing.get import io.ktor.server.routing.route import io.ktor.server.routing.routing import kotlinx.serialization.json.Json +import java.util.concurrent.TimeUnit fun createHttpClient(): HttpClient { return HttpClient { @@ -35,6 +37,11 @@ fun createHttpClient(): HttpClient { } ) } + install(HttpTimeout) { + requestTimeoutMillis = TimeUnit.MINUTES.toMillis(3) + connectTimeoutMillis = TimeUnit.MINUTES.toMillis(1) + socketTimeoutMillis = TimeUnit.MINUTES.toMillis(3) + } } } diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/Arc.kt b/backend/src/main/java/com/nestapp/files/dxf/reader/Arc.kt index 24cd0c0..59fcaa3 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/reader/Arc.kt +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/Arc.kt @@ -38,17 +38,6 @@ internal class Arc(type: String?) : Entity(type!!), AutoPop { path.append(arc, true) } - override fun translate(x: Double, y: Double): Entity { - val translatedArc = Arc(type) - translatedArc.cx = this.cx + x - translatedArc.cy = this.cy + y - translatedArc.radius = this.radius - translatedArc.startAngle = this.startAngle - translatedArc.endAngle = this.endAngle - translatedArc.close() - return translatedArc - } - override fun toWriterEntity(placement: Placement): DXFEntity { val center = RealPoint(cx, cy) diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/Circle.kt b/backend/src/main/java/com/nestapp/files/dxf/reader/Circle.kt index c4c32d9..72edb83 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/reader/Circle.kt +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/Circle.kt @@ -43,17 +43,4 @@ internal class Circle(type: String?) : Entity(type!!), AutoPop { radius ) } - - override fun translate(x: Double, y: Double): Entity { - val newX = cx + x - val newY = cy + y - val originRadius = radius - - return Circle(type).apply { - cx = newX - cy = newY - radius = originRadius - close() - } - } } diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/DXFReader.java b/backend/src/main/java/com/nestapp/files/dxf/reader/DXFReader.java index 214b84f..c048396 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/reader/DXFReader.java +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/DXFReader.java @@ -335,45 +335,6 @@ class Hatch extends Entity implements AutoPop { } } - class Insert extends Entity implements AutoPop { - private String blockHandle, blockName; - private double ix, iy, xScale = 1.0, yScale = 1.0, zScale = 1.0, rotation; - - Insert(String type) { - super(type); - } - - @Override - public void addParam(int gCode, String value) { - switch (gCode) { - case 2: // Name of Block to insert - blockName = value; - break; - case 5: // Handle of Block to insert - blockHandle = value; - break; - case 10: // Insertion X - ix = Double.parseDouble(value); - break; - case 20: // Insertion Y - iy = Double.parseDouble(value); - break; - case 41: // X scaling - xScale = Double.parseDouble(value); - break; - case 42: // Y scaling - yScale = Double.parseDouble(value); - break; - case 43: // Z Scaling (affects x coord and rotation) - zScale = Double.parseDouble(value); - break; - case 50: // Rotation angle (degrees) - rotation = Double.parseDouble(value); - break; - } - } - } - /* * Note: code for "DIMENSION" is incomplete */ @@ -478,66 +439,6 @@ public void close() { } } - class Spline extends Entity implements AutoPop { - Path2D.Double path = new Path2D.Double(); - List cPoints = new ArrayList<>(); - private double xCp, yCp; - private boolean hasXcp, hasYcp; - private boolean closed; - private int numCPs; - private int degree; - - Spline(String type) { - super(type); - } - - @Override - public void addParam(int gCode, String value) { - switch (gCode) { - case 10: // Control Point X - xCp = Double.parseDouble(value); - hasXcp = true; - break; - case 20: // Control Point Y - yCp = Double.parseDouble(value); - hasYcp = true; - break; - case 70: // Flags (bitfield) - // bit 0: Closed spline, bit 1: Periodic spline, bit 2: Rational spline, bit 3: Planar, bit 4: Linear (planar bit is also set) - // Examples: - // 10 = Closed, Periodic, Planar Spline - // - int flags = Integer.parseInt(value); - closed = (flags & 0x01) != 0; - break; - case 71: // Degree of the spline curve - degree = Integer.parseInt(value); - break; - case 73: // Number of Control Points - numCPs = Integer.parseInt(value); - break; - } - if (hasXcp && hasYcp) { - cPoints.add(new Point2D.Double(xCp, yCp)); - hasXcp = hasYcp = false; - if (cPoints.size() == numCPs) { - if (degree == 3) { - Point2D.Double[] points = cPoints.toArray(new Point2D.Double[0]); - path.moveTo(points[0].x, points[0].y); - for (int ii = 1; ii < points.length; ii += 3) { - path.curveTo(points[ii].x, points[ii].y, points[ii + 1].x, points[ii + 1].y, points[ii + 2].x, points[ii + 2].y); - } - } - } else if (degree == 2) { - Point2D.Double[] points = cPoints.toArray(new Point2D.Double[0]); - path.moveTo(points[0].x, points[0].y); - for (int ii = 1; ii < points.length; ii += 2) { - path.quadTo(points[ii].x, points[ii].y, points[ii + 1].x, points[ii + 1].y); - } - } - } - } - } private void push() { stack.add(cEntity); @@ -585,13 +486,6 @@ private void debugPrint(String value) { System.out.println(value); } - public void parseFile(File file) throws IOException { - stack = new ArrayList<>(); - cEntity = null; - Scanner lines = new Scanner(Files.newInputStream(file.toPath())); - parseFile(lines); - } - public void parseFile(InputStream stream) { stack = new ArrayList<>(); cEntity = null; diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/Entity.kt b/backend/src/main/java/com/nestapp/files/dxf/reader/Entity.kt index 0be3141..23e3204 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/reader/Entity.kt +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/Entity.kt @@ -26,8 +26,4 @@ open class Entity internal constructor(@JvmField var type: String) { open fun toWriterEntity(placement: Placement = NotMovedPlacement): DXFEntity { throw UnsupportedOperationException("Not implemented in ${this.javaClass.simpleName}") } - - open fun translate(x: Double, y: Double): Entity { - throw UnsupportedOperationException("Not implemented in ${this.javaClass.simpleName}") - } } diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/Insert.java b/backend/src/main/java/com/nestapp/files/dxf/reader/Insert.java new file mode 100644 index 0000000..512b297 --- /dev/null +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/Insert.java @@ -0,0 +1,40 @@ +package com.nestapp.files.dxf.reader; + +public class Insert extends Entity implements AutoPop { + private String blockHandle, blockName; + private double ix, iy, xScale = 1.0, yScale = 1.0, zScale = 1.0, rotation; + + Insert(String type) { + super(type); + } + + @Override + public void addParam(int gCode, String value) { + switch (gCode) { + case 2: // Name of Block to insert + blockName = value; + break; + case 5: // Handle of Block to insert + blockHandle = value; + break; + case 10: // Insertion X + ix = Double.parseDouble(value); + break; + case 20: // Insertion Y + iy = Double.parseDouble(value); + break; + case 41: // X scaling + xScale = Double.parseDouble(value); + break; + case 42: // Y scaling + yScale = Double.parseDouble(value); + break; + case 43: // Z Scaling (affects x coord and rotation) + zScale = Double.parseDouble(value); + break; + case 50: // Rotation angle (degrees) + rotation = Double.parseDouble(value); + break; + } + } +} diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/Line.kt b/backend/src/main/java/com/nestapp/files/dxf/reader/Line.kt index a2bfc2d..7cea53b 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/reader/Line.kt +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/Line.kt @@ -46,28 +46,4 @@ class Line internal constructor(type: String) : Entity(type), AutoPop { return DXFLine(start.transform(placement), end.transform(placement)) } - - override fun translate(x: Double, y: Double): Entity { - val originStartX = xStart - val originStartY = yStart - val originEndX = xEnd - val originEndY = yEnd - - return Line(type).apply { - this.xStart = originStartX + x - this.yStart = originStartY + y - this.xEnd = originEndX + x - this.yEnd = originEndY + y - this.close() - } - } - - override fun toString(): String { - return "Line{" + - "xStart=" + xStart + - ", yStart=" + yStart + - ", xEnd=" + xEnd + - ", yEnd=" + yEnd + - '}' - } } diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/LwPolyline.kt b/backend/src/main/java/com/nestapp/files/dxf/reader/LwPolyline.kt index 739b05d..35f026e 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/reader/LwPolyline.kt +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/LwPolyline.kt @@ -138,16 +138,6 @@ class LwPolyline internal constructor(type: String) : Entity(type), AutoPop { closed = true ) } - - override fun translate(x: Double, y: Double): Entity { - return LwPolyline(type).also { - it.segments = - segments.map { segment -> LSegment(dx = segment.dx + x, dy = segment.dy + y, bulge = segment.bulge) } - .toMutableList() - it.close = close - it.close() - } - } } diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/Polyline.kt b/backend/src/main/java/com/nestapp/files/dxf/reader/Polyline.kt index a95c7c8..4aba950 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/reader/Polyline.kt +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/Polyline.kt @@ -69,9 +69,7 @@ internal class Polyline(type: String?) : Entity(type!!) { } override fun isClose(): Boolean { - return points.isNotEmpty() && points.first().let { firstPoint -> - points.last().let { lastPoint -> firstPoint.xx == lastPoint.xx && firstPoint.yy == lastPoint.yy } - } + return close } override fun toWriterEntity(placement: Placement): DXFEntity { @@ -84,25 +82,6 @@ internal class Polyline(type: String?) : Entity(type!!) { ) } - override fun translate(x: Double, y: Double): Entity { - return Polyline(type).also { - it.points = points.map { vertex -> - val newVertex = Vertex(type) - newVertex.xx = vertex.xx + x - newVertex.yy = vertex.yy + y - newVertex.bulge = vertex.bulge - newVertex - }.toMutableList() - it.close = close - it.firstX = firstX + x - it.firstY = firstY + y - it.lastX = lastX + x - it.lastY = lastY + y - it.firstPoint = firstPoint - it.close() - } - } - /** * See: http://darrenirvine.blogspot.com/2015/08/polylines-radius-bulge-turnaround.html * diff --git a/backend/src/main/java/com/nestapp/files/dxf/reader/Spline.kt b/backend/src/main/java/com/nestapp/files/dxf/reader/Spline.kt new file mode 100644 index 0000000..b19ec7a --- /dev/null +++ b/backend/src/main/java/com/nestapp/files/dxf/reader/Spline.kt @@ -0,0 +1,127 @@ +package com.nestapp.files.dxf.reader + +import com.nestapp.files.dxf.common.RealPoint +import com.nestapp.files.dxf.writter.parts.DXFEntity +import com.nestapp.files.dxf.writter.parts.DXFSpline +import com.nestapp.nest.Placement +import java.awt.geom.Path2D +import java.awt.geom.Point2D + +internal class Spline(type: String?) : Entity(type!!), AutoPop { + private var path: Path2D.Double = Path2D.Double() + private var cPoints: MutableList = ArrayList() + private var xCp = 0.0 + private var yCp = 0.0 + private var hasXcp = false + private var hasYcp = false + private var closed = false + private var numCPs = 0 + private var degree = 0 + private var numKnots = 0 + private val knots: MutableList = mutableListOf() + + override fun addParam(gCode: Int, value: String) { + when (gCode) { + 10 -> { + xCp = value.toDouble() + hasXcp = true + } + + 20 -> { + yCp = value.toDouble() + hasYcp = true + } + + 40 -> { + // Handle knots (if needed) + knots.add(value.toDouble()) + } + + /*70 -> { + val flags = value.toInt() + closed = (flags and 0x01) != 0 + // Additional flag handling if needed (e.g., periodic splines) + periodic = (flags and 0x02) != 0 + }*/ + + 71 -> degree = value.toInt() + + 72 -> numKnots = value.toInt() + + 73 -> numCPs = value.toInt() + + /*74 -> { + // Handle if spline is periodic + periodic = value.toInt() == 1 + }*/ + } + + // Check if control point is fully defined + if (hasXcp && hasYcp) { + cPoints.add(Point2D.Double(xCp, yCp)) + hasXcp = false + hasYcp = false + + // Handle when enough control points are gathered + if (cPoints.size == numCPs) { + processControlPoints() + } + } + } + + // Helper function to process control points based on degree + private fun processControlPoints() { + if (degree == 3) { + val points = cPoints.toTypedArray() + path.moveTo(points[0].x, points[0].y) + var ii = 1 + while (ii < points.size) { + path.curveTo( + points[ii].x, points[ii].y, + points[ii + 1].x, points[ii + 1].y, + points[ii + 2].x, points[ii + 2].y + ) + ii += 3 + } + } else if (degree == 2) { + val points = cPoints.toTypedArray() + path.moveTo(points[0].x, points[0].y) + var ii = 1 + while (ii < points.size) { + path.quadTo( + points[ii].x, points[ii].y, + points[ii + 1].x, points[ii + 1].y + ) + ii += 2 + } + } + } + + override fun toWriterEntity(placement: Placement): DXFEntity { + // Convert the control points from the Spline class to the format needed for DXFSpline + val controlPoints = mutableListOf() + for (point in cPoints) { + val realPoint = RealPoint(point.x, point.y) + val resultPoint = realPoint.transform(placement) + controlPoints.add(resultPoint.x) + controlPoints.add(resultPoint.y) + } + + // Ensure the knots list is correctly sized based on the degree and number of control points + val knotsArray = knots.toDoubleArray() + + // Create the DXFSpline object + val dxfSpline = DXFSpline(degree, controlPoints.toDoubleArray(), knotsArray) + + return dxfSpline + } + + + override fun isClose(): Boolean { + return closed + } + + override fun toPath2D(): Path2D.Double { + return path + } +} diff --git a/backend/src/main/java/com/nestapp/files/dxf/writter/parts/DXFSpline.java b/backend/src/main/java/com/nestapp/files/dxf/writter/parts/DXFSpline.java index ba3b98b..b7a4df5 100644 --- a/backend/src/main/java/com/nestapp/files/dxf/writter/parts/DXFSpline.java +++ b/backend/src/main/java/com/nestapp/files/dxf/writter/parts/DXFSpline.java @@ -31,55 +31,44 @@ import java.util.Vector; - /** * Class representing a general B-spline * * @author jsevy - * */ -public class DXFSpline extends DXFEntity -{ +public class DXFSpline extends DXFEntity { private int degree; private Vector expandedControlPoints; private double[] knots; private boolean closed; - private Color color; - private BasicStroke stroke; /** * Create a spline of specified degree for the specified control points, using uniform knot vector. * - * @param degree Degree of the piecewise-polynomial spline segments - * @param controlPoints Locations and weights of the control points for the spline - * @param throughEndpoints If true, the spline will be forced to pass through the endpoints by setting the end - * control point multiplicities to degree + 1 - * @param graphics The graphics object specifying parameters for this entity (color, thickness) + * @param degree Degree of the piecewise-polynomial spline segments + * @param controlPoints Locations and weights of the control points for the spline + * @param throughEndpoints If true, the spline will be forced to pass through the endpoints by setting the end + * control point multiplicities to degree + 1 */ - public DXFSpline(int degree, Vector controlPoints, boolean throughEndpoints, Graphics2D graphics) - { + /*public DXFSpline(int degree, Vector controlPoints, boolean throughEndpoints) { // if pass through endpoints, set multiplicities of first and last control points to degree + 1 - if (throughEndpoints) - { - controlPoints.elementAt(0).multiplicity = degree + 1; - controlPoints.elementAt(controlPoints.size()-1).multiplicity = degree + 1; + if (throughEndpoints) { + controlPoints.elementAt(0).multiplicity = degree + 1; + controlPoints.elementAt(controlPoints.size() - 1).multiplicity = degree + 1; } - this.degree = degree; + this.degree = degree; createExpandedPointVector(controlPoints); this.closed = false; - this.color = graphics.getColor(); - this.stroke = (BasicStroke)graphics.getStroke(); // here we use evenly spaced knots, one per expanded control point; have extras at end to keep AutoCAD happy... knots = new double[expandedControlPoints.size() + degree + 1]; - for (int i = 0; i < knots.length; i++) - { + for (int i = 0; i < knots.length; i++) { knots[i] = i; } - } + }*/ /** @@ -88,21 +77,16 @@ public DXFSpline(int degree, Vector controlPoints, boolean t * @param degree Degree of the piecewise-polynomial spline segments * @param controlPoints Locations of the control points for the spline * @param knots The knot sequence; length must be controlPoints.size() + degree + 1 - * @param graphics The graphics object specifying parameters for this entity (color, thickness) */ - public DXFSpline(int degree, double[] controlPoints, double[] knots, Graphics2D graphics) - { + public DXFSpline(int degree, double[] controlPoints, double[] knots) { this.degree = degree; - this.closed = false; - this.color = graphics.getColor(); - this.stroke = (BasicStroke)graphics.getStroke(); + this.closed = true; // populate expanded control point vector - expandedControlPoints = new Vector(); - for (int i = 0; i < controlPoints.length/2; i++) - { - RealPoint controlPoint = new RealPoint(controlPoints[2*i], controlPoints[2*i+1]); + expandedControlPoints = new Vector<>(); + for (int i = 0; i < controlPoints.length / 2; i++) { + RealPoint controlPoint = new RealPoint(controlPoints[2 * i], controlPoints[2 * i + 1]); expandedControlPoints.add(controlPoint); } @@ -112,12 +96,10 @@ public DXFSpline(int degree, double[] controlPoints, double[] knots, Graphics2D } - /** * Implementation of DXFObject interface method; creates DXF text representing the spline. */ - public String toDXFString() - { + public String toDXFString() { String result = "0\nSPLINE\n"; // print out handle and superclass marker(s) @@ -136,8 +118,7 @@ public String toDXFString() result += "73\n" + expandedControlPoints.size() + "\n"; // indicate if closed - if (closed) - { + if (closed) { result += "70\n1\n"; } @@ -145,32 +126,23 @@ public String toDXFString() // knots are augmented at end with n+1 points to make AutoCAD happy // knots first (since there are more of them than control points) - for (int i = 0; i < expandedControlPoints.size() + degree + 1; i++) - { - result += "40\n" + setPrecision(knots[i]) + "\n"; + for (int i = 0; i < expandedControlPoints.size() + degree + 1; i++) { + result += "40\n" + setPrecision(knots[i]) + "\n"; } // now control points and weights - for (int i = 0; i < expandedControlPoints.size(); i++) - { + for (int i = 0; i < expandedControlPoints.size(); i++) { RealPoint point = expandedControlPoints.elementAt(i); result += "10\n" + setPrecision(point.x) + "\n"; result += "20\n" + setPrecision(point.y) + "\n"; result += "41\n1\n"; // all weights 1; multiplicities already accounted for } - // add thickness; specified in Java in pixels at 72 pixels/inch; needs to be in 1/100 of mm for DXF, and restricted range of values - result += "370\n" + getDXFLineWeight(stroke.getLineWidth()) + "\n"; - - // add color number - result += "62\n" + DXFColor.getClosestDXFColor(color.getRGB()) + "\n"; - return result; } - public String getDXFHatchInfo() - { + public String getDXFHatchInfo() { // spline String result = "72\n" + "4" + "\n"; @@ -190,14 +162,12 @@ public String getDXFHatchInfo() result += "96\n" + expandedControlPoints.size() + "\n"; // knots first (since there are more of them than control points) - for (int i = 0; i < expandedControlPoints.size() + degree + 1; i++) - { + for (int i = 0; i < expandedControlPoints.size() + degree + 1; i++) { result += "40\n" + setPrecision(knots[i]) + "\n"; } // now control points and weights - for (int i = 0; i < expandedControlPoints.size(); i++) - { + for (int i = 0; i < expandedControlPoints.size(); i++) { RealPoint point = expandedControlPoints.elementAt(i); result += "10\n" + setPrecision(point.x) + "\n"; result += "20\n" + setPrecision(point.y) + "\n"; @@ -213,27 +183,23 @@ public String getDXFHatchInfo() * Create vector of control points with points multiply represented according to their multiplicities, * and appropriate multiplicity at endpoints to pass through these. */ - private void createExpandedPointVector(Vector controlPoints) - { + private void createExpandedPointVector(Vector controlPoints) { - int index = 0; + int index = 0; expandedControlPoints = new Vector(); - if (controlPoints.size() != 0) - { + if (controlPoints.size() != 0) { - for (int j = 0; j < controlPoints.size(); j++) - { - SplineControlPoint controlPoint = controlPoints.elementAt(j); - controlPoint.expandedIndex = index; + for (int j = 0; j < controlPoints.size(); j++) { + SplineControlPoint controlPoint = controlPoints.elementAt(j); + controlPoint.expandedIndex = index; - for (int i = 0; i < controlPoint.multiplicity; i++) - { - expandedControlPoints.add(new RealPoint(controlPoint.x, controlPoint.y)); - index++; - } - } + for (int i = 0; i < controlPoint.multiplicity; i++) { + expandedControlPoints.add(new RealPoint(controlPoint.x, controlPoint.y)); + index++; + } + } } } } diff --git a/backend/src/main/java/com/nestapp/mongo/ProjectRepository.kt b/backend/src/main/java/com/nestapp/mongo/ProjectRepository.kt index 3980604..64a5192 100644 --- a/backend/src/main/java/com/nestapp/mongo/ProjectRepository.kt +++ b/backend/src/main/java/com/nestapp/mongo/ProjectRepository.kt @@ -1,11 +1,13 @@ package com.nestapp.mongo import com.mongodb.client.model.Filters +import com.mongodb.client.model.Sorts import com.mongodb.kotlin.client.coroutine.MongoClient import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.toList import org.bson.codecs.pojo.annotations.BsonId import org.bson.types.ObjectId +import java.util.Date class ProjectRepository( private val client: MongoClient @@ -20,7 +22,9 @@ class ProjectRepository( suspend fun getProjects(): List { val collection = database.getCollection(collectionName = "projects") - return collection.find().toList() + return collection.find() + .sort(Sorts.descending("createdAt")) + .toList() } suspend fun getProject(slug: String): ProjectDatabase { @@ -38,5 +42,6 @@ data class ProjectDatabase( val name: String, val files: List, val preview: String?, + val createdAt: Date?, ) diff --git a/backend/src/main/java/com/nestapp/nest/PolygonGenerator.kt b/backend/src/main/java/com/nestapp/nest/PolygonGenerator.kt index 9eabe7c..ba2cbaa 100644 --- a/backend/src/main/java/com/nestapp/nest/PolygonGenerator.kt +++ b/backend/src/main/java/com/nestapp/nest/PolygonGenerator.kt @@ -6,9 +6,7 @@ import java.awt.geom.Point2D class PolygonGenerator { - fun getMergedAndCombinedPolygons(rawEntities: List, tolerance: Double): List { - val entities = moveAllEntityToPositiveCoordinates(rawEntities) - + fun getMergedAndCombinedPolygons(entities: List, tolerance: Double): List { val closedPolygons = mutableListOf() val closedEntities = entities.filter { it.isClose() } @@ -29,23 +27,18 @@ class PolygonGenerator { val mergedPolygons = mergePolygons(closedPolygons.sortedByDescending { area(it.points) }) - return mergedPolygons.map { mutableClosePolygon -> - ClosePolygon( - removeNearDuplicates(mutableClosePolygon.points, tolerance), + return mergedPolygons.mapNotNull { mutableClosePolygon -> + val points = removeNearDuplicates(mutableClosePolygon.points, tolerance) + if (points.size < 3) { + return@mapNotNull null + } + return@mapNotNull ClosePolygon( + points, mutableClosePolygon.entities ) } } - private fun moveAllEntityToPositiveCoordinates(rawEntities: List): List { - val paths = rawEntities.map { it.toPath2D() } - - val minX = paths.minOfOrNull { it.bounds2D.minX } ?: 0.0 - val minY = paths.minOfOrNull { it.bounds2D.minY } ?: 0.0 - val entities = rawEntities.map { it.translate(-minX, -minY) } - return entities - } - fun convertEntitiesToPolygons(entities: List, tolerance: Double): List> { val closedPolygons = mutableListOf() diff --git a/backend/src/main/java/com/nestapp/nest/jaguar/JaguarRequest.kt b/backend/src/main/java/com/nestapp/nest/jaguar/JaguarRequest.kt index 7a63402..7d3931c 100644 --- a/backend/src/main/java/com/nestapp/nest/jaguar/JaguarRequest.kt +++ b/backend/src/main/java/com/nestapp/nest/jaguar/JaguarRequest.kt @@ -4,10 +4,12 @@ import com.nestapp.nest.ClosePolygon import com.nestapp.nest.polygonOffset import io.ktor.client.HttpClient import io.ktor.client.call.body +import io.ktor.client.plugins.timeout import io.ktor.client.request.post import io.ktor.client.request.setBody import io.ktor.http.ContentType import io.ktor.http.contentType +import java.util.concurrent.TimeUnit sealed class NestResult { @@ -121,5 +123,4 @@ class JaguarRequest( ) return request } - } diff --git a/backend/src/main/java/com/nestapp/project/ProjectMaker.kt b/backend/src/main/java/com/nestapp/project/ProjectMaker.kt index 4a8f530..cae4663 100644 --- a/backend/src/main/java/com/nestapp/project/ProjectMaker.kt +++ b/backend/src/main/java/com/nestapp/project/ProjectMaker.kt @@ -7,6 +7,7 @@ import com.nestapp.mongo.ProjectDatabase import com.nestapp.mongo.ProjectRepository import com.nestapp.nest.PolygonGenerator import org.bson.types.ObjectId +import java.util.Date import java.util.Locale class ProjectMaker( @@ -61,6 +62,7 @@ class ProjectMaker( projectSlug = slug, preview = previewFile?.let { "files/projects/$slug/media/preview.png" }, files = dxfFileBytes.map { (fileName, _) -> fileName.substringBeforeLast(".") }, + createdAt = Date(), ) )