Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
899e2cea97 |
@ -9,6 +9,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -50,8 +52,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 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"},
|
||||
{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"},
|
||||
}
|
||||
|
||||
var tilePatterns = []PatternOption{
|
||||
@ -59,7 +61,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 degrees 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° 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{
|
||||
@ -522,8 +524,8 @@ func buildCompactFloorPrompt(floor FloorOption, pattern PatternOption, room *Roo
|
||||
if floor.FloorDescription != "" {
|
||||
details = append(details, "目录材质描述:"+floor.FloorDescription)
|
||||
}
|
||||
if floor.SizeLabel != "" || (floor.WidthIn > 0 && floor.LengthIn > 0) {
|
||||
details = append(details, compactSizeInstruction(floor))
|
||||
if sizeRule := compactSizeInstruction(floor, pattern); sizeRule != "" {
|
||||
details = append(details, sizeRule)
|
||||
}
|
||||
if floor.ImageURL != "" {
|
||||
details = append(details, "产品图是唯一材质参考:锁定基础颜色、纹理、纹路、光泽、材质类型;不要重新美化或改色。")
|
||||
@ -544,14 +546,85 @@ func buildCompactFloorPrompt(floor FloorOption, pattern PatternOption, room *Roo
|
||||
)
|
||||
}
|
||||
|
||||
func compactSizeInstruction(floor FloorOption) string {
|
||||
func compactSizeInstruction(floor FloorOption, pattern PatternOption) string {
|
||||
width, length, ok := floorDimensions(floor)
|
||||
if !ok {
|
||||
if pattern.Code == 8 {
|
||||
return "尺寸规则:这是特殊形状砖,按产品图保持真实特殊形状和缝隙结构;不要改成方砖或普通长方形砖。"
|
||||
}
|
||||
if floor.SizeLabel != "" {
|
||||
return "尺寸规则:使用所选尺寸 " + floor.SizeLabel + ";只调整板/砖大小和缝距,不改变材质颜色和纹理。"
|
||||
}
|
||||
if floor.WidthIn > 0 && floor.LengthIn > 0 {
|
||||
return fmt.Sprintf("尺寸规则:每片 %.1f\" x %.1f\";只调整板/砖大小和缝距,不改变材质颜色和纹理。", floor.WidthIn, floor.LengthIn)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func compactProductNameGuard(floor FloorOption) string {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user