Compare commits

..

1 Commits

Author SHA1 Message Date
be38d1b679 Merge pull request 'dev' (#2) from dev into main
Reviewed-on: #2
2026-07-27 08:12:45 +00:00

View File

@ -9,8 +9,6 @@ import (
"net/http"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
@ -52,8 +50,8 @@ type RoomOption struct {
var woodPatterns = []PatternOption{
{Code: 1, Name: "直铺工字拼Straight Lay", Category: "wood", Pattern: "planks running from bottom-left toward top-right of the image, joints staggered randomly, at least 6 inch offset between rows"},
{Code: 2, Name: "横铺 Horizontal Lay", Category: "wood", Pattern: "planks running horizontally left to right, parallel to the bottom edge of the image, joints staggered randomly, at least 6 inch offset"},
{Code: 3, Name: "人字 Herringbone", Category: "wood", Pattern: "ALL planks must be IDENTICAL width - no piece may appear narrower. Planks at 90° forming continuous zigzag V-lines from bottom-left to top-right of the image. At far distance, planks remain distinct with visible seams - NOT merging into a solid mass."},
{Code: 4, Name: "鱼骨 Chevron", Category: "wood", Pattern: "planks with 45° mitered ends forming continuous V-points aligned from bottom-left to top-right of the image"},
{Code: 3, Name: "人字 Herringbone", Category: "wood", Pattern: "ALL planks must be IDENTICAL width - no piece may appear narrower. Planks at 90 degrees forming continuous zigzag V-lines from bottom-left to top-right of the image. At far distance, planks remain distinct with visible seams - NOT merging into a solid mass."},
{Code: 4, Name: "鱼骨 Chevron", Category: "wood", Pattern: "planks with 45 degree mitered ends forming continuous V-points aligned from bottom-left to top-right of the image"},
}
var tilePatterns = []PatternOption{
@ -61,7 +59,7 @@ var tilePatterns = []PatternOption{
{Code: 6, Name: "工字铺1/2错缝Running Bond", Category: "tile", Pattern: "rows parallel to bottom edge of image, each row offset 50% from previous, horizontal grout lines continuous, vertical grout lines staggered"},
{Code: 7, Name: "三七错铺 1/3 Offset", Category: "tile", Pattern: "rows parallel to bottom edge of image, each row offset exactly 33% of tile length, every third row aligns"},
{Code: 8, Name: "六边形 Hexagonal", Category: "tile", Pattern: "six-sided tiles interlocked in honeycomb mesh, flat edges horizontal (parallel to bottom edge of image), grout follows hexagonal edges"},
{Code: 9, Name: "斜铺60度对角Diagonal", Category: "tile", Pattern: "tiles rotated 60° to the image frame, grout lines run diagonally at 60 and 150 degrees to the bottom edge, no lines parallel to image edges"},
{Code: 9, Name: "斜铺60度对角Diagonal", Category: "tile", Pattern: "tiles rotated 60 degrees to the image frame, grout lines run diagonally at 60 and 150 degrees to the bottom edge, no lines parallel to image edges"},
}
var roomOptions = []RoomOption{
@ -524,8 +522,8 @@ func buildCompactFloorPrompt(floor FloorOption, pattern PatternOption, room *Roo
if floor.FloorDescription != "" {
details = append(details, "目录材质描述:"+floor.FloorDescription)
}
if sizeRule := compactSizeInstruction(floor, pattern); sizeRule != "" {
details = append(details, sizeRule)
if floor.SizeLabel != "" || (floor.WidthIn > 0 && floor.LengthIn > 0) {
details = append(details, compactSizeInstruction(floor))
}
if floor.ImageURL != "" {
details = append(details, "产品图是唯一材质参考:锁定基础颜色、纹理、纹路、光泽、材质类型;不要重新美化或改色。")
@ -546,85 +544,14 @@ func buildCompactFloorPrompt(floor FloorOption, pattern PatternOption, room *Roo
)
}
func compactSizeInstruction(floor FloorOption, pattern PatternOption) string {
width, length, ok := floorDimensions(floor)
if !ok {
if pattern.Code == 8 {
return "尺寸规则:这是特殊形状砖,按产品图保持真实特殊形状和缝隙结构;不要改成方砖或普通长方形砖。"
}
func compactSizeInstruction(floor FloorOption) string {
if floor.SizeLabel != "" {
return "尺寸规则:使用所选尺寸 " + floor.SizeLabel + ";只调整板/砖大小和缝距,不改变材质颜色和纹理。"
}
return ""
}
shortSide, longSide := width, length
if shortSide > longSide {
shortSide, longSide = longSide, shortSide
}
ratio := longSide / shortSide
sizeText := formatDimensionPair(width, length)
if ratio <= 1.08 {
return fmt.Sprintf("尺寸规则:每块砖必须是 %s 正方形,真实长宽比 %s。砖缝网格应形成接近 1:1 的方砖;只调整板/砖大小和缝距,不改变材质颜色和纹理。", sizeText, aspectRatioText(shortSide, longSide))
}
return fmt.Sprintf("尺寸规则:每块砖必须是 %s 长方形,真实长宽比 %s。近处可见的完整砖块也必须明显是长方形长边约为短边的 %.2g 倍,不得变成接近正方形;砖缝网格必须形成同样比例的长方形砖块。只调整板/砖大小和缝距,不改变材质颜色和纹理。", sizeText, aspectRatioText(shortSide, longSide), ratio)
}
func floorDimensions(floor FloorOption) (float64, float64, bool) {
if floor.WidthIn > 0 && floor.LengthIn > 0 {
return floor.WidthIn, floor.LengthIn, true
return fmt.Sprintf("尺寸规则:每片 %.1f\" x %.1f\";只调整板/砖大小和缝距,不改变材质颜色和纹理。", floor.WidthIn, floor.LengthIn)
}
text := strings.Join([]string{floor.SizeLabel, floor.Name}, " ")
re := regexp.MustCompile(`(?i)(\d+(?:\.\d+)?)\s*(?:x|×|-|by)\s*(\d+(?:\.\d+)?)`)
match := re.FindStringSubmatch(text)
if len(match) != 3 {
return 0, 0, false
}
width, err1 := strconv.ParseFloat(match[1], 64)
length, err2 := strconv.ParseFloat(match[2], 64)
if err1 != nil || err2 != nil || width <= 0 || length <= 0 {
return 0, 0, false
}
return width, length, true
}
func formatDimensionPair(width, length float64) string {
return fmt.Sprintf("%s x %s 英寸", formatDimension(width), formatDimension(length))
}
func formatDimension(v float64) string {
if v == float64(int(v)) {
return fmt.Sprintf("%d", int(v))
}
return fmt.Sprintf("%.1f", v)
}
func aspectRatioText(shortSide, longSide float64) string {
ratio := longSide / shortSide
bestNumer, bestDenom := 1, 1
bestErr := ratio - 1
if bestErr < 0 {
bestErr = -bestErr
}
for denom := 1; denom <= 12; denom++ {
numer := int(ratio*float64(denom) + 0.5)
if numer < 1 {
numer = 1
}
err := ratio - float64(numer)/float64(denom)
if err < 0 {
err = -err
}
if err < bestErr {
bestErr = err
bestNumer = numer
bestDenom = denom
}
}
return fmt.Sprintf("%d:%d", bestDenom, bestNumer)
return ""
}
func compactProductNameGuard(floor FloorOption) string {